Repository navigation
Release v0.4.0
Added
- Legal-terms acceptance is now resolved authoritatively during command execution:
LegalAcceptanceEvidence.Resolvereads the host'sILegalDocumentSourceexactly once per command and uses that single read for both rejecting the command and building theLegalTermsAcceptedevent, so the version recorded as evidence is always the version this resolution itself just confirmed - never merely the value the client submitted. (#15) - A command that claims legal-terms acceptance while the host has no document source configured is now rejected instead of silently accepted - previously a client could set
acceptedLegalTerms: truewith nothing configured and an unsolicitedLegalTermsAcceptedevent would still be appended. The shared preflightLegalTermsRulesgained the mirror rule so the wizard's eager/validatecall surfaces the same rejection early. (#15) AcceptInvitation,SetupOrganization, andRegisterOrganizationnow validateFirstName/MiddleName/LastNamethrough sharedPersonalNameValidationrules: diacritics, combining marks, non-Latin scripts, apostrophes, hyphens, and the zero-width joiner/non-joiner some scripts need to render correctly are accepted, while Unicode control characters and text-direction-override characters are rejected, and each field is bounded to 100 characters (mirrored automatically into the generated client-side validator, so client and server agree on the limit). (#15)- The three onboarding wizards now reset the legal-acceptance checkbox whenever the host publishes a new document version while a user is mid-flow, forcing a fresh review of the new text without touching the name fields already filled in.
Fixed
- Fixed a client-side bug where the legal-acceptance checkbox and the accepted-version field could be silently reset by CommandForm's reactive value re-application on any unrelated re-render (e.g. opening the terms/privacy dialog) -
initialValuesandcurrentValuespassed toCommandStepperwere recreated on every render, and a defined value ininitialValuesalways wins overcurrentValuesfor the same key, so the previously-hardcodedacceptedLegalVersion: ''baseline was reasserted over the real version on every reactive pass.
Summary
WP-04 of the onboarding-adoption epic (#10). Distinguishes "successfully unconfigured" from "configured" for legal consent, and makes the recorded evidence and the execution-time decision the same read rather than two independently-resolved ones - closing the gap where a client's claimed acceptance was trusted for the emitted event without being re-confirmed against the document source at execution time. Also strengthens FirstName/MiddleName/LastName validation to be inclusive of real names worldwide while still bounding length and rejecting characters with no legitimate place in a personal name.
Deferred, with reasons - all gated on #11 (WP-00, not yet resolved):
- Mononym / making a first-or-last name optional. The issue calls this out explicitly as "requires a product decision" - implementing it here would mean inventing product policy this PR isn't positioned to decide.
- Host-integrator documentation of a supported-provider/recipient matrix, locale-triggered renewed-review policy, and version-history ownership. These describe cross-host contractual guarantees (
#11's "legal-history ownership, required structured-name compatibility, claim comparison/scope" bullet) rather than in-repo behavior; writing them down as fact ahead of that decision would misrepresent them as settled. - A tracked documentation render/link verifier. The issue notes none exists in this repo today; standing one up is a separate, repo-wide tooling effort, not a legal/profile behavior change.
- Full "disappearing mid-flow" reconciliation. If a host's document disappears entirely between page load and submit while a client still holds a stale
acceptedLegalTerms: true, the command is rejected (same authoritative check as unsolicited acceptance) rather than either fabricating consent or silently dropping the claim and proceeding. A more graceful in-place recovery (e.g. auto-clearing just that field and re-prompting without a full page reload) is a frontend UX refinement beyond this PR's scope, not a correctness gap - no consent is ever fabricated or silently lost.
Also found and filed upstream: Cratis/Arc#2658 - the ARC0013 analyzer false-positives on RuleFor selectors that reference a concept's own static member (e.g. MiddleName.NotSet) rather than actually dereferencing a possibly-null instance. Worked around locally in all three validators (see the code comments) by comparing against null and casting instead of coalescing against the sentinel.
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) - 131/131 passing, including new specs for:LegalAcceptanceEvidence.Resolve(unconfigured with/without a claimed acceptance, configured and accepted with the current version, not accepted, stale version), the preflight rule's unsolicited-acceptance rejection, and end-to-end coverage through all three onboarding commands (accepted-with-current-version appends the event with the resolved version/tenant/provider/subject; unsolicited claims are rejected with no events appended; the existing "values are valid" specs now also assert noLegalTermsAcceptedleaks out when nothing was accepted) plusPersonalNameValidation(diacritics/hyphens/apostrophes/non-Latin accepted; a control character, a text-direction-override character, and an over-length name rejected) -
yarn lint:ci- clean -
yarn compile(tsc) - clean -
yarn test(frontend) - 37/37 passing