Files
stack/packages/bus/tests/model-credential-store.test.mjs
jason.woltje 362893d043 feat: integrate reviewed proxy page and managed model keys
Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
2026-10-26 12:04:21 -05:00

77 lines
4.7 KiB
JavaScript

// P2 RED: model is implicit, durable/private, and status never exposes current/retiring values.
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { randomBytes, createHash } from 'node:crypto';
import { Credentials } from '../src/credentials.mjs';
function fixture(t) {
const root = fs.mkdtempSync(join(tmpdir(), 'p2-store-'));
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
const storeRoot = join(root, 'config', 'secrets', 'agents');
fs.mkdirSync(storeRoot, { recursive: true, mode: 0o700 });
const open = () => new Credentials({ storeRoot, dataRoot: join(root, 'data'), modelAgents: ['demo/coder'] });
const file = join(storeRoot, 'demo', 'coder', 'model');
return { root, storeRoot, open, file };
}
const key = () => 'msk-fixture-' + randomBytes(32).toString('base64url');
const id = value => createHash('sha256').update(value).digest('hex').slice(0, 12);
const record = value => ({ key: value, keyId: id(value), issuedAt: '2026-10-24T00:00:00.000Z', rotateBy: '2026-11-23', state: 'valid', retiring: [] });
test('implicit model kind starts not-issued without a business or role reference', t => {
const f = fixture(t), c = f.open(); t.after(() => c.close());
const status = c.status().find(s => s.instance === 'demo/coder' && s.service === 'model');
assert.equal(status?.state, 'not-issued');
assert.equal(fs.existsSync(f.file), false);
});
test('model record persists at 0600 in 0700 dirs and reloads ids/issue time/state only in status', t => {
const f = fixture(t), c = f.open(), value = key(); t.after(() => c.close());
assert.equal(typeof c.writeModel, 'function');
c.writeModel('demo/coder', record(value));
assert.equal(fs.statSync(f.file).mode & 0o777, 0o600);
for (const dir of [f.storeRoot, join(f.storeRoot, 'demo'), join(f.storeRoot, 'demo', 'coder')]) assert.equal(fs.statSync(dir).mode & 0o777, 0o700);
c.close();
const again = f.open(); t.after(() => again.close());
const status = again.status().find(s => s.service === 'model');
assert.equal(status.keyId === id(value), true);
assert.equal(status.issuedAt, '2026-10-24T00:00:00.000Z');
assert.equal(status.state, 'valid');
assert.equal(JSON.stringify(again.status()).includes(value), false);
assert.equal(again.modelRecord('demo/coder').key === value, true);
});
test('revoking model metadata survives restart without losing the private record', t => {
const f = fixture(t), c = f.open(), value = key(); t.after(() => c.close());
assert.equal(typeof c.writeModel, 'function');
c.writeModel('demo/coder', { ...record(value), state: 'revoking', revokingAt: '2026-10-24T01:00:00.000Z' });
c.close(); const again = f.open(); t.after(() => again.close());
assert.equal(again.status().find(s => s.service === 'model').state, 'revoking');
assert.equal(again.modelRecord('demo/coder').key === value, true);
assert.equal(JSON.stringify(again.status()).includes(value), false);
});
test('model record wrong file mode refuses startup rather than inventing a replacement', t => {
const f = fixture(t), c = f.open(); t.after(() => c.close());
assert.equal(typeof c.writeModel, 'function'); c.writeModel('demo/coder', record(key())); c.close();
fs.chmodSync(f.file, 0o640);
assert.throws(() => f.open(), e => e.code === 'credential-file');
});
test('non-proxy Credentials has no implicit model kind', t => {
const f = fixture(t), c = new Credentials({ storeRoot: f.storeRoot, dataRoot: join(f.root, 'data') });
t.after(() => c.close()); assert.deepEqual(c.status(), []);
});
test('credential-revoke-failed: generic remove cannot bypass remote model confirmation', t => {
const f = fixture(t), c = f.open(); t.after(() => c.close());
c.writeModel('demo/coder', record(key()));
assert.throws(() => c.remove('demo/coder'), e => e.code === 'credential-revoke-failed');
assert.equal(c.modelRecord('demo/coder').state, 'valid'); assert.equal(fs.existsSync(f.file), true);
});
test('retiring keys reload privately and remain covered by the credential leak guard', t => {
const f = fixture(t), c = f.open(), value = key(), old = key(); t.after(() => c.close());
c.writeModel('demo/coder', { ...record(value), retiring: [{ key: old, keyId: id(old), issuedAt: '2026-10-23T00:00:00.000Z', retireAt: '2026-10-24T02:00:00.000Z' }] });
c.close(); const again = f.open(); t.after(() => again.close());
assert.equal(again.modelRecord('demo/coder').retiring[0].key === old, true);
const status = JSON.stringify(again.status()); assert.equal(status.includes(old), false); assert.equal(status.includes(value), false);
assert.throws(() => again.assertClean({ value: old }), e => e.code === 'credential-leak');
});