Add a `milestone` argument to `create_issue` and `update_issue` accepting
either a numeric milestone id or a title (resolved case-insensitively against
open and closed milestones, with a clear error for unknown titles). On
`update_issue`, `milestone: 0` clears the milestone. A BeforeValidator rejects
booleans so they are not silently coerced to an id.
Gitea Projects (Kanban boards) were investigated for #22 and are intentionally
left unsupported: Gitea 1.26.2 exposes no project endpoints in its REST API.
Documented this in api-reference.md and refreshed the (stale) write-mode tool
list to cover all 16 write tools.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves the long-standing problem that label tools passed names while Gitea's
API requires numeric label ids.
- gitea_client: add _resolve_label_ids() helper; create_issue and add_labels now
resolve label names to ids (case-insensitive) and raise a clear "Unknown
label(s)" error instead of a generic 500.
- New tools: remove_labels (by name) and update_label (located by current name).
- Register both write tools and document the name-based label contract.
- Tests: resolver mapping + unknown-label error, add_labels id translation,
update_label and remove_labels handlers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously list_repositories was blocked in service-PAT mode because it has no
repository target for the per-user permission check, so users could not list
their repositories at all (the connector surfaced a generic error).
list_repositories now returns only the repositories the signed-in user owns or
contributes to, instead of everything the bot token can see:
- gitea_client.py: add list_user_repositories(login) — resolves the user id and
queries /api/v1/repos/search with the uid filter.
- repository.py: list_repositories_tool uses the user-scoped path when a service
PAT is configured and a user login is present; pure-OAuth mode still uses the
user's own /user/repos.
- server.py: allow list_repositories through the service-PAT guard (it is scoped
to the user in the handler); all other tools still require a repository target.
- README.md: document the new user-scoped behavior and its visibility caveat.
Tests: user-scoped client method (uid resolution + unknown user), PAT-mode tool
scoping, and conftest now clears the request context between tests to prevent
contextvar login leakage across files.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ref-like tool arguments (ref, sha, base, head) were only length-limited
and were interpolated unencoded into Gitea API URL paths (get_tree,
get_commit_diff, compare_refs). Because httpx collapses ".." path segments
(RFC 3986), a crafted value such as "../../../../owner/repo/contents/secret"
escaped the declared owner/repo prefix. In service-PAT mode this allowed a
user authorized on one repository to read arbitrary repositories the service
token could reach, and in OAuth mode it bypassed the policy engine's
per-repository rules (which never see ref values).
Two defense layers:
- arguments.py: add _validate_git_ref / GitRef that rejects ".." path
segments, leading "/", backslashes, null bytes, control chars, whitespace,
and "?"/"#", while preserving legitimate slash refs (feature/foo, v1.2.3).
This is what actually closes the traversal.
- gitea_client.py: defense-in-depth urllib.parse.quote() on owner/repo
(safe="") and ref/sha/base/head/filepath (safe="/") in every repo URL
builder, mirroring the existing pattern in server.py.
Tests: negative cases for traversal/unsafe chars across all four fields,
positive cases for slash-containing refs, length-bound regression, and a
URL-layer confinement check. Full suite green (176 passed), coverage 85.64%.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a GiteaOAuthValidator for JWT and userinfo validation and
fallbacks, add /oauth/token proxy, and thread per-user tokens through
the
request context and automation paths. Update config and .env.example for
OAuth-first mode, add OpenAPI, extensive unit/integration tests,
GitHub/Gitea CI workflows, docs, and lint/test enforcement (>=80% cov).