feat(capturehttp): POST /capture REST adapter + OAuth2 + origin resolver (#53)
The HTTP door for the capture capability. Thin: authenticate → derive trust-zone origin → decode → capture.Service → map receipt to status. - Auth mirrors the chassis Bearer precedence (static token wins, then Dex JWT) but returns the resolved principal + auth path, which the chassis middleware hides — capture needs the principal to derive the origin. Depends on a small Validator interface (the chassis *JWTValidator satisfies it) so the JWT/origin path is testable without a live JWKS. - OriginResolver maps principal → trust zone: static-token caller and allowlisted JWT subjects → sovereign; every other principal → us-nexus (fail safe, so the I1 gate refuses confidential by default). Principal and origin are server-set on the input, overwriting any body the caller sent. - HTTP status: 200 all-ok / dry-run, 207 partial, 502 all-failed, 403 on the I1 refusal, 400 on fail-closed validation. - Wired in main behind the same static+JWT credentials as /mcp, reusing the MCP server's graph-wired brain store (one implementation) and the classification tags (#50). Mounts only when a Gitea tracker is configured. Sovereign JWT principals via BRAIN_CAPTURE_SOVEREIGN_PRINCIPALS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,13 @@ func (s *Server) IssueTracker() capture.IssueTracker {
|
||||
return s.tracker
|
||||
}
|
||||
|
||||
// BrainStore returns the shared brain store (graph-wired once WithGraph
|
||||
// has run), so the capture use-case writes through the exact same
|
||||
// implementation as the MCP handlers.
|
||||
func (s *Server) BrainStore() *brainstore.Store {
|
||||
return s.store
|
||||
}
|
||||
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// MCP streamable HTTP: GET establishes the SSE stream for server-to-client events.
|
||||
if r.Method == http.MethodGet {
|
||||
|
||||
Reference in New Issue
Block a user