feat(auth): add read-only API keys (API_KEYS_READONLY) - #69
Merged
Conversation
API_KEYS was a flat list where every token granted full read, write and delete over the REST API, so there was no safe credential to hand an external consumer of a hosted dataset. Add API_KEYS_READONLY: those tokens authenticate but are limited to GET/HEAD/OPTIONS on REST (403 otherwise) and to non-write MCP tools. The read-only tool set reuses the existing MCP_TOOLS_PROFILE category metadata (drop 'write') rather than a second classification. - API_KEYS keeps full access for backward compatibility; the server warns at startup when no read-only keys are configured - a token listed in both variables is read-only (deny wins) - an MCP session is pinned to the scope of the key that opened it, so a read-only token cannot reuse a read/write session - plugin tools have no category, so read-only sessions drop them Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
API_KEYSwas a flat comma-separated list and every token in it was equal: full read, write and delete over the REST API.MCP_TOOLS_PROFILE=readonlygates only MCP tool listing, not REST routes. So any valid token authorizedPOST /vcons,POST /vcons/batch,PUT|DELETEon tags, andDELETE /vcons/{uuid}— one request could destroy a corpus. There was no safe credential to hand an external consumer of a hosted dataset (e.g. the public IETF demo set).Change
Add
API_KEYS_READONLY. Those tokens authenticate but:GET,HEAD,OPTIONSPOST/PUT/PATCH/DELETE->403 Forbiddenread,schema,analytics,infratoolswritetools (not listed;tools/callfails)Design notes:
tok:roscoping. Colons are legal inside tokens, so parsing them would break existingAPI_KEYSvalues.restrictToReadonlydropswritefrom whateverMCP_TOOLS_PROFILE/MCP_ENABLED_CATEGORIESresolved) rather than inventing a second classification.MCP_DISABLED_*still applies on top.API_KEYSkeeps full access for backward compatibility; the server logs a startup warning when no read-only keys are configured.Tests
New
tests/api/readonly-keys.test.ts(11 tests): read-only key gets 200 onGET /api/v1/vcons, 403 onPOST /vconsandDELETE /vcons/{uuid}(handlers never invoked), full-access key still 201, unknown key 401; scope resolution incl. both-lists and legacy-API_KEYScases; MCPcreate_vconrejected viatools/calland absent fromtools/listwhen read-only.Full suite: 845 tests, 831 passed / 14 skipped.
npm run buildclean.Docs
docs/guide/configuration.md(new "API Keys and Read-Only Access" section),docs/guide/installation.md,docs/var/02-installation-guide.md,docs/var/03-configuration-guide.md,docs/api/rest-api.md,.env.example.Known gap
POST /database/analyze(query plans) is read-ish but blocked for read-only keys by the method rule — documented; the equivalentanalyze_queryMCP tool still works.Follow-up (other repo)
VCONIC/vconic-datasetsdocs/INSTALL.mdstill tells readers the token grants full write ("Connecting an MCP client" and Limitations sections); update once this lands.🤖 Generated with Claude Code