feat(sdk): add MCP authorization lifecycle - #1692
Conversation
fa78d28 to
05dda8b
Compare
05dda8b to
559479c
Compare
|
Fully or partially written by an AI agent (Claude Code Panel review — PR #1692 (feat(sdk): add MCP authorization lifecycle)Fixed point: Spec — does this implement what was asked?Source: Traced all 27 ACs against the actual implementation (
Standards — does this follow project conventions?Sources read: AGENTS.md, ADR 0348, ADR 0304, ADR 0347
No Test adequacy — do the tests independently prove the contract?Traced all 27 ACs to their named tests independently of the implementation. Most are solid: real discriminated-outcome assertions, real transport call-count/ordering checks, genuine planted malformed-frame cases (7 distinct malformed-authorization cases for AC3.3, 6 grammar-violation cases for AC4.1), and a genuinely real-wire e2e suite for AC5.5/AC6.1 (spawns the real
No blockers found; AC3.5 (single-consumption, both directions) was specifically checked and is fine. Domain — what do the specialist reviewers say?Panel: secure-code-reviewer, software-architect, code-duplication-reviewer, library-reuse-reviewer Ship-blockers
Cross-confirmed (1)
Mechanical fixes (3)
Judgement calls (1)
Polish (2)
Gaps
Summary
Most important single issue: the Standards finding — ADR 0348 asserts "no server transition" while Each axis is orthogonal — none of these mask each other. The implementation itself is faithful to the acceptance plan and the security posture is sound; the open items are documentation accuracy, two test-proof gaps in Scenario 5 (concurrency/recovery), and mechanical duplication cleanup in a PR that adds the 4th copy of an existing pattern. PANEL: ship_blockers=0 important=7 advisory=5 reviewer_failures=0 |
kantord
left a comment
There was a problem hiding this comment.
Fully or partially written by an AI agent (Claude Code /panel-review).
Full 4-axis panel review posted above: ship_blockers=0, important=7, advisory=5, reviewer_failures=0.
Requesting changes — not because of a functional defect (the implementation is faithful to all 27 ACs and the security posture is sound), but for one accuracy issue and two test-proof gaps worth closing before merge:
- Standards (important): ADR 0348 §8 states "no ... server transition" changes, but
internal/adapter/server/grpc.go'srelayMCPAuthorizationControlgained new cancel-on-EOF-while-parked-on-ask behavior that didn't exist before. The behavior itself is correct and tested — the ADR text (or the PR's "Interfaces match approved contract: Yes" framing) should acknowledge it. - Test adequacy (important): AC5.1's "concurrent flows" test drives two flows sequentially, not concurrently — it doesn't prove the independence claim it names.
- Test adequacy (important): AC1.3 never actually calls
session.mcpAuthorization(...)after a park to prove "the same Session can immediately create its lifecycle handle."
The remaining 4 important / 5 advisory Domain findings (duplicated runResult(), a 4th copy of the #claim single-consumption guard, a hand-rolled timer duplicating AbortSignal.timeout(), and a test file reinventing a fixture this same PR introduced) are mechanical cleanup, not correctness risks — worth doing while this code is fresh, not necessarily blocking if the team prefers a fast-follow.
559479c to
be4d38c
Compare
|
Addressed the three changes-requested review points on the current stacked head:
The follow-up fixed-point review also found and repaired two related relay races: EOF is remembered when it arrives before a later ordinary ask, and plan-originated asks are excluded from automatic disconnect cancellation. Automatic permission controls now use ask-scoped abort lifetimes so a retired ask cannot dispatch a late verdict. Local focused validation is green, including 329 SDK tests, SDK lint/typecheck, server adapter tests, and repository lint. The stack is synced at |
be4d38c to
727d761
Compare
727d761 to
56ddb9a
Compare
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-Authored-By: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-Authored-By: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
Co-Authored-By: Codex <noreply@openai.com> Signed-off-by: Samuele Verzi <samu@stacklok.com>
56ddb9a to
c4580cd
Compare
|
Rebased this implementation onto current I also reviewed the now-merged #1689 against this lifecycle. The features have separate authority boundaries: #1689 manages host-local direct/global MCP profiles and credentials through Focused post-rebase checks passed:
The full matrix is running in CI. |
kantord
left a comment
There was a problem hiding this comment.
Fully or partially written by an AI agent (Claude Code /panel-review).
Verified all three changes-requested items against the current head (c4580cdd2):
- ADR 0348 now documents the gRPC cancel-on-disconnect-while-parked-on-ask transition instead of claiming "no server transition."
- The AC5.1 concurrency test now genuinely overlaps two flows via
Promise.all([...])and assertsmaxActiveStreams: 2, rather than driving them sequentially. - The AC1.3 test now calls
session.mcpAuthorization(...)right after a park to prove the same released session can immediately create its lifecycle handle.
CI is green apart from k8s e2e (kind), which looks unrelated to this diff (no go.mod/go.sum changes anywhere in the PR, and perf is independently failing on main's last two pushes — reads as current CI infra flakiness, not a regression here).
The remaining Domain-axis duplication findings from the panel review (duplicated runResult(), a 4th copy of the #claim single-consumption guard, a hand-rolled timer vs AbortSignal.timeout()) are still open but were flagged as non-blocking mechanical cleanup, not part of the changes-requested reasons — fine as a fast-follow.
Approving.
Merge origin/main at 686b5e5. Incoming commits after the approved cleanup base: - 79fae4d chore(catalog): refresh models.dev curated subset (#1721) - 73309df chore(deps): bump anthropic-sdk-go (#1713) - e14c88d slack-bot: DM manual permission approvals (#1707) - 5b0db5a feat(sdk): add MCP authorization lifecycle (#1692) - 39715ed chore(deps): bump SDK npm dependencies (#1715) - 498971e plan(sdk): harden malformed-success decode errors (#1698) - 9ac4798 slack-bot: relabel session approval (#1724) - 8de41cd docs(process): route approved cleanup directly (#1720) - a711451 release v0.0.39 (#1727) - 44786d1 fix(sdk): sanitize malformed-success decode errors (#1700) - 85f97fa release TypeScript SDK v0.3.0 (#1729) - 6501b59 fix(ci): repair live compaction slot and metadata (#1728) - 8047188 chore(deps): bump toolhive-core (#1712) - 686b5e5 docs: add README diagrams (#1731) Conflict resolutions preserve the MCP authorization lifecycle from main while applying the approved alpha cleanup: Run and MCP continuation results consume canonical payload usage only; removed EventCommon usage and deprecated aliases stay removed. Keep the landed authorization acceptance record and both the Unreleased cleanup note and released v0.3.0 changelog. Regenerate API reports and user reference from the merged canonical TypeScript sources. Co-Authored-By: mecatl <noreply@mecatl.dev>
Summary
Runas a normal typed handoff, including chained authorization and exact-run continuation controlsDevelopment stage
Implementation of the contract merged through Plan / Interface PR #1687.
Contract linkage
09f76b009691dc9cbb73b75ff7e12649b36e64f9c4580cdd280d569ef080328f78d9afa7968628b0Interface conformance
Interfaces match approved contract: Yes. The #1687 amendment makes exact-run attachment parking terminal, specifies the termination matrix and correlation boundaries, rejects empty authorization IDs locally, and documents the existing relay behavior without changing protobuf fields.
Review response
The changes-requested review on this PR is addressed:
session.mcpAuthorization(...)on the same session.Relationship to direct MCP onboarding
Merged PR #1689 and this PR have separate authority boundaries. PR #1689 administers host-local direct and global MCP profiles through
mecated mcp; this PR consumesauthorization.requiredhandoffs from session-scoped ToolHive broker tools. The user guides, SDK TSDoc, generated API reference, and living architecture now state that boundary and link the two workflows.Verification
task sdk:docs:check,task site:build, andgit diff --checkpassedPlain
task testandtask docsremain host-limited on this macOS 27 machine because its installed TAPI/linker cannot parse the SDK.tbdarchitecture entries. The equivalent focused and CGO-disabled paths passed during development.Issue relationship
Closes #1469
Stack
#1686 (merged) → #1687 (merged) → #1692