feat: expose core identity transport
CI / verify (pull_request) Successful in 27s
CI / infrastructure-smoke (pull_request) Successful in 19s
CI / migration-smoke (pull_request) Successful in 26s

This commit is contained in:
ekklesia
2026-07-21 19:15:14 -05:00
parent 82fe338a8d
commit 91d8f5946f
33 changed files with 2672 additions and 224 deletions
+31 -15
View File
@@ -1,11 +1,13 @@
# Identity
Phase 4A establishes Core's identity foundation: a Core-owned Better Auth database schema, a
Phase 4A established Core's identity foundation: a Core-owned Better Auth database schema, a
first-class Core-owned migration source, minimal opaque-identity contracts, and an explicit Better
Auth construction boundary. It does not expose a sign-in endpoint, mount an HTTP handler, or make
any provider or enrollment decision. See
[ADR 0010](../architecture/decisions/0010-core-identity-and-better-auth-adoption.md) for the full
architectural decision; this page is the practical developer guide.
Auth construction boundary. Phase 4B built the HTTP transport on top of it — see
[API](api.md) and
[ADR 0011](../architecture/decisions/0011-identity-http-transport-and-public-enrollment.md) for
public registration, sign-in, and principal resolution over HTTP. This page covers the identity
foundation itself; see [ADR 0010](../architecture/decisions/0010-core-identity-and-better-auth-adoption.md)
for that architectural decision.
## Ownership
@@ -18,7 +20,8 @@ surface concern. Better Auth is an implementation detail contained entirely behi
cannot import `core` at all under `scripts/check-boundaries.ts`'s boundary matrix, regardless of
what Core exposes.
- **Surfaces will eventually authenticate through Core-exposed HTTP/API and client contracts**,
never by querying Better Auth's tables directly. No such Core API exists yet.
never by querying Better Auth's tables directly. `apps/api` (Phase 4B, see [API](api.md)) is that
transport for server-side/API consumers; no Dashboard, Website, or Mobile Surface exists yet.
- Better Auth's `user` row is an authentication identity, not the future church-person/profile
model. Church membership, ministry roles, contact history, attendance, permissions, and other
module-specific fields must never be added to the identity tables; a future, separately designed
@@ -117,8 +120,8 @@ required. It is part of `pnpm verify`.
## Required identity configuration
`createIdentityConfig` (`core/src/identity/config.ts`) validates three explicit values before
`core/src/identity/factory.ts` constructs Better Auth. This document intentionally contains no
real values — configure them per environment, never commit them:
`core/src/identity/runtime.ts`'s `createIdentityRuntime` constructs Better Auth. This document
intentionally contains no real values — configure them per environment, never commit them:
| Value | Requirement |
| --- | --- |
@@ -133,12 +136,25 @@ raises a sanitized `IdentityConfigError` carrying only a stable code, never the
Secret rotation (Better Auth's plural `secrets` list) and cross-subdomain cookies are deferred; see
ADR 0010.
## The identity runtime (Core's Better Auth transport boundary)
`@ekklesia/core/identity` publicly exports `createIdentityRuntime({config, db})`
(`core/src/identity/runtime.ts`), which constructs Better Auth explicitly and returns a frozen
`EkklesiaIdentityRuntime` exposing exactly two Fetch-standard capabilities:
`handleAuthRequest(request): Promise<Response>` (delegates directly to Better Auth's handler; its
normal responses, including its own error responses, pass through unmodified) and
`resolvePrincipal(headers): Promise<EkklesiaPrincipal>` (never silently downgrades a database
outage to an anonymous result — see ADR 0011 for exactly how). Neither method, nor anything else
exported from `@ekklesia/core/identity`, exposes `auth.api`, Better Auth's session/user types, the
Drizzle adapter, the raw database, a session token, or Better Auth configuration. `apps/api` is the
only current consumer of this boundary; see [API](api.md).
## What is not operational yet
No HTTP server or API route exists, Better Auth's handler is not mounted, and there is no sign-in
or sign-up endpoint, public registration, invitation flow, email delivery, password reset, email
verification, social or OAuth provider, passkey, magic link, two-factor authentication, or roles
and permissions model. **No user can authenticate through this repository yet.** The next expected
slice is identity HTTP transport and an explicit enrollment policy (for example, how the first
administrator account is created) — not a Dashboard Surface, which depends on that transport slice
existing first.
No email verification, password recovery, invitation flow, email delivery, social or OAuth
provider, passkey, magic link, two-factor authentication, or roles/permissions/platform-owner model
exists. Public registration, sign-in, principal resolution, and sign-out over HTTP **are**
operational as of Phase 4B — see [API](api.md) for the transport and routes, and ADR 0011 for why
public registration is intentional and grants no elevation. The next expected slice is Phase 4C:
Core authorization and an explicit, auditable platform-owner bootstrap command — not a Dashboard
Surface, which still depends on an authorization model that does not exist yet.