Skip to content

feat(mcp): stdio transport requires an API-key principal — key→EC threading, fail-closed, no system bypass (ADR-0101) #3246

Description

@os-zhuang

#3167 明确 defer 的最后一块安全项(PR #3217 / #3228 的 PR-B 均已合入)。矩阵行 mcp-stdio-authority 目前 experimental,note 里写着 ADMISSION REQUIREMENT:长驻 stdio bridge 走裸 metadataService + dataEngine(record_by_id resource 直接 dataEngine.findOne(...),无 ExecutionContext → 绕过 RLS/FLS/租户)。本 issue 落地该准入,决策记录见 ADR-0101(随实现 PR 提交,Proposed)。

决策摘要(详见 ADR-0101)

  1. D1 — stdio 必须携带一个后端 principal,形态为 API key:OS_MCP_STDIO_API_KEY=osk_...,经 @objectstack/core 的共享验证链(resolveApiKeyPrincipal / resolveAuthzContext,与 HTTP 面同一条路)解析成 ExecutionContext;resource 读改走 ql.find(..., { context }),RLS/FLS/租户按该身份生效。逐调用重解析,吊销即时生效于存活的 stdio 会话。
  2. D2 — fail-closed:开了 stdio auto-start(OS_MCP_STDIO_ENABLED=true / autoStart)但 key 缺失/无效 → 拒绝启动 stdio(响亮的配置错误,指明如何 mint key);HTTP 面不受影响。
  3. D3 — 不提供 system 旁路模式(rejected alternative):要"满权"就给平台管理员/专用 service 身份 mint 一个 key——供给凭据,而不是绕过身份。理由:可审计(归属真实身份)、可吊销、可轮换、走 posture 规则;OS_MCP_STDIO_IDENTITY=system 是刚在 feat(mcp): #3167 PR-B — stdio/HTTP off-switch split + os dev connect UX + exposure-policy docs #3217 修掉的 footgun 换名重现。

行业对齐:MCP 规范(stdio 不做传输认证、后端凭据从 env 供给)、Postgres/GitHub MCP server(按供给凭据 scope)、Anthropic agent-identity 模型(admin 预置的 scoped service 身份)。

v1 范围(实现 PR)

  • @objectstack/mcp plugin.start():读 OS_MCP_STDIO_API_KEY → 经 core 共享链解析 → 构造 EC(镜像 runtime resolve-execution-context 的映射);缺失/无效 → 拒启 stdio + 清晰报错
  • bridgeResources 系列改 principal-bound:record_by_id 等数据读携带 { context }(逐调用重解析,吊销即时生效)
  • 矩阵 mcp-stdio-authority:experimentalenforced,enforcement 指向新 gate;bridgeResources(unscoped-stdio) 探针键随实现更新(会触发 STALE → 重分类,即本次)
  • 单测:有效 key→scoped 读生效 / 无 key→拒启 / 无效(revoked/expired)key→拒启 / 吊销后存活会话的下一次读被拒
  • docs:environment-variables.mdxOS_MCP_STDIO_API_KEY;connect-mcp.mdx stdio 节更新
  • changeset(@objectstack/mcp minor,若 types 增解析器则一并)

v2(后续,不阻塞 v1)

  • os dev 便利:用已 seed 的 dev-admin 自动 mint 一个本地专用、可撤的 dev key 并在启动打印(scoped key,非旁路,方向一致)
  • 命名 service 身份 / 受限权限集 + key 轮换指引(对齐"静态 token 是主要失败模式"的行业共识)

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions