Skip to content

serve --http (OAuth transport) ignores legacy token permissions.source_id grant — remote __all__ pinned to 'default' #2027

@JunhaoV5

Description

@JunhaoV5

Summary

The #1336 legacy-token source grant (access_tokens.permissions.source_id) is honored by src/mcp/http-transport.ts (parseLegacyTokenScope), but not by the OAuth transport that gbrain serve --http actually uses. GBrainOAuthProvider's legacy access_tokens fallback branch (src/core/oauth-provider.ts, ~line 635) only SELECT name, never reads permissions, and hardcodes sourceId: 'default' with no allowedSources.

Effect

On a multi-source brain, every remote caller authenticating with a legacy bearer token through serve --http is silently pinned to the default source:

This contradicts the CLAUDE.md invariant: "Source isolation. Every read-side op routes through sourceScopeOpts(ctx); precedence is federated array (ctx.auth.allowedSources) > scalar (ctx.sourceId) > nothing." — the OAuth transport never populates the federated array for legacy tokens, while http-transport.ts does.

Repro

  1. Multi-source brain (Postgres engine), gbrain serve --http.
  2. UPDATE access_tokens SET permissions = jsonb_set(permissions, '{source_id}', '["default","src-a","src-b"]') WHERE name='<token>';
  3. Remote MCP query with source_id: "__all__" → results only from default; tools/call whoami shows transport "legacy".
  4. Same grant via the bearer-only http-transport honors the array.

Suggested fix

In the legacy fallback of GBrainOAuthProvider, select permissions and reuse parseLegacyTokenScope (array → allowedSources + first element as scalar write floor; string → scalar; absent → 'default'), mirroring http-transport.ts. The serve's tool dispatch already threads auth: authInfo into the op context, so populating allowedSources on the AuthInfo is sufficient. Happy to PR if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions