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:
Latte committed 2026-10-14 15:34:48 +02:00
1 parent 2b99644ec5
commit 8b7bb7205c
10 files changed
+36323 -37

No files matched your search

+40
View File
@@ -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.