Repository navigation
Conversation
|
/review |
|
Important CHANGES REQUESTED What This PR DoesAdds How It Works
Findings
Finding Details🟡 F1: Approval contract is speculative
The caller also treats every Requested change: either drop the approval path until #5 is agreed, or gate it on an unambiguous proxy-owned marker (for example a dedicated response header) rather than the bare status code. Once #5 lands, derive the mock from that spec. 🟡 F2: Not runnable against Discord as submitted
The README discloses these gaps, but the PR title calls this a "reference client". Requested change: retitle/scope it as a proposal plus mock, or land it after a per-route credential scheme exists so at least the read path works end-to-end. 🟡 F3: Write-grant guidance fails config validation
Requested change: use the prefix form 🟡 F4: Committed credential materialThe README, Requested change: use obvious placeholders in 🟡 F5: Caller input validation
The proxy rejects much of this later, but an example that others copy should fail at its own boundary. Requested change: validate snowflake IDs and 🟡 F6: Mock-only test coverage
🟢 F7: Clear disclosureThe README states the Bot/Bearer gap and the mock's limitations up front instead of hiding them. 🟢 F8: Fail-safe defaultsWrites are disabled with an explicit warning about Phase 1 allow/deny semantics, the bot token is a store reference that never reaches the caller, and the PR touches no crate code. Baseline Check
What's Good (🟢)
Addressing External Reviewer Feedback@thepagent
✅ Addressed: this comment is the requested review. 5. Three Reasons We Might Not Need This PR
|
Implements the caller side of #6 as a self-contained example under
examples/muse-discord/. Nothing here touches the proxy core.What's inside
identity.toml— example config in the real schema (crates/ap-core/src/config.rs): amuseidentity (config holds only the caller key's sha256), adiscordroute, a credential store reference, and grants. Reads (GETon the channel/guild prefixes) are granted. Write grants are included but commented out: Phase 1 policy only allows or denies, so enabling them today would execute writes immediately — they are meant to be enabled together withrequire_approvalfrom FR: require_approval policy action — human-in-the-loop approval for gated requests #5.caller.py— reference caller (Python, stdlib only) in the exact wire shape ofap-client/the pipeline:/ap/<caller-key>/<route><path>, surrogate asBearer aps_...in the route's surrogate header. It also implements the proposed FR: require_approval policy action — human-in-the-loop approval for gated requests #5 outcome flow (202 + request id, poll the caller-scoped outcome endpoint) — against a Phase 1 proxy nothing returns 202, so that path simply never triggers.mock_proxy.py— a stand-in proxy implementing the caller-facing contract (caller-key digest check, surrogate form, parked/executed/denied/expired) so the example runs without a deployment. No real Discord call ever happens; the owner side is represented by clearly-marked test-only admin endpoints.test_caller.py— end-to-end tests: immediate read, park → approve → executed, park → denied, park → expired, bad surrogate refused. All five pass.README.md— the integration guide: protocol summary, policy walkthrough, session issuance/revocation for a Muse caller (registrar on the owner's device, per the Support Muse as a caller: route custom-connector outbound operations through auth-proxy for audit and approval #6 discussion), and security notes.Finding worth flagging: credential scheme
The forwarder always sets the credential header as
Bearer <secret>(crates/ap-proxy/src/forward.rs,credential_value). Discord bot tokens must be sent asBot <token>, so a live Discord upstream cannot authenticate against Phase 1 as shipped — reads and writes alike; storingBot <token>as the secret doesn't help because the prefix is prepended unconditionally. The README documents this and proposes the minimal fix (a per-routecredential_scheme, defaultBearer, e.g."Bot"). Deliberately not in this PR since it touches the proxy core — filing as its own change for review.Refs #5, #6.