Skip to content

feat(leder): Leder per worker - #1503

Merged
renemadsen merged 12 commits into
stablefrom
feat/leder-per-worker
Nov 5, 2026
Merged

renemadsen merged 12 commits into
stablefrom
feat/leder-per-worker

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Closes #1502

  • The Leder flag is stored per worker. It is keyed by the worker's SDK site, using Microting.EformBackendConfigurationBase 10.0.62 (LederAssignments.SiteId).
  • An admin can set or clear Leder on any worker, whatever its access: no login, Web/Arkiv off, or an admin login. Nothing else changes on save, and no access is switched on.
    • LederRequiresLogin, the automatic revoke and the "loses access" refusal are gone.
    • A non-admin still cannot change a Leder worker's e-mail or its login's username (H2). Moving between two unlisted addresses (blank and the placeholder) does not count as a change.
  • Who is a Leder: a login is a Leder when it is active and one of its live sites is flagged. ILederService takes the already-known IsActive and live site ids (LederLiveness) instead of knownLive. A tenant with no flagged site skips the SDK lookup.
  • Delete and list: deleting a worker revokes its site's flag. isLeader is true/false on every Medarbejdere row, from one query per list.
  • Old rows: rows written per login are converted once at startup to their workers' sites (LederLegacyConversionService). One failing row does not block the others, and a failure never stops the plugin loading.
  • Web:
    • The Leder toggle is shown to admins on every worker and is always enabled.
    • A Leder column (Ja/Nej, the Archive column's badges) replaces the chip, for every viewer.
    • Two hint keys are removed from all locales.
  • Playwright: zc is updated.

Deploy note: on a tenant that already runs the per-login Leder release (staging), an old pod's Medarbejdere list fails once per-site rows exist. The old base maps EformUserId as non-nullable. Roll that tenant with recreate, or accept the short gap until the old pod is gone.

Not run locally: the C# tests, Angular unit tests and Playwright run only in CI. Locally, only dotnet build was run.

🤖 Generated with Claude Code

renemadsen and others added 8 commits November 4, 2026 18:53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ges only (#1502)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he site (#1502)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ins (#1502)

- leader.helper: the toggle shows for admins on every worker; Ja/Nej cell helper.
- Worker dialog: the Leder toggle is always enabled; isLeader is sent only when changed.
- Medarbejdere: a Leder column with the Archive column's Ja/Nej badges replaces the chip.
- Every locale: the two disabled-toggle hints are dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…references from comments (#1502)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 05:50
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Legacy conversion can restore revoked permissions through partial or concurrent replay, new tests fail TypeScript excess-property checks, and Leder-only edits remain blocked for existing workers without e-mail or access.

3 open issues
What changed in this PR

Moves Leder assignments from logins to workers’ SDK sites, implementing #1502 across the backend configuration plugin and Angular worker interface.

Changes:

  • Updates storage, authorization, worker lifecycle handling, and startup conversion of legacy assignments.
  • Removes access-based toggle restrictions and adds a Leder Ja/Nej column for all viewers.
  • Updates backend, frontend, and Playwright coverage and removes obsolete translation keys.
File Description
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​LederService.cs Resolves Leder through active logins and flagged live sites.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​LederSaveRules.cs Removes access prerequisites while retaining login protection.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​LederMessages.cs Removes the login-required refusal key.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​LederLegacyConversionService.cs Adds startup conversion of legacy login assignments.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​LederAssignmentStore.cs Keys grants, revocations, and queries by site.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​Leder/​ILederService.cs Introduces the shared login-and-site liveness contract.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​BackendConfigurationAssignmentWorkerService/​BackendConfigurationAssignmentWorkerService.cs Updates deletion and list read-back for site flags.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​ArchiveAccess/​CallerSites.cs Adds worker-site resolution for legacy conversion.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​ArchiveAccess/​ArchiveAccessService.cs Passes resolved live sites to the Leder check.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Resources/​localization.json Removes obsolete login-required translations.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Infrastructure/​Models/​DeviceUserModel.cs Documents the revised worker flag contract.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Infrastructure/​Helpers/​BackendConfigurationAssignmentWorkerServiceHelper.cs Applies site-based save rules and flag writes.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​EformBackendConfigurationPlugin.cs Registers and invokes legacy conversion at startup.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​BackendConfiguration.Pn.csproj Updates the base dependency to 10.0.62.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederWorkerTestBase.cs Checks worker flags by site.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederWorkerLifecycleTests.cs Updates deletion, resignation, and rehire coverage.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederToggleTests.cs Covers site grants independent of login access.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederTestData.cs Updates service substitutes and returns both site identifiers.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederServiceTests.cs Tests flagged-site authorization and supplied liveness.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederSaveRulesTests.cs Revises pure-rule tests for unrestricted admin grants.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederMedarbejdereListTests.cs Tests boolean flag read-back on every worker row.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederLoginProtectionTests.cs Updates non-admin address protection coverage.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederLegacyConversionTests.cs Adds conversion and repeat-run coverage.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederAssignmentStoreTests.cs Tests site-keyed storage and legacy-row queries.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​LederArchiveGateTests.cs Uses flagged sites in archive authorization tests.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​ArchiveLocalizationTests.cs Removes the retired refusal expectation.
eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn.Integration.Test/​ArchiveAccessContextTests.cs Verifies live-site information reaches the Leder service.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​leder-i18n.spec.ts Checks removal of retired hints across locales.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​leder-i18n-keys.ts Separates active translation keys from retired hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​leader.helper.ts Simplifies toggle visibility and adds badge presentation.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​leader.helper.spec.ts Updates toggle, badge, and new-worker tests.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​components/​property-worker-table/​property-worker-table.component.ts Adds the Leder column and cell helper.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​components/​property-worker-table/​property-worker-table.component.html Replaces the name chip with a Ja/Nej cell.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​components/​property-worker-create-edit-modal/​property-worker-create-edit-modal.component.ts Removes access-driven toggle state management.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​modules/​property-workers/​components/​property-worker-create-edit-modal/​property-worker-create-edit-modal.component.html Removes the disabled-toggle hint.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​models/​device-users/​device-user.model.ts Documents site-based flags and informational login fields.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​ukUA.ts Removes obsolete Ukrainian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​svSE.ts Removes obsolete Swedish toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​slSL.ts Removes obsolete Slovenian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​skSK.ts Removes obsolete Slovak toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​roRO.ts Removes obsolete Romanian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​ptPT.ts Removes obsolete Portuguese toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​ptBR.ts Removes obsolete Brazilian Portuguese toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​plPL.ts Removes obsolete Polish toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​noNO.ts Removes obsolete Norwegian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​nlNL.ts Removes obsolete Dutch toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​lvLV.ts Removes obsolete Latvian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​ltLT.ts Removes obsolete Lithuanian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​itIT.ts Removes obsolete Italian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​isIS.ts Removes obsolete Icelandic toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​huHU.ts Removes obsolete Hungarian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​hrHR.ts Removes obsolete Croatian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​frFR.ts Removes obsolete French toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​fiFI.ts Removes obsolete Finnish toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​etET.ts Removes obsolete Estonian toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​esES.ts Removes obsolete Spanish toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​enUS.ts Removes obsolete English toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​elGR.ts Removes obsolete Greek toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​deDE.ts Removes obsolete German toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​da.ts Removes obsolete Danish toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​csCZ.ts Removes obsolete Czech toggle hints.
eform-client/​src/​app/​plugins/​modules/​backend-configuration-pn/​i18n/​bgBG.ts Removes obsolete Bulgarian toggle hints.
eform-client/​playwright/​e2e/​plugins/​backend-configuration-pn/​zc/​archive-leader.spec.ts Updates end-to-end coverage for per-worker Leder behavior.
eform-client/​playwright/​e2e/​plugins/​backend-configuration-pn/​BackendConfigurationPropertyWorkers.page.ts Adds row-scoped Leder badge assertions.

Review effort: Balanced

return 'disabled';
}
return 'enabled';
export function showLeaderToggle(row: RowWith<'canSetLeder'>): boolean {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6702761: the spec types those fixtures as worker rows (row() helper); the helper's parameter stays narrow.

Copilot AI balanced review requested due to automatic review settings November 5, 2026 05:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical flaws allow non-admins to bypass Leder identity protections through shared workers and let partially committed legacy conversions restore explicitly revoked access on restart.

4 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Preserve address and account state for Leder-only edits

eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Infrastructure/​Helpers/​BackendConfigurationAssignmentWorkerServiceHelper.cs:1408

Saving only Leder on an addressless worker still replaces its empty address with a placeholder and creates a login with a fallback group before reaching this flag write. That changes the worker's address and account state rather than only storing Leder. Preserve both for a Leder-only edit, and extend the no-address grant test to assert that the stored address and user count remain unchanged.

Medium severity Match legacy worker addresses using sanitizer semantics

eFormAPI/​Plugins/​BackendConfiguration.Pn/​BackendConfiguration.Pn/​Services/​ArchiveAccess/​CallerSites.cs:54

This raw address comparison loses legacy flags for workers whose stored address needs the sanitizer fallback. For example, a worker stored as jane@example.com is linked to the jane@example.com login by the existing save/list lookup, but this query finds no worker; the converter then permanently removes the legacy assignment without flagging its site. Resolve legacy workers using the same WorkerEmailSanitizer.Clean matching semantics before retiring the row, and cover a padded legacy address in the conversion tests.

Review effort: Balanced

…of the worker (#1502)

- The startup conversion locks each legacy row, re-reads it and skips it when another
  pod already retired it; its site grants and its retirement commit together, so a
  failure or a second pod cannot replay a grant over a later revoke.
- A non-admin cannot change the e-mail of a worker when any of the worker's live
  sites is a Leder, not only the site being edited.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 06:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A non-admin can rename a protected Leder login through a different, unflagged worker because the authorization check ignores sites associated with the resolved login’s current email.

2 open issues
3 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 5, 2026 06:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The startup authorization migration needs MariaDB CI validation of concurrent-start and rollback behavior, plus deployment-owner confirmation of the recreate rollout because old pods cannot read the new per-site rows.

2 open issues

Review effort: Balanced

…1502)

A login whose UserName drifted from its Email can be found by another
worker's address. A non-admin save or create through that worker would
rename the Leder's login; both are now refused when the login's own
e-mail resolves to a flagged live site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 06:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical authorization gap lets non-admins rename logins belonging to resigned workers through another address with a matching username because the protection excludes resigned workers.

2 open issues
1 resolved since last review

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 07:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed because inconsistent email normalization during startup conversion can silently and permanently lose a legacy Leder flag.

1 open issue
1 resolved since last review

Review effort: Balanced

@renemadsen
renemadsen merged commit c8622df into stable Nov 5, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants