verifyToken loaded every non-revoked token and bcrypt-compared each (O(n) per request — auth-latency DoS + linear scaling). New token format vk_<selector>.<verifier>: the non-secret selector is indexed and locates exactly one row; only the verifier is bcrypt-hashed. Legacy NULL-selector tokens still verify via a fallback scan. Dropped the useless idx_agent_tokens_hash. - migration 010_token_selector.sql (adds selector col + unique partial index) - createToken/verifyToken reworked; also adds listTokenMeta (read for Yerin's token_audit tool) - tests/repos/token_selector.test.js Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
13 lines
700 B
SQL
13 lines
700 B
SQL
-- Selector+verifier tokens: make verifyToken O(1) instead of an O(n) bcrypt scan
|
|
-- over every non-revoked token (code-review-2026-06-01.md / security-sweep HIGH).
|
|
-- The selector is a non-secret public lookup key; the verifier stays bcrypt-hashed
|
|
-- in token_hash. Legacy rows keep selector NULL and verify via the fallback path.
|
|
ALTER TABLE agent_tokens ADD COLUMN IF NOT EXISTS selector text;
|
|
|
|
-- One row per selector (partial: legacy NULLs are exempt).
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_tokens_selector
|
|
ON agent_tokens(selector) WHERE selector IS NOT NULL;
|
|
|
|
-- The old hash index was useless — bcrypt hashes can't be looked up by value.
|
|
DROP INDEX IF EXISTS idx_agent_tokens_hash;
|