docs: describe the write-ahead audit model and bring the contract files up to date

This commit is contained in:
Latte committed 2026-10-14 18:01:55 +02:00
1 parent 59d0e43aae
commit 8ff67f5859
5 files changed
+38 -30

No files matched your search

+21 -13
View File
@@ -19,7 +19,11 @@ Full access by default (ADR 0001). The server does not decide what is safe; the
owner restricts exposure with `READ_ONLY`, `TOOLSETS`, `DISABLED_TOOLS` and the
scope of the Gitea token. Everything else below is load-bearing:
- Every tool call produces one audit event in the hash-chained, append-only log.
- Every tool call is audited in the hash-chained, append-only log with a write-ahead
model: a `tool_call_started` entry is written before the call executes (the call is
refused with `audit_unavailable` when that entry cannot be written), and a
`tool_invocation` entry with the outcome is written after it. Anything that counts
calls in the log counts `tool_invocation` entries.
- No secrets or tokens in logs, errors, audit entries or results. Output is
passed through secret masking (`SECRET_DETECTION_MODE`, default `mask`).
`Identity.token` and every `SecretStr` setting never appear in `repr`.
@@ -62,18 +66,21 @@ src/aegis_gitea_mcp/
errors.py ToolError, GiteaAPIError(status, kind, message)
audit.py hash-chained audit log; security.py secret masking;
response_limits.py, rate_limit.py (HTTP), request_context.py, logging_utils.py
server.py, transports, oauth/ planned (chunks B4, B5), not present yet
scripts/ generate_catalog.py, validate_audit_log.py, ci/, check_docs.py (B11)
server.py the low-level SDK Server: tool list, call dispatcher, audit calls
transports.py stdio runner and the streamable HTTP app
auth.py static bearer verification and identity resolution
oauth/ per-user OAuth: provider, resolver, encrypted store, upstream, callback
scripts/ generate_catalog.py, validate_audit_log.py, check_docs.py, ci/
spec/ pinned Gitea swagger
tests/integration/ live Gitea in Docker (harness.py), opt-in
tests/integration/ live Gitea in Docker (harness.py), opt-in; sweep of every tool
tests/mcp/ MCP smoke tests (stdio, HTTP, container image), opt-in
tests/security/ security regression suite
```
Modules marked planned do not exist yet. Request flow (target):
client -> SDK transport and auth verifier -> `Identity` -> toolset/read-only
filters -> schema validation -> executor (Gitea call with the identity's token,
optional `sudo`) -> limits and masking -> result envelope (ADR 0005) -> audit.
The executor and the catalog exist; the server and transports that connect them
to MCP clients do not yet.
Request flow: client -> SDK transport and auth verifier -> `Identity` ->
toolset/read-only filters -> schema validation -> `tool_call_started` audit entry
-> executor (Gitea call with the identity's token, optional `sudo`) -> limits and
masking -> result envelope (ADR 0005) -> `tool_invocation` audit entry.
## Commands
@@ -87,13 +94,14 @@ make lint | format | test | test-integration | run | validate-audit | docker-bui
```
Live-Gitea integration tests carry the `integration` marker and run only with
`AEGIS_INTEGRATION=1` (`make test-integration`).
`AEGIS_INTEGRATION=1` (`make test-integration`); the MCP smoke tests under
`tests/mcp` carry `mcp_smoke`. `tests/integration/sweep_baseline.json` pins the
expected outcome of every tool, see `tests/integration/README.md`.
## Quality gates
Ruff (E,W,F,I,B,C4,UP,S,SIM,RUF), ruff format, mypy and pytest must be green
before every commit. Coverage threshold is 80% until the final chunk and 90%
from then on; never lower it. Tests must not write outside `tmp_path`
before every commit. The coverage threshold is 90%; never lower it. Tests must not write outside `tmp_path`
(the autouse fixture in `tests/conftest.py` isolates env, cwd, `DATA_DIR`,
`AUDIT_LOG_PATH` and singletons). Python 3.10+, line length 100, public
functions need docstrings and type hints. Documentation lives under `docs/`;