@emubrain-studio/auth-ui 0.1.0 contract v1 Specification Design only

The variation budget already exists — this design maps onto it

I did not choose what products may vary. emubrain-auth PR #26 already defines it in src/fleet-ui-contract.ts, and the branding block is z.object({…}).strict()a seventh key is a parse error. So this artifact specifies the shell against those exact six fields and reports where the brief and the contract disagree, rather than inventing a parallel budget.

1Version identity

FieldValueSource
ArtifactFleet shared auth UI — design specificationthis document
Artifact version0.1.0-design.1tracks the package it specifies
Package@emubrain-studio/auth-ui@0.1.0FLEET_AUTH_UI_PACKAGE, FLEET_AUTH_UI_INITIAL_VERSION
Contract version1FLEET_AUTH_UI_CONTRACT_VERSION
Aligned toemubrain-auth PR #26, head c5e5c75branch axel/auth-shared-ui-contract, base main, OPEN
Engine@emubrain-studio/auth, Better Auth 1.6.25, Argon2idproposal, canonical engine inventory

Read at the PR head, not at a branch name. I pinned c5e5c75 because a named ref moved under me three times this week. If the PR advances, this artifact's alignment claim is only true of that head until re-checked.

2The six product-variable tokens

Everything else in the auth surface is package-owned

Manifest fieldSchemaDesign use
branding.logoPath/^\/(?!\/)[^?#]{1,240}$/The mark, 28×28, top-left. Never scaled per product.
branding.logoAlt1–120 chars, trimmedAccessible name and the visible product name. Truncates — see Edges.
branding.accentColor#RRGGBBPrimary button fill, link colour, mark fill.
branding.accentForegroundColor#RRGGBBText and glyphs sitting on the accent.
branding.fontToken/^[A-Za-z][A-Za-z0-9_-]{0,39}$/Selects one stack from a package-owned registry. See delta 3.
branding.themelight | dark | systemPicks a palette; does not define one.

Not variable, and this is the point of the package: field order, validation placement, focus order, error mapping, security copy, spacing, radii, breakpoints, the neutral palette, the dark values, and the focus ring. The proposal is explicit — a product "may not fork a screen, override security copy, add providers, or call raw Better Auth endpoints."

3State inventory

ViewStatesRequired?
Sign indefault · field validation · credentials rejected · submittingAlways — emailPassword: z.literal(true)
Sign updefault · address unavailableAlways
Verify emailpending · success · expiredOnly when capabilities.emailVerification is true
Forgot passwordrequest · sentAlways — passwordReset: z.literal(true)
Reset passwordchoose new · mismatch · link expiredAlways
Logoutsigned outAlways — logout-revocation is a conformance case
Sharedloading · rate-limited · auth unavailable · safe generic errorAlways

Sixteen states across ten views, all drawn at desktop and 360 on the States page. Verification is the only conditional group, and requiredFleetAuthConformanceCases() is what makes it conditional — it appends verification-required-before-signin and verification-consume only when the manifest enables the capability.

4Accessibility and contrast

5Implementation token deltas

Three places where the brief, the contract, or both need a decision

Delta 1 — the brief permits two variations the contract forbids. Adam's task lists product variation as "logo, font, accent tokens, sender/support copy, and optional illustration". Neither exists in branding, and the block is .strict(), so neither can be added without a contract version bump. bindings.fromAddress does exist but it is an env-bound email under bindings, not branding, and the proposal states products may not override security copy. I designed to the contract and excluded both. If they are genuinely wanted, that is a contract change (v1 → v2) and Adam's call, not a design decision.

Delta 2 — the schema validates that the accent pair is hex, not that it is legible. hexColorSchema is /^#[0-9A-Fa-f]{6}$/ and nothing else. A manifest with parses, passes CI, and ships a primary button whose label is invisible. Contrast of that example: . Recommend the schema enforce a flooraccentForegroundColor against accentColor at ≥ 4.5:1 — as a superRefine alongside the origin checks that already exist. It is the same shape of rule and the same file. The three demonstration products all clear it: .

Delta 3 — fontToken is a name with nothing to resolve it. The pattern /^[A-Za-z][A-Za-z0-9_-]{0,39}$/ accepts any identifier, so a manifest can declare Comic_Sans and the package has no registry to map it to a stack. Recommend the package own an explicit token→stack table and reject unknown tokens, which also keeps font loading inside the package where the licence and the fallback chain can be controlled. Three tokens are enough to start: a system sans, a serif, and a monospace.

6Non-goals

Stated explicitly because the brief asked for them, and because on an auth surface the boundary is the deliverable:

Design specification only. Aligned to emubrain-auth PR #26 at head c5e5c75 (branch axel/auth-shared-ui-contract). Presentation only — no code, secrets, deployment or production action. Review authority per the proposal: Rhea reviews the contract, Adam resolves architecture exceptions.