Id app RFC 001 stack portal consolidation
Summary
The Koder ID Flutter app (services/foundation/id/app/) becomes the *ingle user-facing portal*for everything an identified Koder user does outside of product surfaces. Today the app is minimal (theme picker + authgate approval dialog + the justshipped PAT management section). The proposal expands its scope to absorb features that today either live in services/foundation/pass/app/, in dedicated admin web UIs that don't exist, or in product-side admin tools that bypass the identity layer.
This RFC is a *irection-setting document* not an implementation plan. It captures the architectural decision so the backlog work that follows has a single anchor.
Motivation
The current state has three artifacts that show the gap:
- *servicesfoundationid/app` is underbuilt.*The engine has
shipped 124 tickets worth of API surface (
/v1/me/{pats, passkeys, mfa-devices, age, erasure, ...},/v1/admin/{clients, system, ...}, OAuth grants including devicecode, RLS Phase 2 across 12 subservices). The user- facing app exposes a fraction of it.
- *servicesfoundationpass/app` is a separate standalone*
with 196 files spanning Flutter + Go server + chromium extension + Android NFC code + landing. It overlaps with id in identity- adjacent features (passkeys, qrlogin, devices, biometric) but also carries pure-vault concerns (document scan, MDL, import from 1Password). The split was bottom-up — "Pass got built first as its own product" — not a deliberate decision.
- *here is no Stack admin UI today.*Operators run
koder-id-clifrom a terminal, peek at/metricsendpoints, and triage incidents from SSH. Phonebased actions (authgate approval, audit log review, tenant member revoke) are wired per-flow, not unified.
The industry pattern — Apple iCloud Keychain + Settings + Find My, Google Account app, Microsoft Authenticator, even 1Password — is *ne app for "your identity and everything tied to it"*with admin tooling gated by role.
Decision
The services/foundation/id/app/ Flutter app gains the following *ection taxonomy* Each toplevel section is an optin feature of the same app, gated by RBAC role + tenant config.
Section 1 — Account (every user)
- Profile (handle, display name, avatar, locale, country)
- Age declaration (
/v1/me/agefrom #062) - Sessions list (active devices, last-used, revoke)
- Authorized devices (
services/devicetrusted_devices) - Data export (
/v1/me/data-exportfrom identitydataretention.kmd) - Account deletion (LGPD erasure flow
/v1/me/erasurefrom #090)
Section 2 — Security (every user)
- Passkeys (
/v1/me/passkeys— replaces passapplibfeaturespasskeys/) - MFA devices (TOTP, hardware keys, recovery codes — replaces passapplibfeaturessecurity/)
- OAuth grants (third-party apps with access —
/v1/me/grants) - Personal access tokens (#106 — already shipped this session)
- Sign
in approvals (authgate dialog #086 — already shipped) - Recent activity / login audit log
Section 3 — Sign-in helpers (every user)
- QR-code login generator (
services/qr— replaces passapplibfeaturesqrlogin/) - OTP authenticator (TOTP secrets for non-Koder sites, optional)
- Login approval queue (consolidates the auth-gate flow)
Section 4 — Vault (every user; opt-in)
- Saved passwords for non-Koder sites
- Documents (driver's license, passport — from passapplibfeaturesdocument/)
- Import from 1Password / Bitwarden / Apple Keychain (from passapplibfeaturesimport_export/)
- Browser autofill — companion extension lives in passappchromium-extension/
This section is the *pt-in product layer*that absorbs Pass's vault features. It's structured as a separate app section because not every Koder ID user wants a third-party password vault — some will use 1Password or Apple Keychain.
Section 5 — Workspace (workspace owner / admin role)
- Workspace settings (logo, branding, SSO config from
services/auth/internal/handler/workspace_sso_http.go) - Member management (invite, role grant, revoke,
workspace_domains add/verify)
- Subtenant management (
services/foundation/identitysubtenants table — RFC-012)
- Audit log per workspace
- Billing / usage (PAT cost tracker —
read:usagescope from #119)
Section 6 — Admin (Stack super-admin role)
- OAuth client management (
/admin/clients— #115 server-sideexists, UI doesn't)
- Tenant list + provisioning
- Per
subservice /metrics aggregated dashboard (#108) - Audit log query (services/audit)
- Erasure replay (#098)
- Pending invites across tenants
- Service-account creation (#123 ties in here)
Consequences
What changes in services/foundation/pass/
Two paths to evaluate (owner picks the strategic one):
*ath A — Pass becomes B2C-only consumer vault.*Pass keeps its identity (separate app + brand) but refocuses on nonKoderstack users — people who want a 1Password-style vault without committing to the Koder Stack identity. Pass's identity-adjacent code (passkeysqrlogindevices) deprecates in favor of id/app once id/app's Section 2+3 ship. Pass's pure-vault code (document, import_export, browser autofill) stays.
*ath B — Pass absorbed into id/app's Section 4.*Passthe product retires; all its code that survives merges into id/app's Vault section. The Pass brand becomes a "Vault" badge inside id. Saves a Flutter codebase + chromium extension maintenance burden; costs marketing-positioning (B2C "use Pass without Koder Stack" goes away).
This RFC does NOT pick between A and B — owner ratification selects.
What changes in services/foundation/id/app/
- Major scope expansion from "Settings + auth-gate" to "the
Koder portal".
- New navigation surface (drawer or bottom-nav). Today the app is
single-screen.
- RBAC plumbing: client-side role check to show/hide Sections 5+6.
- Per
section deeplink routes for push-notification flows (e.g.notification taps that go directly to "Approve sign-in" land on Section 3's approval queue).
- i18n keys explode — wave 1 en
US + ptBR per existing app pattern.
What changes in the engine
Very little. Most surfaces already exist (`v1me