forked from EduCraft/curriculum-project-hub
docs: define platform admin identity boundary
This commit is contained in:
@@ -112,5 +112,6 @@ Organization for operational reporting; commercial billing remains deferred.
|
||||
and readiness checks.
|
||||
- Folder-level permissions are deferred until there is a concrete customer need.
|
||||
- Self-serve org signup and payment collection are deferred beyond pilot.
|
||||
- The exact platform admin identity store and audit schema are separate from
|
||||
this ADR and should be modeled before exposing the platform admin panel.
|
||||
- The platform admin identity, session, bootstrap, invitation, audit, and
|
||||
offline recovery boundary is decided by ADR-0023 and must be implemented
|
||||
before exposing the platform admin panel.
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
# ADR 0023: Platform Administrator Identity And Audit Boundary
|
||||
|
||||
## Status
|
||||
|
||||
Accepted.
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0021 separated `/admin/platform` from Organization administration but left
|
||||
the exact platform identity store and audit schema open. That choice must be
|
||||
settled before exposing the panel: customer Feishu identities are scoped by
|
||||
their customer-owned applications, Organization membership must not confer
|
||||
platform authority, and a platform operator can create tenants, change
|
||||
connections, rotate credentials, or stop workloads across tenant boundaries.
|
||||
|
||||
The current implementation is not the accepted platform model.
|
||||
`PlatformRoleAssignment` points at the customer-side `User`, includes a legacy
|
||||
`TEACHER` value, and has no platform login or guard. The current browser session
|
||||
is a seven-day stateless customer cookie, while `AuditEntry` is Project/Run
|
||||
oriented and deliberately best-effort. Reusing any of these would couple the
|
||||
two control planes and make immediate revocation or fail-closed privileged
|
||||
audit impossible.
|
||||
|
||||
## Decision
|
||||
|
||||
### Identity issuer and authority
|
||||
|
||||
Platform Administrators authenticate only through one dedicated
|
||||
**Platform-owned Feishu Application**. It is separate from every Organization's
|
||||
Customer-owned Feishu Application and cannot grant Organization membership or
|
||||
Project permission.
|
||||
|
||||
A `PlatformIdentity` is scoped by that platform application and its verified
|
||||
external Feishu user identity. It is not a customer `User`. The same person may
|
||||
also have customer identities, but there is no implicit link, shared session,
|
||||
or authority propagation between them.
|
||||
|
||||
The initial platform control plane has exactly one standing role:
|
||||
`Platform Administrator`. There is no Platform Owner, Super Admin, or Teacher
|
||||
hierarchy. The first administrator has no permanent special authority after
|
||||
another administrator is active.
|
||||
|
||||
### Bootstrap, invitation, and revocation
|
||||
|
||||
The first Platform Administrator is granted through a checked-in, versioned,
|
||||
idempotent and transactional bootstrap database procedure. It accepts only a
|
||||
verified Platform Identity, refuses to run while any standing Platform
|
||||
Administrator is active, and atomically writes the grant plus its Platform
|
||||
Audit Entry. Ad-hoc manual `INSERT` statements and permanent environment
|
||||
allowlists are not supported bootstrap paths.
|
||||
|
||||
Later administrators join through short-lived, single-use invitation links
|
||||
created by an active Platform Administrator. An invitation is bound to one
|
||||
specific Feishu account in the Platform-owned Feishu Application; possessing a
|
||||
link without authenticating as that account is insufficient. The invitation
|
||||
records its inviter and reason and becomes terminal after acceptance, expiry,
|
||||
or revocation. One active Platform Administrator approval is sufficient for the
|
||||
initial service.
|
||||
|
||||
All standing Platform Administrators are peers. An administrator may invite or
|
||||
revoke another administrator, but the last active standing administrator cannot
|
||||
be revoked. Revocation immediately invalidates all Platform Sessions and all
|
||||
unclaimed invitations belonging to the revoked identity.
|
||||
|
||||
### Platform Session and step-up authentication
|
||||
|
||||
`Platform Session` is a separate, server-side, revocable session with a distinct
|
||||
cookie/token namespace. The browser receives an opaque random token; persistence
|
||||
stores only its hash and binds the session to a Platform Identity. Every request
|
||||
reloads the session and active grant. The session carries no Organization,
|
||||
membership, Project, or customer Feishu authority.
|
||||
|
||||
Administrator lifecycle changes, platform or customer Feishu connection
|
||||
changes, platform-managed Provider credential changes, Organization lifecycle
|
||||
changes, workload-brake changes, and Emergency Platform Grant changes require
|
||||
recent Feishu OAuth reauthentication. Exact session/idle/step-up durations,
|
||||
CSRF, cookie and proxy/TLS mechanics belong to the production browser/session
|
||||
boundary decision; they must be configurable under checked maximums rather than
|
||||
silently inheriting the current seven-day customer cookie.
|
||||
|
||||
### Platform audit
|
||||
|
||||
`Platform Audit Entry` is a separate append-only record from customer Project
|
||||
and Agent Run audit. Every successful platform mutation and its audit entry
|
||||
commit in the same database transaction. If the audit entry cannot be written,
|
||||
the mutation fails. Platform audit is durable business evidence, not
|
||||
best-effort telemetry.
|
||||
|
||||
An entry identifies the Platform Identity and Platform Session, action, target
|
||||
kind and identifier, affected Organization when applicable, mandatory reason
|
||||
for security-sensitive actions, request/correlation identity, outcome, time,
|
||||
and redacted before/after facts. It never stores credential, token, recovery-key
|
||||
or other plaintext secret material. The normal service path can append and read
|
||||
but cannot update or delete history.
|
||||
|
||||
Platform Administrators can read the complete redacted platform audit.
|
||||
Organization Administrators can read a customer-safe projection of entries
|
||||
affecting their Organization, including Organization lifecycle, Feishu/provider
|
||||
connection, and workload-brake changes; they cannot read other Organizations,
|
||||
platform administrator lifecycle, recovery material, or internal security
|
||||
events.
|
||||
|
||||
### Offline recovery and break-glass
|
||||
|
||||
There is no standing break-glass web account or shared emergency password.
|
||||
Recovery uses a checked-in offline command from a controlled production-host
|
||||
console. The supported procedure requires both privileged host access and a
|
||||
recovery key held outside the host, environment file, and ordinary backup set.
|
||||
It also requires an incident identifier, reason, and one explicit recovery
|
||||
action.
|
||||
|
||||
Recovery may revoke Platform Sessions, repair the Platform-owned Feishu
|
||||
connection, or issue an `Emergency Platform Grant` to a verified Platform
|
||||
Identity. An emergency grant is time-bounded, automatically expires, is not a
|
||||
standing role, and must be explicitly closed when recovery finishes. Every
|
||||
recovery action is represented in the append-only Platform Audit. Two factors
|
||||
are mandatory for the initial service; two separate human approvers are not.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Platform identity, invitation, standing grant, server-side session, platform
|
||||
audit, and emergency-grant persistence must be distinct from customer
|
||||
`User`, `OrganizationMembership`, Project permission, and Project/Run audit.
|
||||
- `requirePlatformAdmin` must resolve the dedicated session and an active
|
||||
standing or unexpired emergency grant on every request. It is never an
|
||||
Organization-role override.
|
||||
- The legacy `PlatformRoleAssignment`/`TEACHER` schema is not a compatible
|
||||
shortcut and must be migrated or replaced before the platform panel ships.
|
||||
- Bootstrap and recovery remain direct database/control-plane operations, but
|
||||
only through versioned, asserted, auditable procedures rather than arbitrary
|
||||
SQL.
|
||||
- Exact numeric invitation/session/step-up/emergency durations, audit retention
|
||||
and export policy, recovery-key custody rotation, and future multi-party
|
||||
approval remain follow-on operational decisions. They may not weaken the
|
||||
identity separation, last-administrator protection, fail-closed audit, or
|
||||
two-factor recovery invariants fixed here.
|
||||
Reference in New Issue
Block a user