Skip to content

Release v0.4.2

Choose a tag to compare

@github-actions github-actions released this 07 Sep 00:20
a76f7ec

Fixed

  • All three onboarding wizards (UserSetupPage, OrganizationSetupPage, RegistrationPage) no longer dead-end on a reload, a second tab, or returning later: each now derives whether to show the form or a waiting/recovering state from durable status rather than a flag that only the original submitting tab ever knew about. Previously a reload after submitting - but before publication reached Ante's outbox - showed the form again, risking a rejected duplicate submission. (#17)
  • RegistrationPage no longer loses track of an in-flight or already-published registration on reload: it previously minted a brand-new id on every mount (useMemo(() => Guid.create(), [])), so a reload queried status for an id that had never recorded anything and always showed the form again. (#17)
  • UserSetupPage's timedOut branch - documented in #16 as "reserved for future use, not... a shipped behavior" because nothing on the backend ever produced it - now has real, working behavior, applied identically to all three wizards. (#17)
  • Resolving the host redirect URL is now wrapped so a malformed HostAppUrl configuration surfaces as the existing "could not determine where to take you next" message instead of an uncaught exception - setup has already published by that point, so nothing about the person's submission is lost. (#17)

Added

  • A Recorded status value on OrganizationSetupAcceptanceStatus and UserSetupAcceptanceStatus, between Pending and Accepted: a client that has submitted but is still waiting on publication now reads distinctly from one that never submitted at all, so it is never safe (or possible) to resubmit and never a dead end. (#17)
  • A local "still processing" recovery phase, shared across all three wizards: after a bounded wait with no confirmation, the wizard offers "Check again" (resets the local wait without creating a new operation or restarting the flow) and directs to support - it never claims failure, and a later Accepted reading always wins and completes the hand-off automatically. (#17)
  • RegistrationPage persists a versioned, opaque registration-id pointer per browser tab (sessionStorage) so a reload or a later return resumes the same durable registration - never a profile draft, identity claim, legal content, or token. Two tabs opened to /register each get an independent registration. A "Register a different organization" action supports deliberately starting a new one. (#17)

Changed

  • OrganizationSetupStatusSubscriptions / UserSetupStatusSubscriptions now seed every (re)connecting client's live status from a fresh durable read instead of always starting Pending, and only ever move a client's observed status forward (Pending → Recorded → Accepted), never backward - a stale, lagging read racing behind a durable publication another tab already observed can no longer regress that tab's view.

Summary

WP-06 of the onboarding-adoption epic (#10), building on #16's Recorded/Published durable progress. Closes the gap between "durable evidence exists" and "the wizard actually resumes into it": recovery now derives the render phase (form / waiting / timed-out) from status for all three journeys, and the hand-off to the host stays gated on Accepted (full publication) exactly as before - now proven to survive a recovery mid-wait, not only the original submitting tab.

Deferred, with reasons (flagging for #11 / a follow-up):

  • Owner-scoped authorization on the status queries - already flagged as deferred in #16 and unchanged here. StatusForInvitation still accepts any signed-in caller's id with no ownership check, unlike the commands themselves. This PR's recovery phase reads through the same unauthenticated query, so it inherits the gap rather than introducing a new one, but closing it needs the same self-service-registration ownership design #16 deferred to #11.
  • Real browser verification of the full acceptance-criteria list (two tabs, disconnect/reconnect, blocked navigation, late success races) - covered here at the unit level (OnboardingRecoveryState's phase/timeout engine, the tri-state status subscriptions' monotonic seeding, RegistrationOperation's persistence) per this repo's established frontend/backend spec conventions; there is no browser-automation harness in this repo to exercise the actual multi-tab/network-drop scenarios end-to-end.
  • Account switching / reauthentication controls - out of scope per #17 itself pending #11's decision on session invalidation/rebinding; not touched.
  • Cross-replica live status push - already flagged as deferred in #16 and unchanged here; durable re-reads on reconnect still make this safe, just not instantaneous across replicas.

Test plan

  • dotnet build -c Debug (Ante) - 0 warnings, 0 errors; proxies regenerated
  • dotnet build -c Release -p:CratisProxiesOutputPath= (Ante) - 0 warnings, 0 errors
  • dotnet test (Ante) - 187/187 passing, including new coverage for the tri-state status derivation and its monotonic forward-only seeding, for both the join-tenant and organization-setup/registration flows
  • yarn test (Ante) - 66/66 passing, including new coverage for OnboardingRecoveryState (phase transitions, timeout arming/clearing, late-success-wins), RegistrationOperation (persistence, versioning, clearing), and a destination-failure case for resolveHostAppRedirectUrl
  • yarn lint:ci - clean
  • yarn compile (tsc) - clean
  • yarn build (vite) - clean

🤖 Generated with Claude Code

https://claude.ai/code/session_014jfWkrU6BPcC8T3gFNAc8z