Closes#540. Implements US-007 (M-AGENT-REG) from the mosaic-comms PRD.
Endpoints (all host-token gated)
→ mints/ensures , returns .
→ manual revoke from day one; returns .
→ lists agents with ≥1 active token (reconciliation; never advertises revoked/phantom agents).
Security
Per-agent tokens are -prefixed high-entropy random; only sha256 hashes are persisted (plaintext returned exactly once, never stored/logged).
Constant-time token lookup (timingSafeEqual over equal-length hash buffers, no early-out).
Scoped: a per-agent token may only act as its own agent on (403 otherwise); host bridgeTokens stay unscoped. Register/revoke/list are host-only.
Fail-closed auth (empty/garbage/non-magt_ bearer or homeserver error → denied).
Persistence (no new infra)
Token registry lives in Matrix account_data on the AS sender user () — survives pod restart with zero PVC/volume/env. Known v1 limit (Synapse ~100KB account_data cap) documented in-code.
Review
Independent opus adversarial security review: PASS (no critical/high). Remediated the one MEDIUM (agent-slug collision where distinct alias/host pairs join to the same Matrix id — now rejected instead of silently overwriting) + regression test. LOW/INFO items (CAS on multi-replica, registry shape-validation, verifyToken-error→clean-403) documented as non-blocking follow-ups.
Closes #540. Implements US-007 (M-AGENT-REG) from the mosaic-comms PRD.
## Endpoints (all host-token gated)
- → mints/ensures , returns .
- → manual revoke from day one; returns .
- → lists agents with ≥1 active token (reconciliation; never advertises revoked/phantom agents).
## Security
- Per-agent tokens are -prefixed high-entropy random; only sha256 hashes are persisted (plaintext returned exactly once, never stored/logged).
- Constant-time token lookup (timingSafeEqual over equal-length hash buffers, no early-out).
- **Scoped**: a per-agent token may only act as its own agent on (403 otherwise); host bridgeTokens stay unscoped. Register/revoke/list are host-only.
- Fail-closed auth (empty/garbage/non-magt_ bearer or homeserver error → denied).
## Persistence (no new infra)
- Token registry lives in Matrix **account_data** on the AS sender user () — survives pod restart with zero PVC/volume/env. Known v1 limit (Synapse ~100KB account_data cap) documented in-code.
## Review
- Independent opus adversarial security review: **PASS** (no critical/high). Remediated the one MEDIUM (agent-slug collision where distinct alias/host pairs join to the same Matrix id — now rejected instead of silently overwriting) + regression test. LOW/INFO items (CAS on multi-replica, registry shape-validation, verifyToken-error→clean-403) documented as non-blocking follow-ups.
## Gates
typecheck + lint green; 39 tests pass (21 + 18 ).
Fixes #540
POST /bridge/v1/agents mints/ensures @agent-<alias>-<host> and returns a
scoped, revocable per-agent bridge token. Adds POST /bridge/v1/agents/revoke
(manual revoke from day one) and GET /bridge/v1/agents (reconciliation source
that never advertises revoked/phantom agents).
Persistence: per-agent token sha256 hashes stored in Matrix account_data on the
AS sender user (org.uscllc.mosaic_as.agents) — no new infra, survives restart.
Tokens are magt_-prefixed high-entropy random; plaintext is never persisted and
returned exactly once. Per-agent tokens are scoped: usable only to act as their
own agent on /bridge/v1/messages|typing; host bridgeTokens stay unscoped.
Registration/revoke/list are host-token-only.
Independent opus security review: PASS (no critical/high). Remediated the one
MEDIUM (agent-slug collision: distinct alias/host pairs joining to the same
Matrix id now rejected instead of silently overwriting) + regression test.
Closes#540
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.
Closes #540. Implements US-007 (M-AGENT-REG) from the mosaic-comms PRD.
Endpoints (all host-token gated)
Security
Persistence (no new infra)
Review
Gates
typecheck + lint green; 39 tests pass (21 + 18 ).
Fixes #540