feat: 完整游戏运维功能

This commit is contained in:
npc0-hue
2026-07-18 09:04:01 +08:00
parent f3b14b7945
commit 48b8ad8d6c
187 changed files with 16607 additions and 1140 deletions
@@ -0,0 +1,35 @@
# Design
## Session records
`AuthSessionRecord` stores only a SHA-256 token hash, user ID, issued/expiry timestamps, revoked timestamp, and rotation generation. The bearer token is returned once at login/rotation and is never stored in a snapshot. `GetCurrentUser` hashes the presented token and loads the record from the repository, rejecting missing, revoked, expired, or disabled-user sessions. The default TTL is bounded (8 hours); rotation revokes the prior generation before creating a new record. FileStore and MySQLStore snapshots load these records before serving requests.
Strict production routers deliver the platform session in an `HttpOnly`, `SameSite=Strict` cookie and omit the token from JSON, so platform_web JavaScript does not persist new raw tokens. Explicit CLI/local tooling may request a bearer response with `X-Auth-Token-Response: bearer`; the explicitly named `NewTestRouterWithCore` compatibility constructor retains the bearer response contract for existing in-process tests. All normal router constructors enforce authorization.
Run control state follows the same shape: a Run session has a bounded TTL, status, generation, capability fingerprint, and last-seen timestamp. Heartbeat/claim/ack/progress/result/cancel/reconcile/log/artifact operations must validate the current session and reject expired or revoked state.
## Signed Run envelope
HTTP Run channel requests carry `X-Run-Endpoint`, `X-Run-Timestamp`, `X-Run-Nonce`, and `X-Run-Signature`. The signature is HMAC-SHA256 over method, path, timestamp, nonce, and SHA-256 request body using the established Run session token as the channel key. Timestamps are accepted only inside a five-minute clock-skew window and each nonce is accepted once per Run session. The body is buffered and restored before JSON decoding. Legacy in-process service calls remain available for existing tests, but HTTP channel handlers reject missing/invalid signatures after session establishment. Signature errors are safe 401/403 failures and never echo token material.
## Authorization matrix
- Public: health, login, registration, and read-only marketplace/plugin discovery that contains no secret or host detail.
- Platform admin: user administration, AI provider metadata, plugin installation/registration/state, Run endpoint administration, platform metrics, audit inspection, and global job/artifact/log metadata.
- Authenticated server owner or assigned server administrator: server list/detail, runtime binding review, lifecycle, config diff/approval, logs, artifacts, distributions, dependency and client-manager actions for servers visible to that user.
- Owner or platform admin only: runtime binding writes, key reset, server administrator membership changes, destructive/archive actions.
- Run service identity: channelized control/jobs/logs/artifacts for its own endpoint and only resources addressed by a validated job/transfer/session; never browser bearer sessions.
Services repeat ownership and role checks even when a route already checked them. Cross-owner reads/writes return `forbidden`; missing/invalid/expired credentials return `unauthorized`.
## Secret boundary
Secret-bearing writes accept only controlled `secret://` references or opaque logical refs already declared by a plugin. Stored records keep references, encrypted component-key material, status, generation, and fingerprints; raw values are never returned. DTOs expose only `configured`, `secret`, `presence`, and safe fingerprint/status fields. Snapshot tests scan serialized JSON and browser responses for secret literals, paths, sockets, and credentials.
## Failure and migration behavior
Older snapshots decode absent auth/session/secret arrays as empty. Existing users remain valid but must log in again after upgrade if no session record exists. Existing Run endpoints without a persisted session require a fresh signed hello. Expired/revoked records remain durable for audit and can be pruned in a later change. No rollback step writes raw secret data.
## Deferred risks
The controlled secret reference is not a production vault and encrypted component-key material still depends on the configured platform protection boundary. KMS/HSM integration, key wrapping, and multi-resource transactions are explicitly deferred and must not be represented as complete by this change.
@@ -0,0 +1,33 @@
# Harden Platform Authentication, Authorization, and Secret Persistence
## Why
Platform account sessions and Run control sessions currently live only in process memory, so a restart invalidates valid clients and leaves revocation/expiry state implicit. Several management routes also rely on the caller reaching a UI path rather than enforcing an authenticated role or resource-ownership boundary at the API/service boundary. Existing component-key and distribution metadata is not included in the durable file/MySQL snapshot, while secret-bearing values must remain platform-owned and redacted.
## What Changes
- Persist hashed platform sessions and Run control session state with explicit issued/expiry/revoked timestamps and safe rotation.
- Require authenticated sessions for sensitive management APIs and enforce platform-admin, server-owner/administrator, and Run-service boundaries in handlers and services.
- Add a signed, timestamped Run request envelope for control/job/log/artifact channel requests where the HTTP boundary can validate a trusted Run session and reject stale/replayed messages.
- Persist existing encrypted component-key and distribution metadata in FileStore/MySQLStore snapshots, plus controlled secret metadata references and presence/fingerprint projections.
- Ensure auth failures are stable 401/403 API errors and the web client clears invalid sessions without rendering token, key, path, socket, or secret literals.
- Add regression coverage for login/reload, expiry/revocation/rotation, signed Run requests, cross-owner/role rejection, replay/clock failures, snapshot recovery, and non-disclosure.
## Goals / Non-Goals
**Goals:**
- Make session and authorization decisions durable and independently enforceable from the UI.
- Keep raw credentials, host paths, direct sockets, and provider keys out of DTOs, logs, snapshots, and browser state.
- Preserve the independent `run` repository boundary and channel priorities.
**Non-Goals:**
- A production KMS/vault, encrypted secret-value storage, durable scheduling, process supervision, logs/artifacts backends, dependency installation, self-update, client-manager lifecycle, or production scaling.
- Re-adding Run source code to this repository or claiming the later roadmap is complete.
## Impact
- `platform/`: auth/session domain, repositories, snapshots, signed Run request validation, route authorization, safe secret metadata.
- `platform_web/`: API error/session handling and safe auth capability projections.
- `plugins/`: no raw credential or direct channel access; manifest/SDK contracts remain unchanged except for regression fixtures if needed.
@@ -0,0 +1,71 @@
# Platform Authentication, Authorization, and Secret Persistence
## ADDED Requirements
### Requirement: Platform sessions are durable and bounded
The platform SHALL persist only hashed bearer-session records with user ownership, issued time, expiry time, revocation time, and rotation generation, and SHALL reject missing, expired, revoked, or disabled-user sessions.
#### Scenario: Session survives restart
- **WHEN** a user logs in, the platform store is closed and reopened, and the same bearer token is presented before expiry
- **THEN** the platform restores the session record and authenticates the user without storing the raw token
#### Scenario: Expired or revoked session is rejected
- **WHEN** an expired or revoked bearer token is presented
- **THEN** the API returns 401 and performs no protected read or write
#### Scenario: Session rotation revokes the old generation
- **WHEN** an authenticated user rotates a session
- **THEN** a new token is issued, the previous generation is revoked durably, and the previous token is rejected
#### Scenario: Browser session token is not script-readable
- **WHEN** a user logs in through the strict production router
- **THEN** the platform sets an HttpOnly SameSite session cookie and omits the raw token from the JSON response
### Requirement: Run requests use a trusted bounded channel
Run control, job, log, and artifact channel requests SHALL validate the current endpoint session and, at the HTTP boundary, a timestamped HMAC signature with a five-minute clock-skew limit and single-use nonce.
#### Scenario: Valid signed request
- **WHEN** a request is signed by the current Run session with an accepted timestamp and unused nonce
- **THEN** the request is processed for that endpoint and the nonce is recorded as used
#### Scenario: Invalid, stale, or replayed request
- **WHEN** the signature is invalid, the timestamp is outside the skew window, or the nonce was already used
- **THEN** the request is rejected with a safe authentication error and no state mutation occurs
### Requirement: Sensitive APIs enforce role and resource ownership
Sensitive user, provider, plugin, server, distribution, job, runtime-binding, audit, and channel metadata APIs SHALL enforce platform-admin, server-owner/administrator, or Run-service identity at the API and service boundaries.
#### Scenario: Cross-owner access
- **WHEN** an authenticated non-owner requests another owner's server binding, job, config, artifact, or action
- **THEN** the platform returns 403 and leaves the resource unchanged
#### Scenario: UI bypass
- **WHEN** a caller invokes a sensitive route directly without the required role or session
- **THEN** the platform rejects the call regardless of UI state or request shape
### Requirement: Core auth and secret metadata are durable and redacted
FileStore and MySQLStore SHALL persist auth sessions, Run session state, encrypted component-key metadata, distributions, and controlled secret references through the repository snapshot contract; raw tokens, keys, credentials, paths, sockets, and provider secret values MUST NOT appear in snapshots, logs, DTOs, or browser responses.
#### Scenario: Snapshot reload preserves safe metadata
- **WHEN** the store is reopened after creating a session, Run identity, component key, or secret reference
- **THEN** safe status/generation/presence metadata remains available and raw values remain absent
#### Scenario: Secret presence projection
- **WHEN** a secret reference is configured
- **THEN** API and web responses expose only presence/configured/secret flags and safe fingerprints, never the reference value or storage location
### Requirement: Web clients handle auth failures safely
The platform web client SHALL treat 401 as a session reset/re-login condition and 403 as a capability/ownership denial, without persisting or rendering raw tokens, credentials, paths, sockets, or secret references.
#### Scenario: API session expires in the console
- **WHEN** an API call returns 401
- **THEN** the client clears the bearer token and exposes a safe re-authentication state
#### Scenario: API authorization is denied
- **WHEN** an API call returns 403
- **THEN** the client reports a safe access-denied error without including secret or infrastructure details
## Deferred Requirements
- Production KMS/HSM/vault encryption and secret-value rotation are deferred.
- Durable scheduling, process supervision, logs/artifacts backends, dependency installation, self-update, client-manager lifecycle, and production scaling are outside this change.
@@ -0,0 +1,22 @@
## 1. Planning and contracts
- [x] 1.1 Add typed durable auth-session and Run-session contracts, repository interfaces, validation rules, and safe DTO projections.
- [x] 1.2 Document the auth/authorization matrix, signed envelope, replay/clock constraints, secret-ref boundary, and deferred production risks.
## 2. Durable authentication and Run trust
- [x] 2.1 Persist hashed user sessions with expiry, revocation, rotation, and reload support in MemoryStore/FileStore/MySQLStore.
- [x] 2.2 Persist Run session state and enforce bounded lifecycle plus signed timestamp/nonce validation at HTTP channel boundaries.
- [x] 2.3 Add login/session-rotation/revocation routes and safe 401/403 error behavior.
## 3. Authorization and secret boundary
- [x] 3.1 Enforce platform-admin, owner/administrator, and Run-service authorization on sensitive routes and repeat checks in services.
- [x] 3.2 Persist component-key/distribution/secret metadata through all durable snapshots without raw secret disclosure.
- [x] 3.3 Add API and service regressions for cross-owner access, expired/revoked credentials, replay, and non-disclosure.
## 4. Web and verification
- [x] 4.1 Update platform_web API/session handling for 401/403 and capability-safe projections with no secret literals.
- [x] 4.2 Add frontend regressions for session reset/denied access and secret/path/socket non-disclosure.
- [x] 4.3 Run platform, plugin, web, OpenSpec strict validation, structure checks, and risk-relevant independent Run tests; record evidence and leave later roadmap work explicitly deferred.