Skip to content

feat: per-API-key repo scoping (fail-closed) + auth-boundary & stack-trace diagnosis tests#12

Merged
csharp36 merged 7 commits into
mainfrom
feat/apikey-repo-scoping
May 30, 2026
Merged

feat: per-API-key repo scoping (fail-closed) + auth-boundary & stack-trace diagnosis tests#12
csharp36 merged 7 commits into
mainfrom
feat/apikey-repo-scoping

Conversation

@csharp36
Copy link
Copy Markdown
Owner

Summary

Brings API-key callers under the same per-repo least-privilege authorization the OAuth path already enforces, then adds the two requested test suites. Previously the per-repo gate in QueryExecutor.executeQuery fired only for oauth callers — any valid API key could read every indexed repo (source, symbols, file tree, search). On a shared multi-repo indexer that exposed other teams' sensitive code.

  • Per-key repos: allow-list carried on CallerIdentity.allowedRepos, enforced in the existing executeQuery choke point:
    • repos: ["*"] → full read access (explicit, auditable)
    • repos: [a, b] → restricted to those repos
    • repos: omitted → denied all queries (fail-closed) — every key must declare its scope
    • Repo-less/system tools (get_index_health, query_audit_log, verify_audit_chain) require a ["*"] key, consistent with OAuth. stdio (local subprocess) stays trusted/unscoped. SCIP upload (separate write path) is unchanged.
  • PermissionBoundaryTest — proves an unentitled remote caller leaks nothing meaningful across 5/4 tools, for both OAuth and scoped API keys; plus allowed-access controls, fail-closed-on-resolver-error, and audit-of-denials. (Closes a real gap: no end-to-end denial test existed.)
  • StackTraceDiagnosisTest — poster-child "paste a stack trace → diagnose" flow: frame → get_symbol_detail (file+method+line) → find_referencesfind_implementationsget_file_summarysearch_code.
  • ApiKeyScopeGateTest — fast unit tests for the gate (allow/deny/wildcard/unscoped/repo-less).
  • Docs in CLAUDE.md.

Implements the plan in docs/superpowers/plans/2026-05-30-apikey-repo-scoping-and-boundary-tests.md.

⚠️ Breaking config change

Shipping this denies every existing API key until it is given a repos: scope (the fail-closed contract). Existing keys need repos: ["*"] or an explicit list added. The un-rotated dev-* tokens are affected.

Test Plan

  • ./gradlew test — full unit suite green (incl. ApiKeyScopeGateTest, updated CallerIdentityTest/ApiKeyAuthenticatorTest/ConfigLoaderTest)
  • ./gradlew integrationTest for PermissionBoundaryTest, StackTraceDiagnosisTest, SemanticQueryTest, StreamableHttpTransportIntegrationTest — green
  • CI build green on PR

🤖 Generated with Claude Code

@csharp36 csharp36 merged commit 677aa06 into main May 30, 2026
1 check passed
@csharp36 csharp36 deleted the feat/apikey-repo-scoping branch May 30, 2026 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant