Skip to content

feat(keys): enforce explicitly requested scope prerequisites - #52

Merged
drewstone merged 3 commits into
mainfrom
feat/api-key-scope-dependencies
Sep 12, 2026
Merged

drewstone merged 3 commits into
mainfrom
feat/api-key-scope-dependencies

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Apps need Run keys to include Read, but the shared issuer could mint unusable Run-only keys. Add optional scopeDependencies to createApiKeyRoutes, rejecting incomplete grants with HTTP 400 before storing them. Permissions must be explicitly requested; the issuer never expands them.

The change validates configured prerequisites and uses own entries so legitimate scopes such as toString remain usable. GTM, Creative, and Legal can share this enforcement instead of adding local issuer validators.

Validation: 508 tests pass, typecheck and build pass under Node 24.18.0. The prerequisite regressions fail against the predecessor. Independent review reproduced and resolved the inherited-property crash; regressions cover prototype-named scopes and sparse configuration. Package 0.11.2 publishes after a reviewed merge and release tag.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-12T14:15:17.509147Z acf0168 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 35e80a9415

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/api-keys.ts Outdated
const prefix = config.prefix ?? 'ak_'
const validScopes = config.validScopes ?? ['chat']
if (validScopes.length === 0) throw new TypeError('At least one API key scope is required')
const dependencies = new Map(Object.entries(config.scopeDependencies ?? {}))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve a __proto__ dependency entry

When an app uses the explicitly supported __proto__ scope and configures it with the natural typed literal scopeDependencies: { __proto__: ['read'] }, JavaScript treats that entry as the object's prototype, so Object.entries returns no pair. The router consequently skips both configuration validation and dependency enforcement and can mint a __proto__-only key; use or require a representation that reliably retains this property.

Useful? React with 👍 / 👎.

Comment thread README.md Outdated
```

Missing prerequisites return HTTP 400 with `api_key.scope_dependency` before key creation.
The issuer never adds permissions the caller did not request.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid promising that defaults are never injected

This guarantee contradicts the existing behavior in src/api-keys.ts:259-263: when a caller explicitly supplies only invalid scopes, the issuer discards them and inserts defaultScope (a case asserted by tests/api-keys.test.ts:204-218). Consumers therefore cannot rely on every issued permission having appeared in the request; either distinguish an omitted scope list from an invalid explicit list or qualify this statement to refer only to dependency expansion.

Useful? React with 👍 / 👎.

@drewstone

Copy link
Copy Markdown
Contributor Author

Both review findings are addressed in acf0168. Nonstandard dependency-record prototypes are rejected at router setup, including the ambiguous { __proto__: ['read'] } literal; computed own ['__proto__'] prerequisites remain supported and enforced. Two regressions cover denial and actual HTTP issuance. README now promises no automatic prerequisite expansion and explicitly retains existing default-scope behavior.

Final source validation: 510 tests, typecheck, and build pass under Node 24.18.0. @codex review the current delta.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: acf0168e62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independently reviewed the issuer dependency validation and its final prototype handling. Missing prerequisites are rejected before key generation/storage; transitive requirements are enforced by checking each explicitly selected scope. Own-entry Map lookup preserves prototype-named scopes, and plain-record validation rejects ambiguous object-literal prototype configuration. Sparse prerequisites fail startup validation. README now accurately distinguishes dependency rejection from the existing default-scope behavior.

Reproduced the earlier inherited-property HTTP 500, verified its correction, and independently ran tests/api-keys.test.ts on this head: 34 tests pass. No remaining blocking finding in this scoped change.

@drewstone
drewstone merged commit 1212034 into main Sep 12, 2026
3 checks passed
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.

2 participants