fix(mcp): enforce product scope guardrails
This commit is contained in:
parent
91559004a8
commit
9d4271308c
@ -42,7 +42,15 @@ export interface NotesMcpTool<TInput> {
|
|||||||
execute(args: TInput, req: NotesMcpRequest): Promise<unknown>;
|
execute(args: TInput, req: NotesMcpRequest): Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requireProductScope(req: NotesMcpRequest): void {
|
||||||
|
const requestProductId = req.jwtPayload?.productId;
|
||||||
|
if (requestProductId && requestProductId !== PRODUCT_ID) {
|
||||||
|
throw new Error(`Product scope mismatch: expected '${PRODUCT_ID}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function requireUserId(req: NotesMcpRequest): string {
|
function requireUserId(req: NotesMcpRequest): string {
|
||||||
|
requireProductScope(req);
|
||||||
const userId = req.jwtPayload?.sub;
|
const userId = req.jwtPayload?.sub;
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
throw new Error('Authenticated user is required');
|
throw new Error('Authenticated user is required');
|
||||||
|
|||||||
@ -34,10 +34,10 @@ Parent: `docs/ROADMAP.md`
|
|||||||
|
|
||||||
# Phase A3 — Operational Hardening
|
# Phase A3 — Operational Hardening
|
||||||
|
|
||||||
- [ ] Workspace/product scoping guardrails
|
- [x] Workspace/product scoping guardrails
|
||||||
- [ ] Audit verification for mutating tools
|
- [ ] Audit verification for mutating tools
|
||||||
- [ ] Safe usage docs and runbooks
|
- [ ] Safe usage docs and runbooks
|
||||||
- [ ] Regression tests for mutating tool paths
|
- [x] Regression tests for mutating tool paths
|
||||||
- [ ] Review `mcp-server` integration against auth boundaries
|
- [ ] Review `mcp-server` integration against auth boundaries
|
||||||
|
|
||||||
# A2A Follow-On Work
|
# A2A Follow-On Work
|
||||||
@ -71,6 +71,10 @@ Parent: `docs/ROADMAP.md`
|
|||||||
- an adapter that exports the note tools in a shape compatible with shared `mcp-server` registration
|
- an adapter that exports the note tools in a shape compatible with shared `mcp-server` registration
|
||||||
- a clear product-side handoff point for future shared-server wiring
|
- a clear product-side handoff point for future shared-server wiring
|
||||||
- backend verification still passing after the adapter layer was introduced
|
- backend verification still passing after the adapter layer was introduced
|
||||||
|
- 2026-03-10 — Product-side MCP hardening advanced:
|
||||||
|
- executable tools now reject mismatched `productId` scope at runtime
|
||||||
|
- regression coverage now asserts mutating calls do not persist when scope is invalid
|
||||||
|
- core tools remain workspace-scoped through input contracts and repository calls
|
||||||
|
|
||||||
# Open Questions
|
# Open Questions
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ Parent: `docs/ROADMAP.md`
|
|||||||
- [x] MCP tool tests
|
- [x] MCP tool tests
|
||||||
- [ ] Approval workflow tests
|
- [ ] Approval workflow tests
|
||||||
- [ ] Audit verification tests
|
- [ ] Audit verification tests
|
||||||
- [ ] Regression coverage for agent-mediated note changes
|
- [x] Regression coverage for agent-mediated note changes
|
||||||
|
|
||||||
# Phase Q3 — Release
|
# Phase Q3 — Release
|
||||||
|
|
||||||
@ -53,6 +53,7 @@ Parent: `docs/ROADMAP.md`
|
|||||||
- `backend` `npm run typecheck` passes
|
- `backend` `npm run typecheck` passes
|
||||||
- `backend` `npm test` passes
|
- `backend` `npm test` passes
|
||||||
- MCP contract tests and executable MCP tool tests now pass
|
- MCP contract tests and executable MCP tool tests now pass
|
||||||
|
- MCP scope-guard regression tests now pass for invalid product-scoped mutating requests
|
||||||
|
|
||||||
# Open Questions
|
# Open Questions
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user