docs: local vs server quickstart, authz model, packaging

Reframe the README around two transports and add a local stdio quickstart with
uvx/pip and Claude Desktop / Claude Code wiring. New docs: local-quickstart.md
and packaging.md (uv build/publish). Document resource-type-aware authorization
and classified gitea_request in security.md; stdio env vars + audit-log
fallback in configuration.md; local install in deployment.md; core+adapters in
architecture.md. Add the missing root AGENTS.md contract, update CLAUDE.md with
the core/adapter layout, fail-closed invariants, and the branching flow
(HEAD -> feature -> dev -> main). Update roadmap/todo and .env.example.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 11:17:01 +02:00
parent 2859a7f917
commit 385b442b6f
13 changed files with 520 additions and 31 deletions
+10 -15
View File
@@ -8,24 +8,19 @@ Baseline (recorded Phase 0): 284 passed, 1 skipped, coverage 84.04%, threshold 8
## Phase checklist
- [x] Phase 0 — Branch from dev, baseline recorded, PLAN.md committed.
- [ ] Phase 1 — Extract transport-agnostic core + shared tool registry.
- Decouple `tools/raw_tools.py` from `fastapi.HTTPException` (core ToolError).
- Single `registry.py` owning name -> (handler, definition, read/write, resource-type).
- `server.py` consumes the registry. Boundary test: importing core pulls no `fastapi`.
- [ ] Phase 2stdio adapter (`stdio_app.py`) + packaging.
- `mcp` SDK core dep; web deps to `[server]` extra; console scripts; version 0.2.0 -> 0.3.0.
- stdio resolves PAT owner (`GET /user`), sets request_context once; policy+audit ON.
- Local audit-log fallback under user state dir.
- [ ] Phase 3 — Resource-type-aware authorization (fail-closed).
- Classify repo/user/org/admin/misc from (method, path); enforce per type.
- admin default-deny; org membership verified; user==caller; unverifiable => deny.
- [ ] Phase 4 — gitea_request classifier + full coverage by default.
- Deterministic (method, path) -> read|write with override table; unknown path => deny.
- [ ] Phase 5 — Tests: authz matrix, write-mode bypass, classifier, stdio adapter, boundary.
- [ ] Phase 6 — Docs & README (local vs server quickstart, authz model, packaging, CLAUDE.md).
- [x] Phase 1 — Extract transport-agnostic core + shared tool registry (+ boundary test).
- [x] Phase 2 — stdio adapter (`stdio_app.py`) + packaging (core + `[server]` extra, 0.2.0).
- [x] Phase 3 — Resource-type-aware authorization (fail-closed).
- [x] Phase 4 — gitea_request classifier + known-path gate (unknown path => deny).
- [x] Phase 5Tests: authz matrix, write-mode bypass, classifier, stdio adapter, boundary.
- [x] Phase 6 — Docs & README (local vs server quickstart, authz model, packaging, CLAUDE/AGENTS).
- [ ] Phase 7 — `.gitea/workflows/publish.yml` (uv build + publish to Gitea registry on tag).
- [ ] Phase 8 — Verify green + coverage >= baseline, `uv build`, push, open PR into dev.
Note: version bumped to 0.2.0 (the app already reported 0.2.0; pyproject was 0.1.0).
TODO(authz): make `list_organizations` user-scoped (`/users/{login}/orgs`) so it can
be allowed rather than denied in service-PAT mode.
## Key deltas found during orientation
- No single tool registry today: definitions in `mcp_protocol.AVAILABLE_TOOLS`,