Scrubbed extract of
ADP-Orchestration-UI/Epic-1-Stories/US-OUI-1.5b-Login-Authentication-Page.md— cited by the Chronicle (03-the-platform-rises). Redactions: phone / service detail / secrets / clearance / personal / internal hosts.
type: implementation-plan category: Work project: ADP-Orchestration-UI priority: High status: done created: 2026-04-28 updated: 2026-06-09 migrated: 2026-05-14 epic: Epic-1-Foundation user-story: US-OUI-1.5b effort: 6h design_reference: “Login.html · ADP Orchestration UI.html (LoginPage component)” source: wireframe-gap-analysis-2026-05 depends-on: ADR-018 review-profile: standard tags:
- implementation-plan
- epic-1
- auth
- login
- new
US-OUI-1.5b: Login / Authentication Page (NEW)
Epic: [[README|Epic 1: Project Foundation & Design System]] Effort: 6 hours Priority: High Status: Design Complete → Ready for implementation
New story — not in original backlog. Added to account for the authentication entry point designed in the prototype.
Mission
Implement the production LoginPage.tsx view at route /login from the validated Login.html + LoginPage() prototype, wiring four Keycloak grant channels (Credentials → Authorization Code, SSO/OAuth → Auth Code + PKCE, API Key → client_credentials, Device Code → RFC 8628) per [[../../AI-Dev-Platform/ADR/ADR-018-Identity-Federation-Strategy|ADR-018]] through the auth.ts service from US-OUI-1.4. The full ADP mission-control visual treatment (scanline overlay, grid background, ambient amber glow, channel selector active states, success overlay with progress animation + redirect to /) is LOCKED — port without redesigning. A protected-route wrapper must redirect unauthenticated users from any dashboard route back to /login.
Context
The Login page is a NEW story added in 2026-04-28 against the wireframe gap analysis — the original Epic-1 backlog did not include an authentication entry point. The prototype Login.html and the LoginPage() component inside ADP Orchestration UI.html implement the full UI surface (info panel, login card with 4 tabbed grant channels, success overlay, session strip). Per [[../../AI-Dev-Platform/ADR/ADR-018-Identity-Federation-Strategy|ADR-018]], each tab maps to a specific Keycloak grant; token tuning (TTL, audience, refresh policy) is configured per Keycloak client so tokens are per-channel by construction. The auth.ts service from US-OUI-1.4 supplies getToken, isAuthenticated, login, logout; this story authors the UI that drives them and the per-grant flow integrations.
Context Bootstrap
Read the following before writing any code, in order:
- [[../../AI-Dev-Platform/ADR/ADR-017-Human-Review-Branching-And-TDD-Workflow|ADR-017]] — branch-per-story, TDD ordering, PR description schema
- [[../../AI-Dev-Platform/ADR/ADR-018-Identity-Federation-Strategy|ADR-018]] — Keycloak grant channels (Auth Code, PKCE, client_credentials, Device Auth Grant); per-client token tuning rationale
- [[US-OUI-1.1-Project-Scaffold]] — router scaffold,
/loginplaceholder route ownership - [[US-OUI-1.4-API-Client]] —
auth.tsservice +/loginredirect guard this story drives - [[Projects/ADP-Orchestration-UI/Epic-1-Stories/US-OUI-1.2-Design-System]] — design tokens + primitives this story composes from
- [[../_pkf|ADP-Orchestration-UI PKF]] — current project state, open questions on auth flow
- Prototype source:
Login.htmlandADP Orchestration UI.html→LoginPage()component — canonical visual + interaction reference
Gate Policy
This is when the executing agent should pause and surface, rather than proceed silently.
| Trigger | Gate Type | Condition / Reasoning |
|---|---|---|
Backend auth endpoints (POST /api/auth/key, GET /api/auth/device/{code}) not yet defined in the AIService backend |
Confidence Gate | The story’s own Dependencies section flags “auth endpoints (not yet scoped — may need a dedicated auth-endpoints backend story)”. Surface the missing backend contract; do not invent endpoint shapes. |
| OAuth 2.0 PKCE redirect URI registration with Keycloak | Confidence Gate | Per ADR-018, SSO requires the client to be registered in Keycloak with an exact redirect URI. Surface the URI choice rather than auto-deriving from window.location. |
| Keycloak realm + client IDs per grant channel | Confidence Gate | Each tab maps to a distinct Keycloak client (per ADR-018 per-client token tuning). Surface the four client IDs rather than reusing a single client across grants. |
| Channel selector semantics (IDE / Web UI / Discord / CLI) — what does the choice change? | Confidence Gate | The prototype shows a 2×2 channel-selector grid inside the Credentials tab. The behavioral contract (does the channel pick choose a different Keycloak realm, scope, or audience?) is not documented in the original story. Surface, do not guess. |
| Headscale key auth integration shape | Confidence Gate | The Credentials tab lists a “Headscale key” affordance. Surface whether this is a header sent on the Authorization Code flow vs. a separate grant channel; do not silently couple to one. |
| MFA TOTP integration with the Credentials flow | Confidence Gate | The Acceptance Criteria mention “MFA TOTP input (6-digit chain, auto-advance)”. Surface whether MFA is a Keycloak step-up flow (recommended) vs. a custom field shipped to the Authorization Code endpoint. |
| Visual treatment diverging from the prototype (token, layout, animation timing) | Trust Gate | The visual layer is LOCKED. Redesign is not a port. |
| Test failure during Verify (tab switching, channel selection, submit handler, success redirect) | Trust Gate | Do not mark complete with failing tests. |
Deliverables
Group by component. Use checkboxes. Items checked [x] were validated in the prototype; production-port items remain [ ].
Layout & Visual Treatment
- Full layout with info panel + divider + login card designed
- All 4 auth tab panels implemented
- Channel selector with active state
- Password show/hide toggle
- Error state (invalid credentials)
- Success overlay with progress animation and redirect
- Session history strip
- Scanline + grid background + ambient glow
- Device code countdown timer
Production Implementation
-
LoginPage.tsxview component at route/login -
auth.tsservice: POST credentials, handle JWT, store token - SSO redirect flow via OAuth 2.0 PKCE
- API key validation against
POST /api/auth/key - Device code polling against
GET /api/auth/device/{code} - Protected route wrapper redirecting unauthenticated users to
/login - MFA TOTP input (6-digit chain, auto-advance)
- Headscale key auth integration
- Offline-safe: login attempt queued if network unreachable (non-blocking)
- Unit tests: tab switching, channel selection, submit handler, success redirect
Execution Phases
TDD-ordered per [[../../AI-Dev-Platform/ADR/ADR-017-Human-Review-Branching-And-TDD-Workflow|ADR-017]] §4. Plan / Test / PR review checkpoints fire between phases per the resolved review-profile: standard.
- Branch Creation — Create
agent/US-OUI-1.5b-login-authentication-pagefrommain. No commits to protected branches; AIS fires anIRREVERSIBLETrust Gate on violation (ADR-017 §3). - Load Context — Read the Context Bootstrap files plus the prototype (
Login.html+LoginPage()). Resolve every Confidence Gate listed above (Keycloak client IDs, redirect URI, channel semantics, Headscale + MFA shape, backend endpoint contracts) before authoring tests. (Plan Review checkpoint fires after this onstandardprofile.) - Write Failing Tests — Author
LoginPage.test.tsxwith: (a) tab-switching renders the correct panel for each of the 4 channels, (b) channel-selector active-state toggle, (c) submit handler invokes the rightauth.tsmethod per tab, (d) error state renders on rejected credentials, (e) success overlay triggers redirect to/, (f) device-code countdown decrements and regenerates. Author a protected-route guard test (unauthenticated user on/redirects to/login; authenticated user reaches/). All tests must fail before implementation. Record fail transitions per ADR-017 §4. (Test Review checkpoint fires onstandardprofile.) - Implement — Write
LoginPage.tsx, the four tab-panel components, the channel selector, the success overlay, the protected-route wrapper. Extendauth.tswith per-grant methods (Authorization Code, PKCE,client_credentials, Device Auth Grant). Wire the API key and device-code backend calls. Re-run tests; all must pass. - Verify & Refactor — Run
npm run typecheck,npm run lint,npm test. All must succeed. Visually diffLoginPageagainst the prototype to confirm scanline timing, grid opacity, channel-selector active state, and success-overlay progress animation match. Update story status toreview. - PR Submission — Push branch; open one PR to
mainwith the structured PR description per “PR Submission Requirements” below. (PR Review checkpoint fires; merge is human-only.)
PR Submission Requirements
The PR description is generated from the session record before opening the PR. Schema is enforced at PR-open time per [[../../AI-Dev-Platform/ADR/ADR-017-Human-Review-Branching-And-TDD-Workflow|ADR-017]] §5 (pr-description-schema-version: 1.0). Required sections: Reasoning Chain (per-decision summary, especially Keycloak client choices per grant channel and the four resolved Confidence Gates), Gate History (Trust + Confidence gates surfaced during execution — the Keycloak / channel-semantics / MFA / Headscale ambiguities at minimum), Citations (ADR-017, ADR-018, US-OUI-1.1, US-OUI-1.2, US-OUI-1.4, Epic-1 README, project PKF, prototype source), Review Profile (standard; inherited from project default), Test Plan (links to LoginPage.test.tsx and the protected-route-guard test, fail→pass transitions, coverage delta).
Implementation Notes
Design Reference
Prototype: Login.html (standalone) and ADP Orchestration UI.html → LoginPage() component
Visual language: matches full ADP design system — scanline overlay, grid background, amber accent, ambient glow
Implemented Layout
Full-viewport centered layout (flex row, centered vertically):
┌────────────────────────────────────────────────────────────┐
│ Topbar: ADP/Jarvis · SECURE ACCESS TERMINAL · node status │
├───────────────────┬───────┬────────────────────────────────┤
│ Info Panel │ │ │ Login Card (380px) │
│ │ │ │ ┌──────────────────────────┐ │
│ JARVIS wordmark │ │ │ │ Credentials / SSO / │ │
│ Tagline │ │ │ │ API Key / Device Code │ │
│ 4 feature rows │ │ │ │ (tab strip) │ │
│ TG · CF · VK · LR│ │ │ │ │ │
│ │ │ │ │ [form content per tab] │ │
│ │ │ │ │ │ │
│ │ │ │ │ ⊳ Authenticate & Enter │ │
│ │ │ │ └──────────────────────────┘ │
├───────────────────┴───────┴────────────────────────────────┤
│ Session strip: RECENT SESSIONS · 3 prior sessions │
└────────────────────────────────────────────────────────────┘
Background Elements
grid-bg: CSS background-image grid at 48px × 48px, 20% opacityscan-line: animated 1px amber gradient line scanning top→bottom (10s loop)glow-left: radial amber gradient positioned at left edge of viewport
Login Card — 4 Auth Tabs
Per [[../../AI-Dev-Platform/ADR/ADR-018-Identity-Federation-Strategy|ADR-018]], each tab corresponds to a Keycloak grant channel — token tuning (TTL, audience, refresh policy) is configured per Keycloak client so tokens are per-channel by construction.
| Tab | Content | Keycloak grant (ADR-018) |
|---|---|---|
| Credentials | Channel selector (2×2 grid: IDE / Web UI / Discord / CLI) + identity input + passphrase input (show/hide) + error state + submit button + MFA add-on + Headscale key | Authorization Code (realm-internal login form; not ROPC) |
| SSO / OAuth | Provider buttons: GitHub SSO, Azure AD, Google — OAuth 2.0 PKCE flow | Authorization Code + PKCE (RFC 7636) brokered through Keycloak |
| API Key | Single API key input + paste affordance + key expiry note + submit | client_credentials against a confidential per-key Keycloak client |
| Device Code | Generated device code (large amber monospace) + countdown bar + jarvis.local/device URL + regenerate | Device Authorization Grant (RFC 8628) |
Channel Selector
2×2 grid of selectable channel cards (IDE / VS Code, Web UI, Discord, CLI). Active state: amber-dim border + amber-glow background + amber label.
Success State
Full-card overlay on successful auth:
- Green checkmark icon (48×48px, green-glow bg)
- “ACCESS GRANTED” (Condensed 16px bold green)
- “Loading orchestration dashboard…” (mono dim)
- Animated green progress bar (1.5s fill)
- Redirects to
/(dashboard) after 2s
Session Strip (bottom, fixed)
RECENT SESSIONS label + 3 prior session rows (pip + name + channel + time) + node name + live clock
Dependencies
- US-OUI-1.1 (Project Scaffold) — router and auth service must exist
- Auth endpoints (not yet scoped — may need a dedicated auth-endpoints backend story)
Notes
The session strip’s “active now” session should reflect the most recent
authenticated session pulled from the auth service. The live clock in
the bottom-right corner is a setInterval at 1s displaying local time.
Definition of Done
- All Deliverables checked
- All Execution Phases verified
- All 4 Keycloak grant channels wired and tested
- Protected-route wrapper redirects unauthenticated users to
/login - Visual treatment matches prototype (scanline, grid, glow, channel active state, success overlay)
- ADR-017 compliance: branch-per-story, PR description schema, no direct commits to
main - ADR-018 compliance: per-grant Keycloak clients identified; no ROPC; PKCE on SSO
- Status updated to
review
Related
- [[US-OUI-1.1-Project-Scaffold]] — prerequisite (router + auth service scaffold)
- [[Projects/ADP-Orchestration-UI/Epic-1-Stories/US-OUI-1.2-Design-System]] — design tokens + primitives consumed
- [[US-OUI-1.4-API-Client]] —
auth.tsservice this story drives - [[../../AI-Dev-Platform/ADR/ADR-017-Human-Review-Branching-And-TDD-Workflow|ADR-017]] — review/branch/TDD workflow
- [[../../AI-Dev-Platform/ADR/ADR-018-Identity-Federation-Strategy|ADR-018]] — Keycloak grant channels, per-client token tuning
- [[../_pkf|ADP-Orchestration-UI PKF]] — current project state