import test from 'node:test'; import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import { spawnSync } from 'node:child_process'; const dockerfilePath = new URL('../deploy/worker/Dockerfile', import.meta.url); const receiptsPath = new URL('../deploy/worker/receipts.json', import.meta.url); const buildScriptPath = new URL('../deploy/worker/build_image.sh', import.meta.url); const runScriptPath = new URL('../deploy/worker/run_worker_container.sh', import.meta.url); const dockerignorePath = new URL('../.dockerignore', import.meta.url); const bootstrapPath = new URL('../scripts/bootstrap_selfhost_smolvlm.sh', import.meta.url); async function recipe() { const [dockerfile, receipts, buildScript, runScript, dockerignore, bootstrap] = await Promise.all([ readFile(dockerfilePath, 'utf8'), readFile(receiptsPath, 'utf8').then(JSON.parse), readFile(buildScriptPath, 'utf8'), readFile(runScriptPath, 'utf8'), readFile(dockerignorePath, 'utf8'), readFile(bootstrapPath, 'utf8'), ]); return { dockerfile, receipts, buildScript, runScript, dockerignore, bootstrap }; } function bootstrapDefault(script, name) { const match = new RegExp(`^${name}="\\$\\{[A-Z0-9_]*:-([^}]+)\\}"$`, 'm').exec(script); assert.ok(match, `bootstrap script must declare a default for ${name}`); return match[1]; } test('the worker image pins llama.cpp and both model hashes to the bootstrap receipts', async () => { const { dockerfile, receipts, bootstrap } = await recipe(); const commit = bootstrapDefault(bootstrap, 'LLAMA_CPP_COMMIT'); const modelSha = bootstrapDefault(bootstrap, 'MODEL_SHA256'); const mmprojSha = bootstrapDefault(bootstrap, 'MMPROJ_SHA256'); // Receipts are the runtime/CI source of truth and must not drift from the host bootstrap. assert.equal(receipts.llamaCpp.commit, commit); assert.equal(receipts.llamaCpp.repository, 'https://github.com/ggml-org/llama.cpp'); assert.deepEqual(receipts.models.map(model => model.sha256), [modelSha, mmprojSha]); assert.deepEqual(receipts.models.map(model => model.file), [ 'SmolVLM2-2.2B-Instruct-Q4_K_M.gguf', 'mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf', ]); assert.match(receipts.llamaCpp.commit, /^[0-9a-f]{40}$/); for (const model of receipts.models) assert.match(model.sha256, /^[0-9a-f]{64}$/); // The image builds the same pinned revision: the build args default to the receipts. assert.match(dockerfile, new RegExp(`^ARG LLAMA_CPP_COMMIT=${commit}$`, 'm')); assert.match(dockerfile, new RegExp(`^ARG MODEL_SHA256=${modelSha}$`, 'm')); assert.match(dockerfile, new RegExp(`^ARG MMPROJ_SHA256=${mmprojSha}$`, 'm')); assert.match(dockerfile, /git fetch --depth 1 origin "\$\{LLAMA_CPP_COMMIT\}"/); assert.match(dockerfile, /git checkout --detach FETCH_HEAD/); }); test('the worker image uses digest-pinned bases and refuses floating model sources', async () => { const { dockerfile, receipts } = await recipe(); const froms = dockerfile.split('\n').filter(line => line.startsWith('FROM ')); assert.equal(froms.length, 2, 'the recipe is a build stage and a runtime stage'); for (const line of froms) assert.match(line, /@sha256:[0-9a-f]{64}/, `base must be digest-pinned: ${line}`); // The recorded receipts and the recipe must name the same immutable bases. const digests = froms.map(line => /@(sha256:[0-9a-f]{64})/.exec(line)[1]); assert.deepEqual(digests, [receipts.baseImages.build.digest, receipts.baseImages.runtime.digest]); assert.equal(receipts.baseImages.build.reference, 'nvidia/cuda:12.4.1-devel-ubuntu22.04'); assert.equal(receipts.baseImages.runtime.reference, 'nvidia/cuda:12.4.1-runtime-ubuntu22.04'); assert.doesNotMatch(dockerfile, /:latest|ggml-org\/llama\.cpp@?main|refs\/heads\/(?:main|master)/); // Weights are never baked in; the model arrives as a read-only mount. assert.doesNotMatch(dockerfile, /^COPY .*\.gguf/m); assert.doesNotMatch(dockerfile, /^ADD /m); assert.match(dockerfile, /\/models/); }); test('the worker image runs unprivileged with no default credentials and a post-load healthcheck', async () => { const { dockerfile } = await recipe(); // Directives may be wrapped with a line continuation; assert on the joined directive text. const directives = dockerfile.replace(/\\\n\s*/g, ' '); const user = /^USER (?!root)(\S+)$/m.exec(dockerfile); assert.ok(user, 'the runtime stage must drop to an unprivileged user'); assert.match(user[1], /^\d+:\d+$/, 'use a numeric uid:gid so the image needs no passwd entry'); assert.doesNotMatch(dockerfile, /^ENV .*(?:API_KEY|TOKEN|PASSWORD|SECRET)[ =]/im); // Health must gate on the loaded model, so the container is not "healthy" while it cannot answer. assert.match(directives, /^HEALTHCHECK .*timmy-worker-ready/m); assert.match(directives, /--start-period=\d+s/); assert.match(directives, /--host", "127\.0\.0\.1"/, 'the health probe runs on the container loopback'); // The container listens inside its own network namespace; the run recipe, not the image, decides // exposure and publishes on loopback only (asserted separately). assert.match(dockerfile, /--host 0\.0\.0\.0|TIMMY_MODEL_HOST=0\.0\.0\.0/); }); test('the build refuses a floating or missing pin before it reaches docker', async () => { const floating = spawnSync('bash', [buildScriptPath.pathname, '--print-plan'], { encoding: 'utf8', env: { ...process.env, TIMMY_LLAMA_CPP_COMMIT: 'latest' }, }); assert.notEqual(floating.status, 0, 'a floating llama.cpp ref must be rejected'); assert.match(floating.stderr, /pin|40-hex|floating/i); const missingSha = spawnSync('bash', [buildScriptPath.pathname, '--print-plan'], { encoding: 'utf8', env: { ...process.env, TIMMY_MODEL_SHA256: '' }, }); assert.notEqual(missingSha.status, 0, 'a missing model hash must be rejected'); const plan = spawnSync('bash', [buildScriptPath.pathname, '--print-plan'], { encoding: 'utf8' }); assert.equal(plan.status, 0, plan.stderr); assert.match(plan.stdout, /llama\.cpp commit: [0-9a-f]{40}/); assert.match(plan.stdout, /SmolVLM2-2\.2B-Instruct-Q4_K_M\.gguf sha256: [0-9a-f]{64}/); assert.match(plan.stdout, /bind address: 127\.0\.0\.1:8080/); assert.match(plan.stdout, /publish: 127\.0\.0\.1:8080/); }); test('the run recipe publishes on loopback only and drops every privilege it can', async () => { const { runScript } = await recipe(); assert.match(runScript, /127\.0\.0\.1:\$\{?PORT/); assert.match(runScript, /--read-only/); assert.match(runScript, /--cap-drop[= ]ALL/); assert.match(runScript, /no-new-privileges/); assert.match(runScript, /--security-opt/); assert.doesNotMatch(runScript, /--privileged/); assert.doesNotMatch(runScript, /-p "\$PORT:/); assert.doesNotMatch(runScript, /\b0\.0\.0\.0\b/); // The model mount is read-only, and no credential has a default value. assert.match(runScript, /:ro\b/); assert.doesNotMatch(runScript, /(?:API_KEY|TOKEN|PASSWORD)=[^\s"']/); }); test('the run recipe refuses to publish the worker anywhere but loopback', async () => { const hostile = spawnSync('bash', [runScriptPath.pathname, '--print-plan'], { encoding: 'utf8', env: { ...process.env, TIMMY_WORKER_PUBLISH_HOST: '0.0.0.0' }, }); assert.notEqual(hostile.status, 0, 'a non-loopback publish must be refused'); assert.match(hostile.stderr, /loopback|127\.0\.0\.1/i); const plan = spawnSync('bash', [runScriptPath.pathname, '--print-plan'], { encoding: 'utf8' }); assert.equal(plan.status, 0, plan.stderr); assert.match(plan.stdout, /publish: 127\.0\.0\.1:\d+/); }); test('the build context excludes weights, user images, releases, and secrets', async () => { const { dockerignore } = await recipe(); for (const pattern of ['*.gguf', 'artifacts/', 'video/', 'models/', '.git/', 'node_modules/', '.env', '.env.*']) { assert.ok(dockerignore.split('\n').includes(pattern), `dockerignore must exclude ${pattern}`); } // Committed synthetic fixtures are fine, but a real medical corpus directory is never buildable. assert.doesNotMatch(dockerignore, /^!.*\.gguf$/m); });