forked from EduCraft/curriculum-project-hub
137 lines
7.0 KiB
Markdown
137 lines
7.0 KiB
Markdown
# 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.
|