/** * Tests for the Learn boundary. * * The one that matters is `learn token is not a credential for anything else`. * Every other assertion here is supporting evidence for it: the design's whole * claim is that a code-holder cannot become a principal, and the way that * claim fails in practice is not a dramatic bug — it is somebody later * deciding it would be simpler to mint a `Principal` with an empty team list * and rely on capability checks downstream. That refactor passes every test * about learn resources and fails this one. * * The rest pin decisions that would otherwise fail silently: an embed resolver * that accepts a hostile host, a PATCH that promotes a supply video to * anon-visible because it validated the input instead of the merged row, and * a rate limiter whose window never closes. */ import { strict as assert } from 'node:assert'; import { describe, it } from 'node:test'; import { LEARN_CODE_TRACK, LEARN_FRAME_SRC_HOSTS, formatLearnDuration, learnEmbedUrl, learnVisibilityPermitted, resolveLearnEmbed, } from '@pig/core'; import type { Database } from '@pig/db'; import { createApp } from '../src/app'; import { loadConfig } from '../src/lib/config'; import { LEARN_TOKEN_TTL_MS, createAttemptLimiter, learnResourceCreateSchema, mintLearnToken, rateLimitKey, verifyLearnToken, } from '../src/routes/learn'; const ACCESS_CODE = 'carlthefog'; // ---------------------------------------------------------------- the embed describe('embed allowlist', () => { it('resolves a Cap share link to an embed rebuilt from the table', () => { const resolved = resolveLearnEmbed('https://video.karti.ai/s/0n6n9p83efnxbs2'); assert.equal(resolved.ok, true); assert.equal(resolved.ok && resolved.provider, 'cap'); assert.equal(resolved.ok && resolved.externalId, '0n6n9p83efnxbs2'); assert.equal(resolved.ok && resolved.embedUrl, 'https://video.karti.ai/embed/0n6n9p83efnxbs2'); }); it('accepts an embed link too, because that is what people copy', () => { const resolved = resolveLearnEmbed('https://video.karti.ai/embed/0n6n9p83efnxbs2'); assert.equal(resolved.ok && resolved.watchUrl, 'https://video.karti.ai/s/0n6n9p83efnxbs2'); }); it('refuses every shape that would put someone else’s bytes in an iframe src', () => { // Each of these is a real technique, not a hypothetical. The suffix case // is why `hosts` is an exact-match list rather than an `endsWith` check, // and the credential case is why a URL that READS as trusted to a human is // rejected on the parsed hostname instead. const hostile = [ 'javascript:alert(1)', 'data:text/html,', 'http://video.karti.ai/s/0n6n9p83efnxbs2', 'https://video.karti.ai@evil.example/s/0n6n9p83efnxbs2', 'https://evil-video.karti.ai.attacker.test/s/0n6n9p83efnxbs2', 'https://notvideo.karti.ai/s/0n6n9p83efnxbs2', 'https://video.karti.ai:8443/s/0n6n9p83efnxbs2', 'https://video.karti.ai/s/../../admin', 'https://video.karti.ai/s/0n6n9p83efnxbs2/edit', 'https://video.karti.ai/s/">', 'https://video.karti.ai/', 'not a url at all', ]; for (const candidate of hostile) { assert.equal(resolveLearnEmbed(candidate).ok, false, `should reject: ${candidate}`); } }); it('refuses a recognised but not-yet-enabled provider rather than framing it', () => { // Loom is in the table so that enabling it is a flag and a CSP host. Until // the CSP host exists, a Loom row would be a card that silently never // plays — so the row cannot be created at all. const resolved = resolveLearnEmbed('https://www.loom.com/share/0123456789abcdef'); assert.equal(resolved.ok, false); assert.equal(resolved.ok === false && resolved.reason, 'provider_disabled'); }); it('re-validates a stored id rather than trusting the database', () => { // A row written before the pattern tightened, or by a path that skipped // the resolver, must not be framed on the strength of having persisted. assert.equal(learnEmbedUrl('cap', '">