docs: phase 0 audit, chunk plan, ADRs and pinned Gitea 28.1.0 swagger
Inventory and gap analysis of the 0.2.0 codebase against the full Gitea API and the official gitea-mcp toolset, the B1..B11 + security chunk plan, ADRs 0001-0006 for the full-access rebuild, SDK/OAuth research notes, and the instance swagger pinned for tool generation. The audit-logging doc moves to docs/audit-logging.md.
This commit is contained in:
1 parent
2b99644ec5
commit
8b7bb7205c
10 files changed
+36323
-37
No files matched your search
@@ -0,0 +1,40 @@
|
||||
# ADR 0004: admin-token mode and per-user OAuth mode
|
||||
|
||||
Status: accepted (2026-10-14)
|
||||
|
||||
## Context
|
||||
|
||||
Two authentication models must coexist on one deployment: an admin with full
|
||||
access, and other users who log in as themselves. Gitea is an OAuth2 provider
|
||||
but has no RFC 8414 metadata and no dynamic client registration; Mistral Le
|
||||
Chat requires dynamic client registration and Claude prefers it. Details:
|
||||
`docs/research/sdk-oauth-gitea.md` sections 4 and 6.
|
||||
|
||||
## Decision
|
||||
|
||||
- **Admin-token mode (default).** `GITEA_TOKEN` is used for every call. stdio
|
||||
always runs in this mode. On HTTP, a request carrying the static
|
||||
`MCP_BEARER_TOKEN` (constant-time comparison) runs in this mode.
|
||||
- **Per-user OAuth mode (HTTP).** The server is an OAuth 2.1 authorization
|
||||
server for MCP clients, using the SDK's `OAuthAuthorizationServerProvider`
|
||||
with dynamic client registration, and a confidential OAuth2 client of Gitea
|
||||
upstream (authorization code with PKCE S256, fixed and validated scope list).
|
||||
Our `/oauth/callback` exchanges the Gitea code, then issues our own opaque
|
||||
access and refresh tokens mapped to the user's Gitea tokens. Tool calls use
|
||||
the user's Gitea access token, so Gitea enforces that user's permissions;
|
||||
admin tools fail with Gitea's own 403 for non-admins. Upstream refresh is
|
||||
automatic.
|
||||
- **Token store.** A JSON file under `DATA_DIR` (default
|
||||
`~/.local/state/aegis-gitea-mcp`, `/var/lib/aegis-mcp` in the image), mode
|
||||
0600, values encrypted with Fernet using a key derived from
|
||||
`TOKEN_ENCRYPTION_KEY`. Our own tokens are stored only as SHA-256 hashes.
|
||||
- **Combined verifier.** One `TokenVerifier` accepts the static bearer (admin
|
||||
identity) or an issued OAuth token (user identity). The SDK requires passing
|
||||
it explicitly on the low-level server.
|
||||
- **Identity in results.** Every tool result carries `identity: {login, mode,
|
||||
sudo}`.
|
||||
|
||||
## Consequences
|
||||
|
||||
The server holds per-user Gitea tokens. That is the most sensitive asset after
|
||||
the admin token and is covered by the threat model.
|
||||
Reference in new issue
Block a user