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:

  1. *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.

  1. *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.

  1. *here is no Stack admin UI today.*Operators run

    koder-id-cli from a terminal, peek at /metrics endpoints, 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/age from #062)
  • Sessions list (active devices, last-used, revoke)
  • Authorized devices (services/device trusted_devices)
  • Data export (/v1/me/data-export from identitydataretention.kmd)
  • Account deletion (LGPD erasure flow /v1/me/erasure from #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)
  • Signin 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/identity

    subtenants table — RFC-012)

  • Audit log per workspace
  • Billing / usage (PAT cost tracker — read:usage scope from #119)

Section 6 — Admin (Stack super-admin role)

  • OAuth client management (/admin/clients — #115 server-side

    exists, UI doesn't)

  • Tenant list + provisioning
  • Persubservice /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.
  • Persection 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 enUS + ptBR per existing app pattern.

What changes in the engine

Very little. Most surfaces already exist (`v1me

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/id-app-RFC-001-stack-portal-consolidation.kmd