Implements the IssueTracker port as a real Gitea REST client (#49c) — the
new outbound dependency the brain server gains for capture.
- CreateIssue / CommentIssue / CloseIssue(+optional closing comment) over
the Gitea API. Owner is the const "mathias", never caller-supplied, so
a caller cannot redirect a write to another owner's repo.
- Token read once at construction (BRAIN_GITEA_TOKEN), held in the struct,
travels only in the Authorization header — never logged or in argv.
Error messages carry status + truncated body, never the token
(regression-tested). gitea.New returns nil when URL or token is unset,
so missing config = tracker disabled via one nil check.
- Injected into the MCP server behind the capture.IssueTracker interface
via WithIssueTracker (constructor injection, swappable/testable); main
wires it from BRAIN_GITEA_URL (default https://git.d-ma.be) +
BRAIN_GITEA_TOKEN. Consumed by the capture use-case in #53.
Tests use httptest transports: create (owner+auth header asserted),
comment, close with/without comment, error path that proves the token
never leaks into an error string.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#52's IssueTracker spec is CloseIssue(repo, number, comment). Refine the
#51 port signature to match and have the service pass the ticket body as
the closing comment (empty ⇒ close only). Keeps the close-with-comment
flow first-class rather than forcing two separate ticket items.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>