capture #49d: POST /capture REST adapter + OAuth2 + I1 gate (server-derived origin) #53
Closed
opened 2026-06-22 20:27:28 +00:00 by mathias
·
1 comment
No Branch/Tag Specified
main
fix/pipeline-writes-158
fix/edit-path-io-192
fix/create-regular-188
fix/guard-special-179
fix/linkcheck-keeps-write-178
fix/write-dir-redirect-173
fix/tunnel-detect-174
fix/pipeline-root-157
w3/154-mcp-auth-wiring
fix/tunnel-traversal
test/in-brain-targets-171
fix/brain-scan-root-157
fix/graph-wiki-root-157
fix/vectorstore-root-157
fix/notes-root-157
fix/search-root-157
fix/brainwide-root-157
fix/raw-symlinks-153
feat/symlink-tripwire-157
fix/rest-auth-149
fix/123-brain-edit-envelope-check
feat/106-page-aware-extraction
fix/105-source-drift-on-main
fix/104-surface-merge-conflicts-on-main
agent/b1-compile-on-ingest
agent/104-surface-merge-conflicts
agent/105-source-drift
agent/107-loud-unconfigured-alerting
feat/brain-read-edit
fix/capture-i1-refusal-names-target
renovate/configure
feat/consolidate-single-harness
icebox/cmd-routing
feat/brain-pending-promote
fix/close-session-classification-refresh
fix/capture-summarywriter
v0.24.0
v0.23.1
v0.23.0
v0.22.0
v0.21.1
v0.21.0
v0.20.1
v0.20.0
v0.19.1
v0.19.0
v0.18.4
v0.18.3
v0.18.2
v0.18.1
v0.18.0
v0.17.0
v0.16.1
v0.16.0
v0.15.0
v0.14.0
v0.13.2
v0.13.1
v0.13.0
v0.12.1
v0.12.0
v0.11.2
icebox/cmd-routing-2026-07-01
v0.11.1
v0.11.0
v0.10.0
v0.9.0
v0.8.0
v0.7.0
v0.6.0
v0.5.0
v0.4.1
v0.4.0
v0.3.0
v0.2.0
v0.1.0
Labels
Clear labels
agent/ready
blocked/client
blocked/supplier
blocked/upstream
risk/high
risk/low
risk/medium
size/l
size/m
size/s
size/xs
status:dispatch
status:dispatched
status:review
status:reviewing
type/chore
type/decision
type/docs
type/feat
type/fix
type/ops
type/research
type/test
Meets the agent-ready contract; authorizes unattended execution
Waiting on the client
Waiting on a supplier
Waiting on an upstream project or vendor
Irreversible, security-relevant, or control plane
Reversible, local, test-covered
Touches shared state, deploys or data
Too big - split it
Under two days
Under half a day
Under an hour
Maintenance, no behaviour change
Human decision required; never agent/ready
Documentation only
New capability
Corrects broken behaviour
Infrastructure, deploy, runtime
Investigate; output is a finding, not code
Test coverage only
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mathias/hyperguild#53
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Parent: #49 · Spec:
specs/capture-bdd-spec.md§1, §4.1–4.2 · Depends on: #50 (tags), #51 (use-case), #52 (tracker) · Blocks: #49fScope
The HTTP door + the load-bearing I1 gate. Wire
CaptureService(#51) behindPOST /capturewith OAuth2/JWT auth, implement the server-derived harness-origin → trust-zone mapping (Q2/§4.2), and enforce the I1 sovereignty gate using the classification tags (#50). After this, capture works end-to-end for harnesses that can run against the REST endpoint directly (Claude Code CLI, Agentsquad) — the relay (#49f) is not required for these.This is where the gate stops being theoretical, so it's downstream of the taxonomy, the use-case, and the tracker.
What to build
POST /captureadapter — JWT-authed (reuse existing Authentik/JWT middleware), thin: decodeCaptureRequest→ callCaptureService.Capture→ encodeCaptureReceipt. No business logic in the handler.context.harnessis descriptive-only, NEVER a gate input. A caller-asserted label that disagrees with the derived origin is logged as a security event.dry_runvalidates + returns would-be receipt.Acceptance criteria
POST /captureJWT-authed, thin adapter (decode → use-case → encode)context.harnessnot a gate inputdry_runwrites nothingtask checkgreen; secret-handling respectedinfra/k3s/apps/**(I3) — coordinate with infraNotes
Gherkin scenarios this makes live: the entire I1 sovereignty block + classification-model-(C) block in the spec. This is the milestone where "capture works" is true for direct-REST harnesses. The audit path (#49e) and relay (#49f) build on top.
Implemented — PR #59 (open, base main)
PR: #59 · branches from
main(#50/#51/#52 merged).I1 gate (in the use-case):
CaptureContext.Origin(server-derivedZone); confidential + us-nexus → refuse before any write (ErrSovereigntyRefused), refusal audited. Asserted-vs-derived harness mismatch → security event. Gate fires only on explicit us-nexus so the unset default can't misfire.REST adapter (
capturehttp): auth (static wins, then Dex JWT) returns the principal + auth path the chassis middleware hides → derives origin viaOriginResolver. Principal/origin server-set, overwriting any forged body (TestCallerCannotForgeOrigin). Status: 200 / 207 partial / 502 all-failed / 403 refusal / 400 validation.Origin → zone (spec §4.2, made concrete): static token + allowlisted JWT subjects → sovereign; every other principal → us-nexus (fail safe). Sovereign JWT subjects via
BRAIN_CAPTURE_SOVEREIGN_PRINCIPALS.Audit: minimal
audit.SlogSink(I5 record to logs); #54 swaps in loki+buffer+degradation behind the same interface.Wiring:
/capturereuses the MCP server's graph-wired brain store (one impl, newBrainStore()accessor) + classification tags; mounts only when Gitea is configured.All ACs met;
task checkgreen; token only ever in the auth header (never logged/argv).Testability note: handler depends on a small
Validatorinterface (chassis*JWTValidatorsatisfies it) so the JWT/origin path is testable without a live JWKS.Deferred per the epic: real audit sink + degradation → #54; ai-sessions
SummaryWriter→ nil for now (summary item fails as partial, rest lands); k3s manifest (I3) → infra/#55.Brain:
wiki/hyperguild/decisions/gate-on-server-derived-signals-fail-safe.Milestone: with #50–#53 merged, capture works end-to-end for direct-REST harnesses (Claude Code CLI, Agentsquad). Remaining: #54 (I5 audit path + classification-aware degradation) → #55 (central relay + I2 ledger, the heaviest security weight).