Skip to content

[architecture] auth.admin — a separate, pluggable write/admin plane for identity & permission management (keeps provider verify-only, verifier decision-only) #4

Description

@y1o1

Architecture Decision Record (direction, not a now-task). Records where write/admin capability belongs in the stack, so future work does not push it into the verify/decision layers.

Decision

If and when write / administrative capability is needed, it lives in a separate repository auth.admin — a pluggable, optional management API (UI optional) for identity and permission administration. auth.provider stays verify-only; auth.policy-verifier stays decision-only. Neither gains user-CRUD / grant-authoring / lifecycle write.

Motivation

The verify-only boundary (see auth.provider #296 / #297 / #301, and the adapter-surface epic auth.provider #305) deliberately keeps identity lifecycle and permission authoring out of the authentication/decision layers. Those write concerns still need a home. Bolting them onto the provider or the verifier would break the separation of concerns that the whole stack is built on. A dedicated write plane keeps each component single-responsibility and independently deployable.

This mirrors the established split we already resemble (Ory): identity management (Kratos) / OAuth (Hydra) / permission management (Keto) / enforcement (Oathkeeper), each exposing an admin API on a separate trust boundary from its public API.

Resulting stack (write plane added)

Plane Repo Responsibility
Administration / write (new, future) auth.admin Identity CRUD, credential/password writes, email/phone verification-state transitions, account state machine, device registration + device→user linking, anonymous→registered upgrade, MFA enrollment management, and permission authoring (role / scope / ABAC-attribute grant management). UI optional (admin console + end-user self-service signup/reset/verify screens).
Authentication & token issuance auth.provider verify-only + issuance + issuer/subject/claims binding
Authorization decision auth.policy-verifier decision-only (evaluates; does not own grants)
Authorization enforcement protobuf.interceptors gRPC/protobuf interceptors
Stores operator-owned written by auth.admin, read by auth.provider (identity) and auth.policy-verifier (grants/attributes)

Design guardrails (keep the stack coherent)

  1. Separate trust boundary. The admin API is privileged (creates users, grants permissions). It MUST NOT share the public surface of the provider's token endpoint — internal-only, strong caller auth (mTLS / service credential), fully audited. (Do not repeat the 0.0.0.0 + no-caller-auth mistake — see auth.policy-verifier #108.)
  2. Shared Store contract, not shared code. auth.admin writes the same schema that auth.provider's UserRepository and auth.policy-verifier's collectors read. The integration point is the Store schema, not a library dependency — so repos stay independently deployable (consistent with the stack's no-cross-repo-atomic-commit constraint).
  3. auth.admin is itself pluggable / optional. Operators may adopt it wholesale or replace it with their own IAM/admin system. Same philosophy as the Store adapters (auth.provider #305).
  4. Authoring here, decision in the verifier. "Who has which role/scope/attribute" is a write owned by auth.admin; "allow/deny" is evaluation owned by auth.policy-verifier. Separate administer from decide.
  5. UI belongs to this plane. Admin console and end-user self-service (signup / reset / verify screens) live here (or are built by the operator against this API) — resolving the provider's intentional "no UI" gap without polluting the token layer.

What this resolves from the review + follow-up

  • Signup, password-reset write, email-verification state, device registration, device→user linking, anonymous→registered upgrade → auth.admin + Stores.
  • Permission/grant authoring → auth.admin; auth.policy-verifier stays decision-only.
  • "No UI" → auth.admin (optional).
  • auth.provider retains only: verify, issuance, device-login entry point (auth.provider #301), post-credential-change revocation hook (auth.provider #296 sliver), and Store-owned state → claim surfacing (auth.provider #297 sliver).

Status

Direction recorded. No implementation implied yet. Revisit when write/admin capability is actually scheduled; at that point, spin up auth.admin and expand this into a component spec.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationドキュメントImprovement改善・機能追加Prior優先area:architectureStack-level architecture / decision recordepicTracking/strategy issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions