Plan: `admin-console` + `auth` concerns — the foundational product surfaces (it.35)
Plan: admin-console + auth concerns — the foundational product surfaces (it.35)
Date: 2026-05-26 · Scope: methodology (new concerns + auth-provider slot + frame auto-select) · Branch: helix-self-improvement-2026-05-24
Runtime-neutral; additive ddx: frontmatter preserved. Operator-directed (“admin backend = a missing helix concern”).
Problem (operator-surfaced, bench-confirmed)
Both faithful HubSpot greenfield builds (claude FastAPI, codex Next.js) shipped a backend delivery pipeline + read-only dashboards and omitted the two foundational user-facing surfaces of a real SaaS:
- No operator admin backend — no UI to upload/edit a list, edit a template, schedule a campaign to a list, watch delivery stats, or pause/cancel a send. (claude had CRUD endpoints + 5 read pages and no pause/cancel even in the API; codex was 4 read-only pages + 1 mutation.)
- No auth — no signup, login, sessions, in-tenant roles, or platform admin, in a multi-tenant product.
Root cause: nothing in HELIX asserts these surfaces, so “runnable slice” collapsed to “pipeline + dashboards” and the it.31 e2e “passed” on the pipeline, not the operator’s jobs-to-be-done through the UI. Same locally-correct/globally-wrong failure as it.31, at the product-surface level.
Evidence to ground the concerns (the two directed admin+auth evolves both independently produced):
- Auth modeled as an
auth-providerslot: real local default (claudelocal-sessionspassword+magic-link behind anIdentityProvider; codexlocal-password-session-provider) + deferred-live external IdP/Auth0, swappable with no call-site change, IdP never hardcoded; signup→tenant+owner; HttpOnly sessions; PBKDF2; in-tenant RBAC (owner/admin/member) + platform-admin enforced server-side; tenant isolation through the authenticated principal. - Admin-console: claude’s
http-e2edriven through the UI over the primary operator workflow (signup → create list → create template → schedule campaign → delivery stats → pause), asserting rendered HTML +aria-current; both wired operator CRUD + pause/cancel to the engine.
Change (two concerns + one slot + auto-select), grounded in the above
- New exclusive slot
auth-providerinworkflows/concerns/slots.yml— the one swappable authentication/identity backend.defaults: auth-provider: auth-local-sessions. (Both evolves treated auth as a slot; future providers — Auth0/Clerk/OIDC — fill it via their own concern.md## Slot: auth-provider.) - New concern
auth(workflows/concerns/auth/{concern.md,practices.md}),## Slot: auth-provider, areasapi, data, ui. Practices (from evidence): an account/multi-tenant product MUST build the auth product surface — signup that provisions a tenant + its owner, login/logout, server-side sessions (HttpOnly), in-tenant RBAC (owner/admin/member or product-appropriate) enforced server-side, a global/ platform-admin role, and multi-tenant isolation enforced through the authenticated principal — with the provider behind a swappable interface: a real working local default (sessions/password), an external IdP (Auth0/OIDC) as a deferred-live swap selected by config with no call-site change and never hardcoded. A stub/seam-only auth (no usable signup/login/roles) does NOT satisfy it. Composes withsecurity-owasp. - New concern
admin-console(workflows/concerns/admin-console/{concern.md,practices.md}), COMPOSABLE (no slot), areasui, api. Practices: for an operator-facing product, build the operator’s jobs-to-be-done — CRUD over the core domain objects + lifecycle/control actions (e.g. pause / cancel / resume) — as usable UI screens, and the primary operator workflow must be exercised end-to-end THROUGH THE UI (the verification evidence gate + thee2e-frameworktool drive the real UI over the operator’s job;ux-radixowns the UI quality). A backend pipeline + read-only dashboards does NOT satisfy it — the operator must be able to do their job from the UI. (This absorbs the “primary-workflow coverage” idea as a concern, not a bolt-on gate.) Boundary:admin-consoleowns which surfaces/workflows exist + e2e-through-UI;ux-radixowns how they look/behave;verificationowns evidence; thefrontend-frameworkslot owns the stack. - Frame AUTO-SELECT in
workflows/references/concern-resolution.md(highinferred selection, after 2a/2b):- 2c: an operator-facing / back-office product (a human operator manages domain objects through a UI)
auto-selects
admin-console(recorded assumption). - 2d: an account-based / multi-tenant product (users sign in; data scoped to accounts/tenants)
auto-selects
authand fillsauth-provider(defaultauth-local-sessions), recorded assumption. Mirror in SKILL.md’s frame route (one line) so the surfaced rule is also in the skill body.
- 2c: an operator-facing / back-office product (a human operator manages domain objects through a UI)
auto-selects
Validation (re-bench)
Fresh greenfield via faithful TUI on the HubSpot brief (or a new operator-facing/multi-tenant brief). Success =
the agent, UNPROMPTED, (a) selects auth + admin-console, (b) builds real signup/login/roles + the operator
admin UI with control actions, and (c) the e2e drives the primary operator workflow through the UI green —
vs the pre-it.35 pipeline+dashboards. Cross-check no over-fire: a non-operator-facing product (a pure API
service, a CLI, a library) does NOT auto-select these.
Codex plan-review: VERDICT SOUND-WITH-FIXES — all 6 incorporated (corrected structure below)
- Split auth: composable requirement vs slot filler.
auth= COMPOSABLE concern owning the product requirement (signup/login/logout, tenant bootstrap, RBAC, platform-admin, isolation-through-principal) — it does NOT fill the slot.auth-local-sessions= the defaultauth-providerslot filler (the local sessions/password impl). Futureauth0-oidc/clerkfill the same slot. (Avoids a provider swap replacing the generic auth product requirement.) admin-consoleboundary = “required operator product surface + required workflow-coverage target.” It does NOT own evidence (verification), runner/form (e2e-framework), stack (frontend-framework), UI quality (ux-radix), or security hardening (security-owasp) — state each explicitly.- Crisp auto-select triggers (deterministic, no over-fire):
admin-consoleonly when a human operator/ back-office/admin must manage mutable domain objects or lifecycle state through a UI (NOT pure API / CLI / library / public content site / read-only dashboard unless an operator UI is explicitly required).authonly when the product has accounts/users/tenants/orgs/sign-in/session/roles/principal-scoped data or actions (NOT anonymous sites / libraries / single-user local CLIs / machine-only APIs unless principals are explicit). - e2e-through-the-UI teeth: “the workflow starts from the rendered UI surface and drives the same controls
an operator would use; direct API-only e2e does NOT satisfy
admin-console.” Letverificationdecide the form — browser for client-rendered, live-server HTTP + rendered-markup assertions for server-rendered (it.33). - Lifecycle/control actions explicit:
admin-consolerequires CRUD plus domain lifecycle controls where the domain has controllable state (schedule / pause / cancel / resume / retry / archive / revoke / approve). “Read-only dashboard + backend job pipeline” is a named drift signal. - Runtime-neutral: concern/practices text avoids DDx/TUI language; re-bench/validation lives in this plan, not the portable concern contract.
Final file set
workflows/concerns/slots.yml:auth-provider: { exclusive: true }+defaults: auth-provider: auth-local-sessions.workflows/concerns/auth/{concern.md,practices.md}— composable (areas api,data,ui), product requirement; references theauth-providerslot for the backend; composes withsecurity-owasp.workflows/concerns/auth-local-sessions/{concern.md,practices.md}—## Slot: auth-provider, the default local sessions/password filler (HttpOnly sessions, hashed passwords, behind the swappable interface; external IdP e.g. Auth0/OIDC is a different filler, deferred-live, never hardcoded).workflows/concerns/admin-console/{concern.md,practices.md}— composable (areas ui,api).workflows/references/concern-resolution.md2c/2d auto-select (crisp triggers) + one-line SKILL.md frame-route mirror.
Over-engineering guard / risks
- Scope: two concerns + one slot + two auto-select bullets. Don’t create per-provider auth concerns now (Auth0
is a deferred-live swap described in
authpractices, not a separate concern yet). admin-consoletriggers only for operator-facing products;authonly for account/multi-tenant — not every product. Keep the practices about building the surface + e2e-through-UI, not prescribing specific screens/fields.- Codex-review BOTH ends. Runtime-neutral; preserve
ddx:frontmatter; SKILL.md 0 ddx hits; re-blessconcern-resolution(stamped).