companion-shell-integration.test.mjs
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * Tier 2 — INTEGRATION: Phase 5 adapters composed with Phase 2–4 cores. |
| 3 | */ |
| 4 | |
| 5 | import { after, describe, it } from 'node:test'; |
| 6 | import assert from 'node:assert/strict'; |
| 7 | import crypto from 'node:crypto'; |
| 8 | import { mkdtemp, readFile, rm } from 'node:fs/promises'; |
| 9 | import os from 'node:os'; |
| 10 | import path from 'node:path'; |
| 11 | |
| 12 | import { createCompanionInferenceListener } from '../lib/companion-inference-listener.mjs'; |
| 13 | import { |
| 14 | createCompanionShell, |
| 15 | createRuntimeGroup, |
| 16 | downloadVerifyAndStageModel, |
| 17 | } from '../lib/companion-shell.mjs'; |
| 18 | |
| 19 | const tmpRoots = []; |
| 20 | after(async () => { |
| 21 | for (const dir of tmpRoots) await rm(dir, { recursive: true, force: true }); |
| 22 | }); |
| 23 | |
| 24 | function sha256(data) { |
| 25 | return crypto.createHash('sha256').update(data).digest('hex'); |
| 26 | } |
| 27 | |
| 28 | describe('guarded listener fronts the runtime callback', () => { |
| 29 | it('admits only same-origin loopback requests with the bearer token', async () => { |
| 30 | let runtimeHits = 0; |
| 31 | const listener = createCompanionInferenceListener({ |
| 32 | expectedToken: 'loopback-token', |
| 33 | runtimeRequest(_req, res) { |
| 34 | runtimeHits += 1; |
| 35 | res.statusCode = 200; |
| 36 | res.setHeader('Content-Type', 'application/json'); |
| 37 | res.end(JSON.stringify({ ok: true })); |
| 38 | }, |
| 39 | }); |
| 40 | const bound = await listener.start(); |
| 41 | try { |
| 42 | const url = `http://127.0.0.1:${bound.port}/v1/models`; |
| 43 | const denied = await fetch(url, { headers: { Origin: 'https://evil.example', Authorization: 'Bearer loopback-token' } }); |
| 44 | assert.equal(denied.status, 403); |
| 45 | assert.equal(runtimeHits, 0); |
| 46 | |
| 47 | const allowed = await fetch(url, { |
| 48 | headers: { |
| 49 | Host: `127.0.0.1:${bound.port}`, |
| 50 | Origin: `http://127.0.0.1:${bound.port}`, |
| 51 | 'Sec-Fetch-Site': 'same-origin', |
| 52 | Authorization: 'Bearer loopback-token', |
| 53 | }, |
| 54 | }); |
| 55 | assert.equal(allowed.status, 200); |
| 56 | assert.equal(runtimeHits, 1); |
| 57 | assert.equal(allowed.headers.get('access-control-allow-origin'), null); |
| 58 | } finally { |
| 59 | await listener.close(); |
| 60 | } |
| 61 | }); |
| 62 | }); |
| 63 | |
| 64 | describe('download → integrity → atomic stage', () => { |
| 65 | it('streams chunks through the accumulator before verified rename', async () => { |
| 66 | const data = Buffer.from('verified model payload'); |
| 67 | const dir = await mkdtemp(path.join(os.tmpdir(), 'knowtation-phase5-')); |
| 68 | tmpRoots.push(dir); |
| 69 | const tempPath = path.join(dir, 'model.tmp'); |
| 70 | const verifiedPath = path.join(dir, 'model.gguf'); |
| 71 | const runtimeGroup = createRuntimeGroup({ |
| 72 | spawn: async () => ({ pid: 42, kill: async () => {} }), |
| 73 | healthCheck: async () => true, |
| 74 | async download(_url, onChunk) { |
| 75 | onChunk(data.subarray(0, 8)); |
| 76 | onChunk(data.subarray(8)); |
| 77 | }, |
| 78 | }); |
| 79 | |
| 80 | const result = await downloadVerifyAndStageModel({ |
| 81 | runtimeGroup, |
| 82 | tempPath, |
| 83 | verifiedPath, |
| 84 | spec: { |
| 85 | modelUrl: 'https://cdn.knowtation-models.com/model.gguf', |
| 86 | expectedDigest: sha256(data), |
| 87 | expectedSizeBytes: data.length, |
| 88 | allowedSourceUrls: ['https://cdn.knowtation-models.com/'], |
| 89 | }, |
| 90 | }); |
| 91 | |
| 92 | assert.equal(result.verifiedPath, verifiedPath); |
| 93 | assert.equal(await readFile(verifiedPath, 'utf8'), data.toString('utf8')); |
| 94 | }); |
| 95 | }); |
| 96 | |
| 97 | describe('runtime lifecycle drives lane selection', () => { |
| 98 | it('integrity + listener + token + health_ok flips companionAvailable and selects local', async () => { |
| 99 | let now = 1000; |
| 100 | const shell = createCompanionShell({ |
| 101 | now: () => now, |
| 102 | healthRecencyMs: 500, |
| 103 | runtimeGroup: { |
| 104 | spawn: async () => ({ pid: 7, port: 41111, kill: async () => {} }), |
| 105 | download: async () => {}, |
| 106 | healthCheck: async () => true, |
| 107 | }, |
| 108 | }); |
| 109 | shell.markIntegrityVerified(); |
| 110 | shell.setListenerBound(true); |
| 111 | shell.setLoopbackTokenPresent(true); |
| 112 | await shell.startRuntime({ |
| 113 | binaryPath: '/opt/knowtation/runtime', |
| 114 | modelPath: '/models/verified.gguf', |
| 115 | port: 41111, |
| 116 | maxRamBytes: 1024, |
| 117 | }); |
| 118 | |
| 119 | assert.equal(shell.companionAvailable(), true); |
| 120 | assert.equal(shell.selectLane({}, { managedKeyAvailable: true }), 'local'); |
| 121 | now = 2000; |
| 122 | assert.equal(shell.companionAvailable(), false); |
| 123 | }); |
| 124 | }); |
File History
2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠
1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6
docs: accept Calendar Events v0 spec with Phase 0 security …
Human
1 day ago