feat: local stdio package + safe full-API coverage #59
Reference in New Issue
Block a user
Delete Branch "feat/local-package-and-full-coverage"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Refactors AegisGitea-MCP into a transport-agnostic core + two thin adapters and ships a local stdio package alongside the existing public HTTP/OAuth server, with safe full-API coverage and resource-type-aware authorization. The public HTTP/OAuth server behavior is unchanged.
registry.pyis the single name→handler source of truth consumed by both adapters. Core handlers raise the transport-agnosticerrors.ToolError(no morefastapi.HTTPExceptionin the core); the HTTP adapter maps it back toHTTPException. A subprocess boundary test asserts the core imports nofastapi/uvicorn/starlette.stdio_app.py(officialmcpSDK) runsuvx aegis-gitea-mcp— single-user, PAT-owner identity, no OAuth. It resolves the PAT owner (GET /user), pins request context, and runs the same policy +WRITE_MODE+ secret sanitization + audit; it skips only the per-user repo probe (the operator is the token owner). Audit log falls back to a per-user state path.[server]extra (fastapi/uvicorn/PyJWT/python-multipart). Console scriptsaegis-gitea-mcp(stdio) andaegis-gitea-mcp-server(guarded HTTP entry). Version → 0.2.0.uv buildproduces sdist + wheel.Authorization model (every decision fails closed)
Enforced in service-PAT mode on top of policy +
WRITE_MODE(pure-OAuth mode defers to the user's token at Gitea):repositoryorguser_owned(/users/{x},/packages/{owner})user_self(/user,/notifications)misc_globaladminRAW_API_ALLOW_SENSITIVE=trueand a verified site adminunknown/ unverifiable / transport errorgitea_requestadds a deterministic write classifier (a render-only override table can only downgrade provably side-effect-free POSTs to reads, never upgrade — a write can't slip pastWRITE_MODE), a known-path gate (unknown prefix → deny), and the pre-existing admin/credential denylist.Verification
uv build→ sdist + wheel;uvx --from ./dist/<wheel> aegis-gitea-mcpinstalls 34 core deps (no FastAPI) and runs the console script end-to-end.Assumptions / deferred
list_organizations(/user/orgs) stays denied in service-PAT mode because it returns the bot's orgs (fail-closed, safe). Follow-up: make it user-scoped via/users/{login}/orgsso it can be allowed.structlogretained as a core dep per the brief though currently unused insrc.Notes
HEAD → feature → dev → main. This PR targetsdev;dev/mainare expected to be protected. The publish workflow runs on av*tag..gitea/workflows/publish.ymlbuilds withuvand publishes to the Gitea PyPI registry on tag, gated on lint + tests, usingGITEA_PACKAGE_USER/GITEA_PACKAGE_TOKENsecrets (fails loudly if absent; public PyPI intentionally not published).🤖 Generated with Claude Code