| import { describe, it } from 'node:test'; |
| import assert from 'node:assert/strict'; |
| import { callerKeyFromRequest, extractBodyCallerSubKey, hasCallerScope } from '../src/caller-key.js'; |
|
|
| function fakeReq({ headers = {}, ip = '127.0.0.1' } = {}) { |
| return { headers, socket: { remoteAddress: ip } }; |
| } |
|
|
| describe('extractBodyCallerSubKey (v2.0.25 HIGH-3)', () => { |
| it('returns empty for body with no user signal', () => { |
| assert.equal(extractBodyCallerSubKey({}), ''); |
| assert.equal(extractBodyCallerSubKey(null), ''); |
| assert.equal(extractBodyCallerSubKey({ messages: [], model: 'm' }), ''); |
| }); |
|
|
| it('returns a digest when body.user is present (OpenAI chat convention)', () => { |
| const k = extractBodyCallerSubKey({ user: 'alice@example.com' }); |
| assert.ok(k && k.length === 16); |
| }); |
|
|
| it('different users yield different digests', () => { |
| const a = extractBodyCallerSubKey({ user: 'alice' }); |
| const b = extractBodyCallerSubKey({ user: 'bob' }); |
| assert.notEqual(a, b); |
| }); |
|
|
| it('uses Responses-style previous_response_id when no user', () => { |
| const k = extractBodyCallerSubKey({ previous_response_id: 'resp_abc123' }); |
| assert.ok(k && k.length === 16); |
| }); |
|
|
| it('does NOT inspect metadata.user_id (handled by messages.js parser)', () => { |
| |
| |
| |
| |
| assert.equal(extractBodyCallerSubKey({ metadata: { user_id: '{"device_id":"abc"}' } }), ''); |
| }); |
| }); |
|
|
| describe('callerKeyFromRequest with body', () => { |
| it('appends :user:<digest> when body has a user signal', () => { |
| const k = callerKeyFromRequest(fakeReq(), 'sk-test-key', { user: 'alice' }); |
| assert.match(k, /^api:[a-f0-9]+:user:[a-f0-9]{16}$/); |
| }); |
|
|
| it('falls back to :client:<ip+ua-digest> when body has no user signal', () => { |
| |
| |
| |
| |
| const k = callerKeyFromRequest(fakeReq(), 'sk-test-key', {}); |
| assert.match(k, /^api:[a-f0-9]+:client:[a-f0-9]{16}$/); |
| }); |
|
|
| it('two end-users on same shared API key get different keys', () => { |
| const ka = callerKeyFromRequest(fakeReq(), 'shared-key', { user: 'alice' }); |
| const kb = callerKeyFromRequest(fakeReq(), 'shared-key', { user: 'bob' }); |
| assert.notEqual(ka, kb); |
| }); |
|
|
| it('two physical clients on same apiKey land on different subkeys via IP+UA', () => { |
| |
| |
| |
| const ka = callerKeyFromRequest( |
| fakeReq({ ip: '1.2.3.4', headers: { 'user-agent': 'claude-cli/1.0' } }), |
| 'shared-key', null, |
| ); |
| const kb = callerKeyFromRequest( |
| fakeReq({ ip: '5.6.7.8', headers: { 'user-agent': 'claude-cli/1.0' } }), |
| 'shared-key', null, |
| ); |
| assert.notEqual(ka, kb); |
| assert.match(ka, /^api:[a-f0-9]+:client:[a-f0-9]{16}$/); |
| }); |
|
|
| it('same physical client across turns lands on the same subkey (reuse precondition)', () => { |
| |
| |
| const ka = callerKeyFromRequest( |
| fakeReq({ ip: '1.2.3.4', headers: { 'user-agent': 'claude-cli/1.0' } }), |
| 'shared-key', null, |
| ); |
| const kb = callerKeyFromRequest( |
| fakeReq({ ip: '1.2.3.4', headers: { 'user-agent': 'claude-cli/1.0' } }), |
| 'shared-key', null, |
| ); |
| assert.equal(ka, kb); |
| }); |
|
|
| it('omits :client: when no IP and no UA are extractable', () => { |
| |
| |
| const k = callerKeyFromRequest({ headers: {} }, 'sk-test-key', {}); |
| assert.match(k, /^api:[a-f0-9]+$/); |
| }); |
|
|
| it('falls back to header session id when no API key', () => { |
| const k = callerKeyFromRequest(fakeReq({ headers: { 'x-session-id': 'sess-xyz' } })); |
| assert.match(k, /^session:[a-f0-9]+$/); |
| }); |
|
|
| it('falls back to ip+ua when nothing else available', () => { |
| const k = callerKeyFromRequest(fakeReq({ ip: '1.2.3.4', headers: { 'user-agent': 'Mozilla/X' } })); |
| assert.match(k, /^client:[a-f0-9]+$/); |
| }); |
| }); |
|
|
| describe('hasCallerScope', () => { |
| it('true for callerKey containing :user:', () => { |
| assert.equal(hasCallerScope('api:abc:user:xyz'), true); |
| }); |
|
|
| it('true for callerKey containing :client: anywhere (v2.0.37 fallback)', () => { |
| |
| |
| assert.equal(hasCallerScope('api:abc:client:xyz'), true); |
| }); |
|
|
| it('true for session: prefix', () => { |
| assert.equal(hasCallerScope('session:abc'), true); |
| }); |
|
|
| it('true for client: prefix', () => { |
| assert.equal(hasCallerScope('client:abc'), true); |
| }); |
|
|
| it('false for bare api: without any subkey', () => { |
| |
| |
| |
| assert.equal(hasCallerScope('api:abc'), false); |
| }); |
|
|
| it('true when body carries a user signal even if callerKey is bare', () => { |
| assert.equal(hasCallerScope('api:abc', null, { user: 'alice' }), true); |
| }); |
| }); |
|
|