feat: one Set Password operation over the delivery queue; Synchronise Password withdrawn (#1635, layer 3 of 3) - #1639
Open
JayVDZ wants to merge 7 commits into
Conversation
…d a shared delivery core (#1635) Set Password and Synchronise Password converge on PasswordSynchronisationServer.SetPasswordAsync(SetPasswordRequest): Targets null propagates to every Connected System configured for Password Synchronisation (unchanged behaviour, Origin Propagated, EnableAccount never carried); a list of Connected System Object ids queues one Explicit row per named account, validated before anything is recorded, with the administrator's enable decision and the system's time to live, needing no configuration and not held by a paused one (decision D1). Both share one Activity shape and coalesce onto each other by person and system. PendingPasswordChange gains Origin and EnableAccount (migration AddPasswordChangeOrigin; existing rows are Propagated). The lane claims and expires explicit rows only over an unconfigured or paused system, resolves an explicit row's account from its own id and parks it when that account is gone, retries under ConnectedSystemPasswordSynchronisation defaults where no configuration exists, and builds a Connector only once something is claimed. The due-systems, outlook, summary and header reads treat an explicit row as due wherever it is; GetChangeOutcomesAsync never reports one as Held. The open, check, set, classify, close sequence is extracted once into PasswordDeliveryCore and used by the lane, the initial-password pass (a throwing Connector is now a transient retry there rather than an escaping exception) and the interim immediate path. ConnectedSystemServer's set-password members stay as shims for the controller and Razor callers the web layer still compiles against, marked for that layer's rewrite. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The person page's Password Synchronisation and Actions tabs become one Administrator-gated Password tab: an attention strip for parked or expired changes with Retry, the Set Password card with the capable-account count, Still to be delivered with per-row Retry and Stop trying, and Recent password changes with a Set or Propagated kind chip. The tab's data loads on first activation of its slug (NavigableMudTabs now raises ActivePanelSlugChanged); only the badge count is read with the page. SetPasswordDialog keeps its composition and submits through PasswordSynchronisationServer.SetPasswordAsync with the ticked accounts as explicit targets. Its result stage is driven by the outcome waiter: one row per Connected System reading Set, Retrying (next attempt, Stop trying) or Parked (the target's words, guidance, Try another password), with the storage promise reworded per decision D4. The Connected System Object page uses the same dialog and operation with one target. The Synchronise Password dialog, the Actions tab and the progress rail are removed. Application layer, in support: SetPasswordAsync records the change's origin on the parent Activity's TargetContext and the password history projects it back as PasswordSynchronisationEvent.Origin (null for older Activities), and PasswordChangeTargetOutcome carries the queue row's FailureReason so the dialog can choose remediation guidance. Service Health cards: the footer's separator dot is drawn in the column gap and clipped at a line start so a wrap never opens with a dot, and an unhealthy card that was idle fills its condition slot with its last heartbeat. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hronise Password withdrawn (#1635) REST: POST /api/v1/metaverse/objects/{id}/password is now SetMetaverseObjectPassword, taking password, optional connectedSystemObjectIds (omitted = every Connected System configured for Password Synchronisation), expiryBehaviour, enableAccount (named accounts only) and wait (0 to 30, default 10 with named accounts, 0 when propagating). The response is the per-target outcome shape plus origin; 200 when settled, 202 when not, 400 for validation and for the core's ArgumentException, 404 for the person. The account-scoped endpoint is a one-target wrapper over the same operation with the same response, and answers 404 when the object is not joined to a Metaverse Object. PowerShell: Set-JIMMetaverseObjectPassword gains the propagate default (D5), -Wait and four parameter sets (Named/Propagate x Supplied/Generated) with -EnableAccount only in the Named sets; -AllAccounts and Sync-JIMMetaverseObjectPassword are removed. Set-JIMConnectedSystemObjectPassword returns the same outcome shape, waits by default, gains -Wait and loses -PassThru. A Parked target is also a non-terminating error carrying the result. Docs: one operation with two target modes in docs/concepts/passwords.md, D4 wording for what JIM holds and for how long, the person's Password tab, cmdlet pages and the API overview updated, Sync- section removed. Changelog amended so 0.15.0 reads as the final shape. Scenario 20 moved to the new cmdlet. Plan carries a Deviations section. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…son on the REST outcome (#1635) The web and API now call SetPasswordAsync directly, so the ConnectedSystemServer shims, the QueuePasswordChangeAsync forwarders, MultiAccountPasswordSetResult and AccountPasswordSetOutcome go, with the two fixtures that existed only for them; the fan-out tests exercise the propagate mode of the one operation. The per-target failure reason the portal uses for its guidance is now on the REST response and the cmdlet output too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ssword history as a timeline (#1635) Service Health cards carry the uptime on the heartbeat line and move host, version and instance behind a per-card details control, each value in monospace with a copy button; the version-skew chip stays on the card's face beside the pill and repeats on the Version row. The status pill becomes the shared .jim-status-pill vocabulary (ok, warn, err, neutral). The person page's recent password changes become a day-grouped timeline: one entry per change with the time, kind chip and initiator, a status pill per Connected System, and words only where a system refused the change or is still owed it, with Retry and Stop trying on that line. The derivation, including which change a live queue row belongs to, lives in PasswordHistoryTimelineModel with its own unit tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Layer 3 of #1635 (plan:
engineering/plans/done/PASSWORD_PIPELINE_CONVERGENCE.md), stacked on #1638 and #1636. Closes #1635 when the stack lands.PasswordSynchronisationServer.SetPasswordAsync(SetPasswordRequest)replaces both the immediate set-password path and the separate synchronise path. A request names accounts (Connected System Object ids) or names none, meaning every Connected System configured for Password Synchronisation. Both origins write the same queue rows, the same Activity shape (parent per change, child per system) and are delivered by the Layer 2 service.AddPasswordChangeOrigin.PasswordDeliveryCore, used by the delivery lane and by initial password provisioning. The immediateConnectedSystemServerset-password methods, the queue forwarders and their result DTOs are gone.SetPasswordDialogkeeps its composition (picker, generate, copy while masked, expiry, enable) and its result stage now follows the queue live: Set, Retrying with next attempt and Stop trying, Parked with the target's words and guidance, Try another password. Synchronise Password and the Actions tab are removed. The account page uses the same dialog with one target.POST /api/v1/metaverse/objects/{id}/passwordis Set Password:password, optionalconnectedSystemObjectIds,expiryBehaviour(defaults differ by mode),enableAccount(named accounts only),wait(default 10 s with accounts, 0 when propagating); per-target outcome includingfailureReason, 200 settled or 202. The account-scoped endpoint is a one-target wrapper with the same response.Set-JIMMetaverseObjectPasswordgains-ConnectedSystemId <int[]>naming accounts, the propagate default when none is named (decision D5),-Wait, and the outcome shape;-AllAccountsandSync-JIMMetaverseObjectPasswordare withdrawn;Set-JIMConnectedSystemObjectPasswordreturns the same shape.docs/concepts/passwords.mdsay so; the "two ways to give somebody a password" section is now one operation with two target modes.Verification
dotnet build JIM.sln: 0 warnings, 0 errors;dotnet test JIM.sln: green (see checks). RequiresPostgres fixtures for claims, origins and outcomes run against a scratch database.Lint-Changelog.ps1andLint-DocExamples.ps1pass.Set-JIMMetaverseObjectPassword.🤖 Generated with Claude Code