3.2 KiB
3.2 KiB
Web Foundations dogfood notes
This living note records concrete pressure discovered while Gamertan services adopt Web Foundations. It is implementation evidence, not a promise that every application concern belongs in the shared module.
Gamertan accounts and commerce
- The account email remains required and unique. Gamertan uses normalized email as the canonical login identifier and keeps username as a stable public identity. Until a mail package exists, the application must not describe an address as verified merely because it was entered during registration.
- Password authentication is sufficient for an ordinary customer base
session. Privileged application actions use an exact operation binding with
authwebauthn.BeginApprovalandFinishApproval; that is safer than a broad long-lived "elevated" session. A user without a passkey can use ordinary features but must enroll one before performing protected work. auth.Service.VerifyPasswordremains available for flows that truly require password plus passkey before session issuance.- Public registration exposed a cross-package transaction boundary. The
accountpackage now keeps an unusable bounded registration draft and makes recovery-code digests, personal organization, membership, owner binding, activation, audits, and an optional initial passkey one repository commit. A failed WebAuthn ceremony can be restarted, or an ordinary password account can finish without it, without persisting a partly privileged account. - Media belongs behind a storage-neutral interface with a hardened local adapter. Content workflow, references, and authorization remain application policy.
- Historical
authsqlite.Openstill migrates for compatibility. Applications with reviewed deployment gates useOpenWithOptionswith migration disabled, require the current schema at startup, and invokeMigrateonly from an explicit operator command. - Commerce remains a separately versioned nested module so payment-provider policy and catalog evolution do not enlarge the authentication core.
- Self-service enrollment exposed an authorization seam: completing a valid
ceremony and checking its user only after persistence is too late.
FinishRegistrationForUsernow consumes mismatched ceremonies and checks the application-authenticated user before storing a credential. - First-owner provisioning exposed another cross-package transaction boundary.
bootstrapnow commits the passkey-only user, enrollment digest, non-personal organization, membership, direct owner binding, and audits together. Applications must seed their owner role first and must write the returned raw token only to a newly created private file. - Recovery-code consumption alone is not a complete recovery path. The
restricted grant must survive an interrupted authenticator prompt yet be
consumed in the same transaction that stores the verified replacement
passkey and replacement code digests.
authrecovery.BeginPasskeyandFinishPasskeynow provide that boundary without creating an authenticated session; Gamertan keeps the raw grant only in a short-lived HttpOnly cookie.