screentinker/server/test/agency-list.test.js
ScreenTinker 6d152a5ccf feat(api): GET /api/agency/playlists - a token's designated targets (#73)
The portal needs to show an agency which playlists it may post to. New read surface on the
security primitive, built with write-path rigor: the confinement query lives in
lib/agency-targets.js (own token + bound workspace only) and is bite-tested four ways -
own targets yes; another token's, outside the allowlist, and cross-workspace all NO;
neutralizing the t.token_id filter makes it go red. Real-path wiring + the portal's
graceful 401 trigger asserted in the integration suite. No :playlistId, so router.param
doesn't apply - the query is the seam.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:08:07 -05:00

36 lines
1.8 KiB
JavaScript

'use strict';
// #73: GET /api/agency/playlists is a new READ surface on the security primitive, so prove
// it confines with write-path rigor. The query (lib/agency-targets.js) must return ONLY this
// token's designated, in-workspace playlists. Four ways it could leak, all asserted here;
// neutralizing the t.token_id filter makes it go red (the bite).
const { test } = require('node:test');
const assert = require('node:assert/strict');
const Database = require('better-sqlite3');
const { listDesignatedPlaylists } = require('../lib/agency-targets');
const db = new Database(':memory:');
db.exec(`
CREATE TABLE api_token_targets (token_id TEXT, playlist_id TEXT, PRIMARY KEY(token_id, playlist_id));
CREATE TABLE playlists (id TEXT PRIMARY KEY, name TEXT, status TEXT, workspace_id TEXT);
INSERT INTO playlists (id, name, status, workspace_id) VALUES
('p1','One', 'published','wsA'),
('p2','Two', 'published','wsA'),
('p3','Three','published','wsA'),
('pX','Cross','published','wsB');
INSERT INTO api_token_targets (token_id, playlist_id) VALUES
('tokA','p1'), -- own + in-workspace -> MUST appear
('tokA','pX'), -- own but CROSS-workspace -> must NOT appear
('tokB','p2'); -- ANOTHER token's -> must NOT appear for tokA
-- p3 is in wsA but designated to no one -> OUTSIDE the allowlist -> must NOT appear
`);
test('#73 GET targets: returns ONLY this token\'s designated, in-workspace playlists', () => {
const a = listDesignatedPlaylists(db, 'tokA', 'wsA').map(r => r.id);
assert.deepEqual(a, ['p1'],
'tokA sees ONLY p1 - not p2 (another token), not p3 (outside allowlist), not pX (cross-workspace)');
const b = listDesignatedPlaylists(db, 'tokB', 'wsA').map(r => r.id);
assert.deepEqual(b, ['p2'], 'tokB sees ONLY p2');
});