feat: add browser auth shell
This commit is contained in:
@@ -42,6 +42,33 @@ a module entrypoint, or starts a server. Real, working (non-throwing) module fix
|
||||
production module-runtime startup/shutdown ordering and cleanup against a mocked pool/Better
|
||||
Auth/server — see [Authorization](authorization.md#tests).
|
||||
|
||||
Phase 7B pass 1 adds browser-authentication evidence
|
||||
([ADR 0034](../architecture/decisions/0034-host-owned-browser-authentication.md)). API tests pin the
|
||||
two exact browser-boundary exceptions. Any body-bearing successful `2xx` from
|
||||
`POST /api/auth/sign-in/email` preserves Better Auth's `Set-Cookie` and status but returns fixed
|
||||
`{"ok":true}`, with no token/user body. `/api/auth/get-session`, `/api/auth/list-sessions`,
|
||||
`/api/auth/update-session`, and `/api/auth/change-password` each receive the identical sanitized
|
||||
`404` without invoking the identity handler; failures and every other supported auth route retain
|
||||
their native semantics. The live browser transport additionally proves the host-only cookie and
|
||||
that no token, session, user, or email appears in the sign-in body.
|
||||
|
||||
Shell protocol and React tests cover principal-first anonymous/authenticated/failure states; the
|
||||
labelled email/password form and keyboard submission; autocomplete, pending state, and same-tick
|
||||
duplicate suppression; password clearing; fixed credential-versus-service errors; no credential or
|
||||
raw exception logging; fresh principal and navigation resolution after login; sign-out followed by
|
||||
principal resolution; and retry without a full-page reload.
|
||||
|
||||
The same shell suites exercise session transitions under repeated timing: active module cleanup and
|
||||
realtime teardown on sign-out/verified expiry; stale attempts after unmount; platform bootstrap
|
||||
`401` mapping directly to unauthenticated; and deduplicated principal revalidation for both module
|
||||
`401` and `403`. They prove an authenticated recheck preserves the module's original response,
|
||||
session, and mounted UI; an anonymous recheck unmounts once and shows login; a revalidation failure
|
||||
is a sanitized host failure; and a response from an already-unmounted frame cannot overwrite a newer
|
||||
transition. Return/callback input is not part of the browser contract, and tests pin that external,
|
||||
protocol-relative, backslash-prefixed, and scheme-bearing values cannot become navigation.
|
||||
Modularity checks keep authentication out of the module UI SDK/context and Dashboard login code out
|
||||
of the separate display bundle.
|
||||
|
||||
`pnpm verify` is intentionally Docker-free. It never plans or applies migrations against a live
|
||||
database.
|
||||
|
||||
@@ -79,8 +106,9 @@ A second dedicated suite (`apps/api/tests/api-http.integration.ts`, included in
|
||||
`pnpm test:migrations:integration` run) starts the real `apps/api` HTTP server against a freshly
|
||||
migrated disposable database and exercises it with real HTTP requests: public sign-up (with no
|
||||
automatic session, per `autoSignIn: false`), explicit sign-in producing a host-only
|
||||
`HttpOnly`/`SameSite=Lax`/secure session cookie, `/api/v1/principal` for both the authenticated and
|
||||
anonymous shapes, sign-out actually invalidating the session, a malformed or missing cookie
|
||||
`HttpOnly`/`SameSite=Lax`/secure session cookie and fixed `{"ok":true}` body containing no token,
|
||||
`/api/v1/principal` for both the authenticated and anonymous shapes, sign-out actually invalidating
|
||||
the session, a malformed or missing cookie
|
||||
resolving as anonymous, duplicate sign-up creating no second identity row, two distinct accounts
|
||||
producing identical principal shapes with no elevation and no owner/role/permission data at the
|
||||
database level, no plaintext password ever stored, the exact 8–128 password-length boundary (7
|
||||
@@ -90,6 +118,13 @@ outage during principal resolution producing a sanitized `503` rather than a fal
|
||||
starting the API against an unmigrated database creating no tables at all, and a clean listener/pool
|
||||
shutdown.
|
||||
|
||||
The browser-authentication chain in that live suite also creates a development identity, invokes
|
||||
Core's real single-use platform-owner bootstrap for that existing id, signs in through the real HTTP
|
||||
transport, presents the returned cookie to `/api/v1/principal`, and reaches protected Dashboard
|
||||
navigation with the owner authority. It proves composition across identity, authorization, and the
|
||||
Dashboard resource; because production signup is prohibited, it deliberately does **not** claim to
|
||||
prove a production first-user enrollment path.
|
||||
|
||||
A dedicated group within that suite proves session-store readiness against the real database rather
|
||||
than a mock, since that is the only place a broken store looks exactly like an anonymous request: a
|
||||
request carrying no cookies and one carrying only an unrelated cookie both resolve as anonymous
|
||||
|
||||
Reference in New Issue
Block a user