feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,558 @@
const assert = require('node:assert/strict');
const fs = require('node:fs');
const { DatabaseSync } = require('node:sqlite');
const {
createStepRunRecord,
transitionStepRunMutation,
} = require('@qinglong/runtime-core/step-run');
const {
createModelInvocationCompletionCommand,
createModelInvocationMutationIdentity,
createModelInvocationStartCommand,
} = require('../../dist/model-invocation/modelInvocation.js');
const {
LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
LocalModelInvocationFeatureActivationRepository,
createLocalModelInvocationFeatureTransitionCommand,
} = require('@qinglong/ai/local-feature-activation');
const {
LocalModelInvocationRepository,
} = require('../../dist/model-invocation/localModelInvocationRepository.js');
const NOW = 3_000_000;
const CRASH_POINTS = Object.freeze({
start_before_begin: Object.freeze({
operation: 'start',
timing: 'beforeExec',
sql: 'BEGIN IMMEDIATE',
durable: false,
}),
start_after_mutation: Object.freeze({
operation: 'start',
timing: 'afterRun',
sql: 'INSERT INTO "StepRunMutations"',
durable: false,
}),
start_after_fact: Object.freeze({
operation: 'start',
timing: 'afterRun',
sql: 'INSERT INTO "ModelInvocationStarts"',
durable: false,
}),
start_after_commit: Object.freeze({
operation: 'start',
timing: 'afterExec',
sql: 'COMMIT',
durable: true,
}),
completion_after_mutation: Object.freeze({
operation: 'completion',
timing: 'afterRun',
sql: 'INSERT INTO "StepRunMutations"',
durable: false,
}),
completion_after_fact: Object.freeze({
operation: 'completion',
timing: 'afterRun',
sql: 'INSERT INTO "ModelInvocationCompletions"',
durable: false,
}),
completion_after_commit: Object.freeze({
operation: 'completion',
timing: 'afterExec',
sql: 'COMMIT',
durable: true,
}),
});
function openClient(databasePath, profile) {
const client = new DatabaseSync(databasePath);
client.exec('PRAGMA foreign_keys = ON');
client.exec('PRAGMA busy_timeout = 5000');
client.exec(`PRAGMA journal_mode = ${profile === 'edge' ? 'DELETE' : 'WAL'}`);
client.exec('PRAGMA synchronous = FULL');
return client;
}
function createMainContract(client) {
client.exec(`
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
status TEXT NOT NULL,
version INTEGER NOT NULL,
event_sequence INTEGER NOT NULL
);
CREATE TABLE "RunEvents" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
sequence INTEGER NOT NULL,
type TEXT NOT NULL,
dedupe_key TEXT NOT NULL,
actor_type TEXT NOT NULL,
actor_id TEXT,
attempt_id TEXT,
step_run_id TEXT,
payload TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
UNIQUE (run_id, sequence),
UNIQUE (run_id, dedupe_key)
);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
kind TEXT NOT NULL,
status TEXT NOT NULL,
version INTEGER NOT NULL,
attempt_count INTEGER NOT NULL,
output_ref TEXT,
approval_request_id TEXT,
ready_at_ms INTEGER,
started_at_ms INTEGER,
finished_at_ms INTEGER,
result_code TEXT,
error_summary TEXT,
updated_at_ms INTEGER NOT NULL,
last_mutation_id TEXT NOT NULL,
step_run_digest TEXT NOT NULL,
step_run_json TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (
mutation_id TEXT PRIMARY KEY,
mutation_digest TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
step_run_digest TEXT NOT NULL,
event_id TEXT NOT NULL,
event_sequence INTEGER NOT NULL,
run_version INTEGER NOT NULL,
step_run_json TEXT NOT NULL,
committed_at_ms INTEGER NOT NULL
);
`);
}
function audit(phase, overrides = {}) {
return {
phase,
projectId: 'crash-project',
runId: 'crash-run',
stepRunId: 'crash-step',
traceId: 'crash-trace',
requestId: 'crash-request',
provider: 'remote',
model: 'crash-model',
policyRevision: 'policy-1',
requestDigest: `sha256:${'b'.repeat(64)}`,
deadlineAtMs: NOW + 10_000,
inputBytes: 128,
maxOutputTokens: 64,
outputBytes: 0,
usage: null,
errorCode: null,
occurredAtMs: NOW,
...overrides,
};
}
function startCommand(ready) {
const identity = createModelInvocationMutationIdentity(
'crash-request',
'start',
);
return createModelInvocationStartCommand(
audit('admitted'),
transitionStepRunMutation(
ready,
{
expectedVersion: ready.version,
expectedDigest: ready.stepRunDigest,
mutationId: identity.mutationId,
to: 'running',
atMs: NOW,
},
{
expectedRunVersion: 1,
expectedRunEventSequence: 1,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
}
function completionCommand(start) {
const identity = createModelInvocationMutationIdentity(
'crash-request',
'completion',
);
return createModelInvocationCompletionCommand(
start.start,
audit('completed', {
occurredAtMs: NOW + 25,
outputBytes: 12,
usage: { inputTokens: 5, outputTokens: 2, totalTokens: 7 },
}),
transitionStepRunMutation(
start.stepRunMutation.stepRun,
{
expectedVersion: start.start.startedStepRunVersion,
expectedDigest: start.start.startedStepRunDigest,
mutationId: identity.mutationId,
to: 'succeeded',
atMs: NOW + 25,
outputRef: 'model-invocation:crash-request',
},
{
expectedRunVersion: 2,
expectedRunEventSequence: 2,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
}
async function setupScenario({ databasePath, statePath, profile, operation }) {
const client = openClient(databasePath, profile);
try {
createMainContract(client);
await migrateLocalModelInvocationFeature(client);
new LocalModelInvocationFeatureActivationRepository(client).transition(
createLocalModelInvocationFeatureTransitionCommand({
featureId: 'model-invocation',
expectedGeneration: 0,
expectedState: null,
state: 'active',
mutationId: 'model-invocation-crash-feature-activation',
requestId: 'model-invocation-crash-feature-request',
expectedMigrationDigest: LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
safety: {
mode: 'fresh_database',
backupEvidenceDigest: null,
},
principal: {
subject: { type: 'user', id: 'test-owner' },
authenticationId: 'local_ai_feature:crash-proof',
authenticatedAtMs: 1,
expiresAtMs: 301_000,
assurance: 'local_console',
},
}),
);
const ready = createStepRunRecord({
id: 'crash-step',
runId: 'crash-run',
stepKey: 'summarize',
kind: 'model',
definitionRef: 'prompt:crash@1',
definitionDigest: 'a'.repeat(64),
required: true,
initialStatus: 'ready',
inputRef: 'artifact:crash-input',
mutationId: 'create-crash-step',
createdAtMs: NOW - 1,
});
client
.prepare(
`INSERT INTO "Runs"
(id, project_id, status, version, event_sequence)
VALUES ('crash-run', 'crash-project', 'running', 1, 1)`,
)
.run();
client
.prepare(
`INSERT INTO "StepRuns" (
id, run_id, kind, status, version, attempt_count, output_ref,
approval_request_id, ready_at_ms, started_at_ms, finished_at_ms,
result_code, error_summary, updated_at_ms, last_mutation_id,
step_run_digest, step_run_json
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
)
.run(
ready.id,
ready.runId,
ready.kind,
ready.status,
ready.version,
ready.attemptCount,
ready.outputRef,
ready.approvalRequestId,
ready.readyAtMs,
ready.startedAtMs,
ready.finishedAtMs,
ready.resultCode,
ready.errorSummary,
ready.updatedAtMs,
ready.lastMutationId,
ready.stepRunDigest,
JSON.stringify(ready),
);
const start = startCommand(ready);
const completion = completionCommand(start);
if (operation === 'completion') {
assert.equal(
(await new LocalModelInvocationRepository(client).admit(start)).status,
'created',
);
}
fs.writeFileSync(
statePath,
JSON.stringify({ profile, operation, start, completion }),
{ encoding: 'utf8', flag: 'wx', mode: 0o600 },
);
} finally {
client.close();
}
}
function writeCrashMarker(markerPath, pointName) {
const file = fs.openSync(markerPath, 'wx', 0o600);
try {
fs.writeSync(
file,
JSON.stringify({
schema: 'qinglong/sqlite-model-invocation-crash-marker@v1',
point: pointName,
pid: process.pid,
}),
);
fs.fsyncSync(file);
} finally {
fs.closeSync(file);
}
}
function crashClient(client, pointName, markerPath) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error(`unknown crash point ${pointName}`);
let triggered = false;
const crash = () => {
if (triggered) return;
triggered = true;
writeCrashMarker(markerPath, pointName);
process.kill(process.pid, 'SIGKILL');
throw new Error(`SIGKILL did not terminate ${pointName}`);
};
const matches = (timing, sql) =>
!triggered && point.timing === timing && sql.trim().includes(point.sql);
return new Proxy(client, {
get(target, property) {
if (property === 'exec') {
return (sql) => {
if (matches('beforeExec', sql)) crash();
const result = target.exec(sql);
if (matches('afterExec', sql)) crash();
return result;
};
}
if (property === 'prepare') {
return (sql) => {
const statement = target.prepare(sql);
return new Proxy(statement, {
get(statementTarget, statementProperty) {
const value = Reflect.get(
statementTarget,
statementProperty,
statementTarget,
);
if (statementProperty === 'run') {
return (...values) => {
const result = value.apply(statementTarget, values);
if (matches('afterRun', sql)) crash();
return result;
};
}
return typeof value === 'function'
? value.bind(statementTarget)
: value;
},
});
};
}
const value = Reflect.get(target, property, target);
return typeof value === 'function' ? value.bind(target) : value;
},
});
}
async function runCrashScenario({
databasePath,
statePath,
markerPath,
pointName,
}) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error(`unknown crash point ${pointName}`);
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
if (state.operation !== point.operation) {
throw new Error(
`crash point ${pointName} does not match ${state.operation}`,
);
}
const client = openClient(databasePath, state.profile);
const repository = new LocalModelInvocationRepository(
crashClient(client, pointName, markerPath),
);
if (point.operation === 'start') {
await repository.admit(state.start);
} else {
await repository.complete(state.completion);
}
throw new Error(`crash point ${pointName} was not reached`);
}
function facts(client) {
return {
...client
.prepare(
`SELECT
step.status AS "stepStatus",
step.version AS "stepVersion",
run.version AS "runVersion",
run.event_sequence AS "runEventSequence",
(SELECT count(*) FROM "RunEvents") AS "eventCount",
(SELECT count(*) FROM "StepRunMutations") AS "mutationCount",
(SELECT count(*) FROM "ModelInvocationStarts") AS "startCount",
(SELECT count(*) FROM "ModelInvocationCompletions")
AS "completionCount"
FROM "StepRuns" AS step
JOIN "Runs" AS run ON run.id = step.run_id
WHERE step.id = 'crash-step' AND run.id = 'crash-run'`,
)
.get(),
};
}
async function verifyScenario({ databasePath, statePath, pointName }) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error(`unknown crash point ${pointName}`);
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
const client = openClient(databasePath, state.profile);
const repository = new LocalModelInvocationRepository(client);
try {
assert.equal(
client.prepare('PRAGMA integrity_check').get().integrity_check,
'ok',
);
assert.equal(
client.prepare('PRAGMA journal_mode').get().journal_mode,
state.profile === 'edge' ? 'delete' : 'wal',
);
const operation = point.operation;
const before = facts(client);
if (operation === 'start') {
assert.deepEqual(
before,
point.durable
? {
stepStatus: 'running',
stepVersion: 2,
runVersion: 2,
runEventSequence: 2,
eventCount: 1,
mutationCount: 1,
startCount: 1,
completionCount: 0,
}
: {
stepStatus: 'ready',
stepVersion: 1,
runVersion: 1,
runEventSequence: 1,
eventCount: 0,
mutationCount: 0,
startCount: 0,
completionCount: 0,
},
);
const replay = await repository.admit(state.start);
assert.equal(replay.status, point.durable ? 'existing' : 'created');
assert.equal((await repository.admit(state.start)).status, 'existing');
} else {
assert.deepEqual(
before,
point.durable
? {
stepStatus: 'succeeded',
stepVersion: 3,
runVersion: 3,
runEventSequence: 3,
eventCount: 2,
mutationCount: 2,
startCount: 1,
completionCount: 1,
}
: {
stepStatus: 'running',
stepVersion: 2,
runVersion: 2,
runEventSequence: 2,
eventCount: 1,
mutationCount: 1,
startCount: 1,
completionCount: 0,
},
);
const replay = await repository.complete(state.completion);
assert.equal(replay.status, point.durable ? 'existing' : 'created');
assert.equal(
(await repository.complete(state.completion)).status,
'existing',
);
}
const after = facts(client);
assert.equal(
after.stepStatus,
operation === 'start' ? 'running' : 'succeeded',
);
assert.equal(after.startCount, 1);
assert.equal(after.completionCount, operation === 'start' ? 0 : 1);
return Object.freeze({
profile: state.profile,
point: pointName,
crashBeforeCommit: !point.durable,
durableAfterCrash: point.durable,
journalMode: client.prepare('PRAGMA journal_mode').get().journal_mode,
integrityCheck: 'ok',
});
} finally {
client.close();
}
}
if (require.main === module) {
const [mode, databasePath, statePath, markerPath, pointName] =
process.argv.slice(2);
if (mode !== 'crash') throw new Error(`unknown mode ${mode}`);
runCrashScenario({
databasePath,
statePath,
markerPath,
pointName,
}).catch((error) => {
process.stderr.write(`${error.stack ?? error.message}\n`);
process.exitCode = 1;
});
}
module.exports = {
CRASH_POINTS,
setupScenario,
verifyScenario,
};
@@ -0,0 +1,597 @@
const assert = require('node:assert/strict');
const fs = require('node:fs');
const { DatabaseSync } = require('node:sqlite');
const { migrateLocalSqlitePath } = require('@qinglong/local-sqlite/migration');
const {
LocalSqlitePluginPackageInstallRepository,
} = require('@qinglong/local-sqlite/plugin-package-install');
const {
LocalSqlitePluginPackageMaterializedRevisionRepository,
} = require('@qinglong/local-sqlite/plugin-package-materialized-revision');
const {
LocalSqlitePluginPackageTaskReconciliationRepository,
} = require('@qinglong/local-sqlite/plugin-package-task-reconciliation');
const {
LocalSqlitePluginPackageAutomationPublicationRepository,
} = require('@qinglong/local-sqlite/plugin-package-automation-publication');
const {
createInitialPluginPackageAutomationPublication,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
const {
activateInstall,
pluginPackageTaskReconciliationFixture,
} = require('../../../../test/contracts/pluginPackageTaskReconciliationRepositoryContract.cjs');
const {
LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
LocalModelInvocationFeatureActivationRepository,
createLocalModelInvocationFeatureTransitionCommand,
} = require('@qinglong/ai/local-feature-activation');
const {
LocalPluginPackagePromptAdmissionRepository,
} = require('../../dist/prompt/localPluginPackagePromptAdmissionRepository.js');
const {
LocalModelInvocationRepository,
} = require('../../dist/model-invocation/localModelInvocationRepository.js');
const {
DurableModelInvocationCoordinator,
} = require('../../dist/model-invocation/durableModelInvocationCoordinator.js');
const { BoundedModelGateway } = require('../../dist/model-gateway/gateway.js');
const {
preparePluginPackagePromptExecution,
} = require('../../dist/prompt/pluginPackagePromptExecution.js');
const CRASH_POINTS = Object.freeze({
admission_before_begin: Object.freeze({
operation: 'admission',
timing: 'beforeExec',
sql: 'BEGIN IMMEDIATE',
durable: false,
}),
admission_after_run: Object.freeze({
operation: 'admission',
timing: 'afterRun',
sql: 'INSERT INTO "Runs"',
durable: false,
}),
admission_after_step_mutation: Object.freeze({
operation: 'admission',
timing: 'afterRun',
sql: 'INSERT INTO "StepRunMutations"',
durable: false,
}),
admission_after_fact: Object.freeze({
operation: 'admission',
timing: 'afterRun',
sql: 'INSERT INTO "ModelInvocationPromptAdmissions"',
durable: false,
}),
admission_after_commit: Object.freeze({
operation: 'admission',
timing: 'afterExec',
sql: 'COMMIT',
durable: true,
}),
finalization_before_begin: Object.freeze({
operation: 'finalization',
timing: 'beforeExec',
sql: 'BEGIN IMMEDIATE',
durable: false,
}),
finalization_after_run: Object.freeze({
operation: 'finalization',
timing: 'afterRun',
sql: 'UPDATE "Runs"',
durable: false,
}),
finalization_after_event: Object.freeze({
operation: 'finalization',
timing: 'afterRun',
sql: 'INSERT INTO "RunEvents"',
durable: false,
}),
finalization_after_fact: Object.freeze({
operation: 'finalization',
timing: 'afterRun',
sql: 'INSERT INTO "ModelInvocationPromptFinalizations"',
durable: false,
}),
finalization_after_commit: Object.freeze({
operation: 'finalization',
timing: 'afterExec',
sql: 'COMMIT',
durable: true,
}),
});
function openClient(databasePath, profile) {
const client = new DatabaseSync(databasePath);
client.exec('PRAGMA foreign_keys = ON');
client.exec('PRAGMA busy_timeout = 5000');
client.exec(
'PRAGMA journal_mode = ' + (profile === 'edge' ? 'DELETE' : 'WAL'),
);
client.exec('PRAGMA synchronous = FULL');
return client;
}
function promptResource() {
return {
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}} for {{audience}}.',
parameters: [
{ name: 'audience', required: false },
{ name: 'subject', required: true },
],
};
}
async function seedPublication(client, profile) {
const fixture = pluginPackageTaskReconciliationFixture(
'prompt-crash-matrix',
{
profile,
tasks: [],
prompts: [promptResource()],
},
);
const publication = createInitialPluginPackageAutomationPublication(
fixture.revision,
fixture.registry,
2_000,
);
client
.prepare(
'INSERT INTO "QingLong3Projects" ' +
'(id, name, slug, status, version, created_at_ms, updated_at_ms) ' +
"VALUES (?, ?, ?, 'active', 1, 1, 1)",
)
.run(fixture.projectId, fixture.projectId, fixture.projectId);
await activateInstall(
new LocalSqlitePluginPackageInstallRepository(client),
fixture,
);
await new LocalSqlitePluginPackageMaterializedRevisionRepository(
client,
fixture.registry,
).publish(fixture.revision);
await new LocalSqlitePluginPackageTaskReconciliationRepository(
client,
fixture.registry,
).reconcile(fixture.revision, {
async findActiveResourceGeneration() {
return fixture.revision.generation;
},
});
await new LocalSqlitePluginPackageAutomationPublicationRepository(
client,
).publish(publication);
return publication;
}
function executionInput(publication) {
return {
publication,
expectedPublicationDigest: publication.publicationDigest,
promptId: 'summary',
requestId: 'prompt-crash-request',
traceId: 'prompt-crash-trace',
requestedBySubject: { type: 'user', id: 'prompt-crash-owner' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'private crash matrix input' },
provider: 'openai-compatible',
model: 'vendor/model-a',
maxOutputTokens: 512,
temperature: 0.2,
plannedAtMs: 2_000,
deadlineAtMs: 62_000,
};
}
function createGateway(repository) {
return new BoundedModelGateway({
providers: [
{
type: 'openai-compatible',
async listModels() {
return [{ id: 'vendor/model-a' }];
},
async generate() {
return {
provider: 'openai-compatible',
model: 'vendor/model-a',
text: 'private crash matrix output',
finishReason: 'stop',
usage: { inputTokens: 7, outputTokens: 3, totalTokens: 10 },
};
},
async *stream() {
throw new Error('not used');
},
},
],
policies: {
async resolve() {
return {
revision: 'prompt-crash-policy-1',
allowedProviders: ['openai-compatible'],
allowedModels: ['vendor/model-a'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 512,
maxTotalTokens: 1024,
maxCostMicros: null,
priceRevision: null,
};
},
},
pricing: {
async resolve() {
throw new Error('pricing must remain unreachable');
},
},
audit: new DurableModelInvocationCoordinator(repository),
maxConcurrent: 1,
now: () => 3_000,
});
}
async function setupScenario({ databasePath, statePath, profile, operation }) {
await migrateLocalSqlitePath({ databasePath, profile });
const client = openClient(databasePath, profile);
try {
await migrateLocalModelInvocationFeature(client);
new LocalModelInvocationFeatureActivationRepository(client).transition(
createLocalModelInvocationFeatureTransitionCommand({
featureId: 'model-invocation',
expectedGeneration: 0,
expectedState: null,
state: 'active',
mutationId: 'prompt-crash-feature-activation',
requestId: 'prompt-crash-feature-request',
expectedMigrationDigest: LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
safety: {
mode: 'fresh_database',
backupEvidenceDigest: null,
},
principal: {
subject: { type: 'user', id: 'prompt-crash-owner' },
authenticationId: 'local_ai_feature:prompt-crash',
authenticatedAtMs: 1,
expiresAtMs: 301_000,
assurance: 'local_console',
},
}),
);
const publication = await seedPublication(client, profile);
const prepared = preparePluginPackagePromptExecution(
executionInput(publication),
);
if (operation === 'finalization') {
const admissions = new LocalPluginPackagePromptAdmissionRepository(
client,
);
assert.equal((await admissions.admit(prepared.plan)).status, 'created');
const invocations = new LocalModelInvocationRepository(client);
const result = await createGateway(invocations).generate(
prepared.request,
{
projectId: prepared.plan.target.projectId,
runId: prepared.plan.runId,
stepRunId: prepared.plan.stepRunId,
traceId: prepared.plan.traceId,
requestId: prepared.plan.invocationId,
deadlineAtMs: prepared.plan.deadlineAtMs,
},
);
assert.equal(result.text, 'private crash matrix output');
}
fs.writeFileSync(
statePath,
JSON.stringify({ profile, operation, plan: prepared.plan }),
{ encoding: 'utf8', flag: 'wx', mode: 0o600 },
);
} finally {
client.close();
}
}
function writeCrashMarker(markerPath, pointName) {
const file = fs.openSync(markerPath, 'wx', 0o600);
try {
fs.writeSync(
file,
JSON.stringify({
schema: 'qinglong/sqlite-plugin-package-prompt-crash-marker@v1',
point: pointName,
pid: process.pid,
}),
);
fs.fsyncSync(file);
} finally {
fs.closeSync(file);
}
}
function crashClient(client, pointName, markerPath) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error('unknown crash point ' + pointName);
let triggered = false;
const crash = () => {
if (triggered) return;
triggered = true;
writeCrashMarker(markerPath, pointName);
process.kill(process.pid, 'SIGKILL');
throw new Error('SIGKILL did not terminate ' + pointName);
};
const matches = (timing, sql) =>
!triggered && point.timing === timing && sql.trim().includes(point.sql);
return new Proxy(client, {
get(target, property) {
if (property === 'exec') {
return (sql) => {
if (matches('beforeExec', sql)) crash();
const result = target.exec(sql);
if (matches('afterExec', sql)) crash();
return result;
};
}
if (property === 'prepare') {
return (sql) => {
const statement = target.prepare(sql);
return new Proxy(statement, {
get(statementTarget, statementProperty) {
const value = Reflect.get(
statementTarget,
statementProperty,
statementTarget,
);
if (statementProperty === 'run') {
return (...values) => {
const result = value.apply(statementTarget, values);
if (matches('afterRun', sql)) crash();
return result;
};
}
return typeof value === 'function'
? value.bind(statementTarget)
: value;
},
});
};
}
const value = Reflect.get(target, property, target);
return typeof value === 'function' ? value.bind(target) : value;
},
});
}
async function runCrashScenario({
databasePath,
statePath,
markerPath,
pointName,
}) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error('unknown crash point ' + pointName);
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
if (state.operation !== point.operation) {
throw new Error(
'crash point ' + pointName + ' does not match ' + state.operation,
);
}
const client = openClient(databasePath, state.profile);
const repository = new LocalPluginPackagePromptAdmissionRepository(
crashClient(client, pointName, markerPath),
);
if (point.operation === 'admission') {
await repository.admit(state.plan);
} else {
await repository.finalize(state.plan.requestId);
}
throw new Error('crash point ' + pointName + ' was not reached');
}
function count(client, sql, value) {
return client.prepare(sql).get(value).count;
}
function facts(client, plan) {
const run = client
.prepare(
'SELECT status, version, event_sequence AS "eventSequence" ' +
'FROM "Runs" WHERE id = ?',
)
.get(plan.runId);
const step = client
.prepare('SELECT kind, status, version FROM "StepRuns" WHERE id = ?')
.get(plan.stepRunId);
return {
run: run ? { ...run } : null,
step: step ? { ...step } : null,
runEvents: count(
client,
'SELECT count(*) AS count FROM "RunEvents" WHERE run_id = ?',
plan.runId,
),
attempts: count(
client,
'SELECT count(*) AS count FROM "RunAttempts" WHERE run_id = ?',
plan.runId,
),
mutations: count(
client,
'SELECT count(*) AS count FROM "StepRunMutations" WHERE run_id = ?',
plan.runId,
),
starts: count(
client,
'SELECT count(*) AS count FROM "ModelInvocationStarts" ' +
'WHERE invocation_id = ?',
plan.invocationId,
),
completions: count(
client,
'SELECT count(*) AS count FROM "ModelInvocationCompletions" ' +
'WHERE invocation_id = ?',
plan.invocationId,
),
admissions: count(
client,
'SELECT count(*) AS count FROM "ModelInvocationPromptAdmissions" ' +
'WHERE request_id = ?',
plan.requestId,
),
finalizations: count(
client,
'SELECT count(*) AS count FROM "ModelInvocationPromptFinalizations" ' +
'WHERE request_id = ?',
plan.requestId,
),
};
}
function emptyFacts() {
return {
run: null,
step: null,
runEvents: 0,
attempts: 0,
mutations: 0,
starts: 0,
completions: 0,
admissions: 0,
finalizations: 0,
};
}
function admittedFacts() {
return {
run: { status: 'running', version: 2, eventSequence: 2 },
step: { kind: 'model', status: 'ready', version: 1 },
runEvents: 2,
attempts: 0,
mutations: 1,
starts: 0,
completions: 0,
admissions: 1,
finalizations: 0,
};
}
function modelCompletedFacts() {
return {
run: { status: 'running', version: 4, eventSequence: 4 },
step: { kind: 'model', status: 'succeeded', version: 3 },
runEvents: 4,
attempts: 0,
mutations: 3,
starts: 1,
completions: 1,
admissions: 1,
finalizations: 0,
};
}
function finalizedFacts() {
return {
run: { status: 'succeeded', version: 5, eventSequence: 5 },
step: { kind: 'model', status: 'succeeded', version: 3 },
runEvents: 5,
attempts: 0,
mutations: 3,
starts: 1,
completions: 1,
admissions: 1,
finalizations: 1,
};
}
async function verifyScenario({ databasePath, statePath, pointName }) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error('unknown crash point ' + pointName);
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
const client = openClient(databasePath, state.profile);
const repository = new LocalPluginPackagePromptAdmissionRepository(client);
try {
assert.equal(
client.prepare('PRAGMA integrity_check').get().integrity_check,
'ok',
);
assert.equal(
client.prepare('PRAGMA journal_mode').get().journal_mode,
state.profile === 'edge' ? 'delete' : 'wal',
);
assert.deepEqual(client.prepare('PRAGMA foreign_key_check').all(), []);
const before = facts(client, state.plan);
if (point.operation === 'admission') {
assert.deepEqual(before, point.durable ? admittedFacts() : emptyFacts());
const replay = await repository.admit(state.plan);
assert.equal(replay.status, point.durable ? 'existing' : 'created');
assert.equal((await repository.admit(state.plan)).status, 'existing');
assert.deepEqual(facts(client, state.plan), admittedFacts());
} else {
assert.deepEqual(
before,
point.durable ? finalizedFacts() : modelCompletedFacts(),
);
const replay = await repository.finalize(state.plan.requestId);
assert.equal(replay.status, point.durable ? 'existing' : 'created');
assert.equal(
(await repository.finalize(state.plan.requestId)).status,
'existing',
);
assert.deepEqual(facts(client, state.plan), finalizedFacts());
}
const durableBytes = fs.readFileSync(databasePath);
assert.equal(
durableBytes.includes(Buffer.from('private crash matrix input')),
false,
);
assert.equal(
durableBytes.includes(Buffer.from('private crash matrix output')),
false,
);
return Object.freeze({
profile: state.profile,
operation: point.operation,
point: pointName,
crashBeforeCommit: !point.durable,
durableAfterCrash: point.durable,
exactReplay: true,
contentFree: true,
journalMode: client.prepare('PRAGMA journal_mode').get().journal_mode,
integrityCheck: 'ok',
foreignKeyCheck: 'ok',
physicalPowerLossProven: false,
});
} finally {
client.close();
}
}
if (require.main === module) {
const [mode, databasePath, statePath, markerPath, pointName] =
process.argv.slice(2);
if (mode !== 'crash') throw new Error('unknown mode ' + mode);
runCrashScenario({
databasePath,
statePath,
markerPath,
pointName,
}).catch((error) => {
process.stderr.write((error.stack ?? error.message) + '\n');
process.exitCode = 1;
});
}
module.exports = {
CRASH_POINTS,
setupScenario,
verifyScenario,
};
+602
View File
@@ -0,0 +1,602 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
BoundedModelGateway,
ModelAuditUnavailableError,
ModelBudgetExceededError,
ModelGatewayBusyError,
ModelInvocationAbortedError,
ModelInvocationDeadlineExceededError,
ModelInvocationReplayBlockedError,
ModelPolicyDeniedError,
} = require('../dist/model-gateway/gateway.js');
const {
ModelPriceUnavailableError,
StaticModelPriceCatalog,
createModelPriceCatalogEntry,
} = require('../dist/pricing/pricing.js');
const {
InvalidModelValueError,
normalizeModelInvocationPolicy,
} = require('../dist/model-gateway/validation.js');
const NOW = 1_000_000;
const disabledPricing = Object.freeze({
async resolve() {
throw new Error('pricing must remain unreachable');
},
});
function request(overrides = {}) {
return {
provider: 'remote',
model: 'model-a',
messages: [{ role: 'user', content: 'top secret prompt' }],
maxOutputTokens: 16,
...overrides,
};
}
function context(overrides = {}) {
return {
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
deadlineAtMs: NOW + 10_000,
...overrides,
};
}
function policy(overrides = {}) {
return {
revision: 'policy-1',
allowedProviders: ['remote'],
allowedModels: ['model-a'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 64,
maxTotalTokens: 256,
maxCostMicros: null,
priceRevision: null,
...overrides,
};
}
function provider(overrides = {}) {
return {
type: 'remote',
async listModels() {
return [{ id: 'model-a' }];
},
async generate() {
return {
provider: 'remote',
model: 'model-a',
text: 'safe summary',
finishReason: 'stop',
usage: { inputTokens: 5, outputTokens: 2, totalTokens: 7 },
};
},
async *stream() {
yield { delta: 'safe ' };
yield {
delta: 'summary',
finishReason: 'stop',
usage: { inputTokens: 5, outputTokens: 2, totalTokens: 7 },
};
},
...overrides,
};
}
test('policy rejects an output token limit above its total token limit', () => {
assert.throws(
() =>
normalizeModelInvocationPolicy(
policy({ maxOutputTokens: 65, maxTotalTokens: 64 }),
),
InvalidModelValueError,
);
});
function gateway({
modelProvider = provider(),
resolvedPolicy = policy(),
auditRecords = [],
maxConcurrent = 1,
} = {}) {
return new BoundedModelGateway({
providers: [modelProvider],
policies: {
async resolve() {
return resolvedPolicy;
},
},
pricing: disabledPricing,
audit: {
async record(record) {
auditRecords.push(record);
},
},
maxConcurrent,
now: () => NOW,
});
}
test('generate binds Project/Run/StepRun and emits content-free bounded audit', async () => {
const auditRecords = [];
const instance = gateway({ auditRecords });
const result = await instance.generate(request(), context());
assert.equal(result.text, 'safe summary');
assert.equal(instance.activeInvocations, 0);
assert.deepEqual(
auditRecords.map((record) => record.phase),
['admitted', 'completed'],
);
assert.equal(auditRecords[0].projectId, 'project-a');
assert.equal(auditRecords[0].runId, 'run-a');
assert.equal(auditRecords[0].stepRunId, 'step-a');
assert.match(auditRecords[0].requestDigest, /^sha256:[0-9a-f]{64}$/);
assert.equal(
JSON.stringify(auditRecords).includes('top secret prompt'),
false,
);
assert.equal(JSON.stringify(auditRecords).includes('safe summary'), false);
assert.deepEqual(auditRecords[1].usage, {
inputTokens: 5,
outputTokens: 2,
totalTokens: 7,
});
});
test('priced invocation snapshots one exact revision before provider I/O', async () => {
const records = [];
let providerCalls = 0;
const pricing = new StaticModelPriceCatalog([
createModelPriceCatalogEntry({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
publishedAtMs: NOW - 1,
}),
]);
const instance = new BoundedModelGateway({
providers: [
provider({
async generate() {
providerCalls += 1;
return {
provider: 'remote',
model: 'model-a',
text: 'safe summary',
finishReason: 'stop',
usage: {
inputTokens: 5,
outputTokens: 2,
totalTokens: 7,
costMicros: 99_999,
},
};
},
}),
],
policies: {
async resolve() {
return policy({
priceRevision: 'price-1',
maxCostMicros: 100,
projectQuota: {
revision: 'quota-1',
windowMs: 3_600_000,
maxInvocations: 10,
maxTokens: 10_000,
maxCostMicros: 1_000,
},
});
},
},
pricing,
audit: {
async record(record) {
records.push({ record });
},
async recordWithPricing(record, quote, quotaAdmission) {
records.push({ record, quote, quotaAdmission });
},
},
maxConcurrent: 1,
now: () => NOW,
});
const result = await instance.generate(request(), context());
assert.equal(providerCalls, 1);
assert.equal(records[0].record.phase, 'admitted');
assert.equal(records[0].quote.priceRevision, 'price-1');
assert.equal(records[0].quote.reservedCostMicros, 46);
assert.equal(records[0].quotaAdmission.reservedCostMicros, 46);
assert.equal(records[1].record.usage.costMicros, 3);
assert.equal(result.usage.costMicros, 3);
});
test('missing exact price revision fails before provider I/O', async () => {
let providerCalls = 0;
const instance = new BoundedModelGateway({
providers: [
provider({
async generate() {
providerCalls += 1;
throw new Error('must remain unreachable');
},
}),
],
policies: {
async resolve() {
return policy({ priceRevision: 'missing-price' });
},
},
pricing: {
async resolve() {
return null;
},
},
audit: {
async record() {
throw new Error('must remain unreachable');
},
},
maxConcurrent: 1,
now: () => NOW,
});
await assert.rejects(
instance.generate(request(), context()),
ModelPriceUnavailableError,
);
assert.equal(providerCalls, 0);
});
test('policy denies a provider or model before external I/O', async () => {
let calls = 0;
const instance = gateway({
resolvedPolicy: policy({ allowedModels: ['model-b'] }),
modelProvider: provider({
async generate() {
calls += 1;
throw new Error('must not run');
},
}),
});
await assert.rejects(
instance.generate(request(), context()),
ModelPolicyDeniedError,
);
assert.equal(calls, 0);
assert.equal(instance.activeInvocations, 0);
});
test('durable admission replay never invokes the provider again', async () => {
let calls = 0;
const instance = new BoundedModelGateway({
providers: [
provider({
async generate() {
calls += 1;
return provider().generate();
},
}),
],
policies: {
async resolve() {
return policy();
},
},
pricing: disabledPricing,
audit: {
async record(record) {
return {
status: record.phase === 'admitted' ? 'existing' : 'created',
};
},
},
maxConcurrent: 1,
now: () => NOW,
});
await assert.rejects(
instance.generate(request(), context()),
ModelInvocationReplayBlockedError,
);
assert.equal(calls, 0);
assert.equal(instance.activeInvocations, 0);
});
test('post-response token and byte budgets fail closed and are audited', async () => {
const auditRecords = [];
const instance = gateway({
auditRecords,
resolvedPolicy: policy({ maxOutputBytes: 4 }),
});
await assert.rejects(
instance.generate(request(), context()),
ModelBudgetExceededError,
);
assert.deepEqual(
auditRecords.map((record) => [record.phase, record.errorCode]),
[
['admitted', null],
['failed', 'MODEL_BUDGET_EXCEEDED'],
],
);
});
test('process-local concurrency is bounded without a hidden queue', async () => {
let release;
const blocked = new Promise((resolve) => {
release = resolve;
});
const instance = gateway({
modelProvider: provider({
async generate() {
await blocked;
return {
provider: 'remote',
model: 'model-a',
text: 'ok',
finishReason: 'stop',
usage: { inputTokens: 1, outputTokens: 1, totalTokens: 2 },
};
},
}),
});
const first = instance.generate(request(), context());
await new Promise((resolve) => setImmediate(resolve));
assert.equal(instance.activeInvocations, 1);
await assert.rejects(
instance.generate(
request(),
context({ requestId: 'request-b', traceId: 'trace-b' }),
),
ModelGatewayBusyError,
);
release();
await first;
assert.equal(instance.activeInvocations, 0);
});
test('policy resolution consumes concurrency and cannot bypass the deadline', async (t) => {
const now = 1_000_000;
t.mock.timers.enable({
apis: ['Date', 'setTimeout'],
now,
});
let releasePolicy;
const pendingPolicy = new Promise((resolve) => {
releasePolicy = resolve;
});
let markPolicyEntered;
const policyEntered = new Promise((resolve) => {
markPolicyEntered = resolve;
});
let providerCalls = 0;
const instance = new BoundedModelGateway({
providers: [
provider({
async generate(...args) {
providerCalls += 1;
return provider().generate(...args);
},
}),
],
policies: {
async resolve() {
markPolicyEntered();
return pendingPolicy;
},
},
pricing: disabledPricing,
audit: { async record() {} },
maxConcurrent: 1,
});
const first = instance.generate(
request(),
context({ deadlineAtMs: now + 40 }),
);
await policyEntered;
assert.equal(instance.activeInvocations, 1);
await assert.rejects(
instance.generate(
request(),
context({
requestId: 'request-policy-b',
traceId: 'trace-policy-b',
deadlineAtMs: Date.now() + 1000,
}),
),
ModelGatewayBusyError,
);
t.mock.timers.tick(40);
await assert.rejects(first, ModelInvocationDeadlineExceededError);
assert.equal(providerCalls, 0);
assert.equal(instance.activeInvocations, 0);
releasePolicy(policy());
});
test('a provider that ignores AbortSignal cannot hold the gateway past deadline', async () => {
const auditRecords = [];
const instance = new BoundedModelGateway({
providers: [
provider({
async generate() {
return new Promise(() => {});
},
}),
],
policies: {
async resolve() {
return policy();
},
},
pricing: disabledPricing,
audit: {
async record(record) {
auditRecords.push(record);
},
},
maxConcurrent: 1,
});
const startedAt = Date.now();
await assert.rejects(
instance.generate(request(), context({ deadlineAtMs: Date.now() + 40 })),
ModelInvocationDeadlineExceededError,
);
assert.ok(Date.now() - startedAt < 500);
assert.equal(instance.activeInvocations, 0);
assert.deepEqual(
auditRecords.map((record) => [record.phase, record.errorCode]),
[
['admitted', null],
['failed', 'MODEL_INVOCATION_DEADLINE_EXCEEDED'],
],
);
});
test('durable admission is never detached when its deadline expires', async () => {
let releaseAdmission;
const admissionBarrier = new Promise((resolve) => {
releaseAdmission = resolve;
});
let providerCalls = 0;
const auditRecords = [];
const instance = new BoundedModelGateway({
providers: [
provider({
async generate(...args) {
providerCalls += 1;
return provider().generate(...args);
},
}),
],
policies: {
async resolve() {
return policy();
},
},
pricing: disabledPricing,
audit: {
async record(record) {
auditRecords.push(record);
if (record.phase === 'admitted') await admissionBarrier;
},
},
maxConcurrent: 1,
});
const invocation = instance.generate(
request(),
context({ deadlineAtMs: Date.now() + 40 }),
);
await new Promise((resolve) => setTimeout(resolve, 70));
assert.equal(providerCalls, 0);
assert.equal(instance.activeInvocations, 1);
releaseAdmission();
await assert.rejects(invocation, ModelInvocationDeadlineExceededError);
assert.equal(providerCalls, 0);
assert.equal(instance.activeInvocations, 0);
assert.deepEqual(
auditRecords.map((record) => [record.phase, record.errorCode]),
[
['admitted', null],
['failed', 'MODEL_INVOCATION_DEADLINE_EXCEEDED'],
],
);
});
test('stream requires final usage and audits consumer cancellation', async () => {
const auditRecords = [];
const instance = gateway({ auditRecords });
const deltas = [];
for await (const chunk of instance.stream(request(), context())) {
deltas.push(chunk.delta);
}
assert.equal(deltas.join(''), 'safe summary');
assert.deepEqual(
auditRecords.map((record) => record.phase),
['admitted', 'completed'],
);
auditRecords.length = 0;
for await (const chunk of instance.stream(
request(),
context({ requestId: 'request-cancel', traceId: 'trace-cancel' }),
)) {
assert.equal(chunk.delta, 'safe ');
break;
}
assert.deepEqual(
auditRecords.map((record) => [record.phase, record.errorCode]),
[
['admitted', null],
['failed', 'MODEL_STREAM_CANCELLED'],
],
);
assert.equal(instance.activeInvocations, 0);
});
test('stream releases provider and concurrency when cancellation audit fails', async () => {
let disposed = false;
const instance = new BoundedModelGateway({
providers: [
provider({
async *stream() {
try {
yield { delta: 'first' };
yield {
delta: 'last',
usage: { inputTokens: 1, outputTokens: 1, totalTokens: 2 },
};
} finally {
disposed = true;
}
},
}),
],
policies: {
async resolve() {
return policy();
},
},
pricing: disabledPricing,
audit: {
async record(record) {
if (record.errorCode === 'MODEL_STREAM_CANCELLED') {
throw new Error('audit unavailable');
}
},
},
maxConcurrent: 1,
now: () => NOW,
});
await assert.rejects(async () => {
for await (const _chunk of instance.stream(request(), context())) {
break;
}
}, ModelAuditUnavailableError);
await new Promise((resolve) => setImmediate(resolve));
assert.equal(disposed, true);
assert.equal(instance.activeInvocations, 0);
});
@@ -0,0 +1,227 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { DatabaseSync } = require('node:sqlite');
const {
LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
LocalModelInvocationFeatureActivationRepository,
LocalModelInvocationFeatureTransitionConflictError,
LocalModelInvocationFeatureTransitionUnavailableError,
assertLocalModelInvocationFeatureActive,
createLocalModelInvocationFeatureTransitionCommand,
} = require('@qinglong/ai/local-feature-activation');
function createMainSqliteContract(client) {
client.exec(`
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (id TEXT PRIMARY KEY);
CREATE TABLE "RunEvents" (id TEXT PRIMARY KEY);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (mutation_id TEXT PRIMARY KEY);
`);
}
function principal(authenticationId = 'local_ai_feature:proof-1') {
return {
subject: { type: 'user', id: 'owner-user' },
authenticationId,
authenticatedAtMs: 1_000,
expiresAtMs: 301_000,
assurance: 'local_console',
};
}
function transition(overrides = {}) {
return createLocalModelInvocationFeatureTransitionCommand({
featureId: 'model-invocation',
expectedGeneration: 0,
expectedState: null,
state: 'active',
mutationId: 'feature-activation-1',
requestId: 'feature-request-1',
expectedMigrationDigest: LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
safety: {
mode: 'fresh_database',
backupEvidenceDigest: null,
},
principal: principal(),
...overrides,
});
}
async function fixture() {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
await migrateLocalModelInvocationFeature(client);
return client;
}
test('local AI feature activation is append-only, replay-safe and non-destructive', async () => {
const client = await fixture();
const repository = new LocalModelInvocationFeatureActivationRepository(
client,
);
assert.equal(repository.findCurrent(), null);
assert.throws(
() => assertLocalModelInvocationFeatureActive(client),
LocalModelInvocationFeatureTransitionUnavailableError,
);
const activated = repository.transition(transition());
assert.equal(activated.status, 'created');
assert.equal(activated.transition.generation, 1);
assert.equal(activated.transition.state, 'active');
assert.equal(
assertLocalModelInvocationFeatureActive(client).transitionDigest,
activated.transition.transitionDigest,
);
const replayed = repository.transition(transition());
assert.equal(replayed.status, 'existing');
assert.deepEqual(replayed.transition, activated.transition);
const deactivated = repository.transition(
transition({
expectedGeneration: 1,
expectedState: 'active',
state: 'inactive',
mutationId: 'feature-deactivation-1',
requestId: 'feature-request-2',
safety: {
mode: 'preserve_existing',
backupEvidenceDigest: null,
},
}),
);
assert.equal(deactivated.status, 'created');
assert.equal(deactivated.transition.generation, 2);
assert.equal(deactivated.transition.state, 'inactive');
assert.throws(
() => assertLocalModelInvocationFeatureActive(client),
LocalModelInvocationFeatureTransitionUnavailableError,
);
assert.deepEqual(
{
...client
.prepare(
`SELECT
(SELECT count(*) FROM "ModelInvocationFeatureTransitions") AS transitions,
(SELECT count(*) FROM "ModelInvocationFeatureHead") AS heads,
(SELECT count(*) FROM "ModelInvocationStarts") AS starts,
(SELECT count(*) FROM "ModelPriceCatalogPublications") AS publications`,
)
.get(),
},
{ transitions: 2, heads: 1, starts: 0, publications: 0 },
);
client.close();
});
test('local AI feature activation rejects CAS, plan and identity drift', async () => {
const client = await fixture();
const repository = new LocalModelInvocationFeatureActivationRepository(
client,
);
repository.transition(transition());
assert.throws(
() =>
repository.transition(
transition({
mutationId: 'feature-activation-conflict',
requestId: 'feature-request-conflict',
}),
),
LocalModelInvocationFeatureTransitionConflictError,
);
assert.throws(
() =>
repository.transition(
transition({
expectedGeneration: 1,
expectedState: 'active',
state: 'inactive',
mutationId: 'feature-deactivation-plan-drift',
requestId: 'feature-request-plan-drift',
expectedMigrationDigest: 'f'.repeat(64),
safety: {
mode: 'preserve_existing',
backupEvidenceDigest: null,
},
}),
),
LocalModelInvocationFeatureTransitionConflictError,
);
assert.throws(
() =>
repository.transition(
transition({
principal: principal('local_ai_feature:different-proof'),
}),
),
LocalModelInvocationFeatureTransitionConflictError,
);
client.close();
});
test('local AI feature transaction fence runs before replay and rolls back', async () => {
const client = await fixture();
let fences = 0;
const first = new LocalModelInvocationFeatureActivationRepository(client, {
beforeMutation() {
fences += 1;
},
});
first.transition(transition());
first.transition(transition());
assert.equal(fences, 2);
const rejected = new LocalModelInvocationFeatureActivationRepository(client, {
beforeMutation() {
throw new Error('fence rejected');
},
});
assert.throws(
() =>
rejected.transition(
transition({
expectedGeneration: 1,
expectedState: 'active',
state: 'inactive',
mutationId: 'feature-deactivation-rejected',
requestId: 'feature-request-rejected',
safety: {
mode: 'preserve_existing',
backupEvidenceDigest: null,
},
}),
),
LocalModelInvocationFeatureTransitionUnavailableError,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count
FROM "ModelInvocationFeatureTransitions"`,
)
.get().count,
1,
);
client.close();
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,338 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { DatabaseSync } = require('node:sqlite');
const {
ModelPriceCatalogConflictError,
createModelPriceCatalogPublishCommand,
createModelPriceCatalogTransitionCommand,
} = require('../dist/pricing/modelPriceCatalog.js');
const {
ModelPriceCatalogManagementSeparationOfDutyError,
createModelPriceCatalogAuthorizationCommand,
createModelPriceCatalogManagementService,
createModelPriceCatalogPolicyDecision,
} = require('../dist/pricing/modelPriceCatalogManagement.js');
const {
LocalModelPriceCatalogRepository,
} = require('../dist/pricing/storage/localModelPriceCatalogRepository.js');
const {
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
function createMainSqliteContract(client) {
client.exec(`
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (id TEXT PRIMARY KEY);
CREATE TABLE "RunEvents" (id TEXT PRIMARY KEY);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (mutation_id TEXT PRIMARY KEY);
`);
}
async function fixture(decisionMode = 'human_confirmation') {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
await migrateLocalModelInvocationFeature(client);
const repository = new LocalModelPriceCatalogRepository(client);
const now = Date.now();
const service = createModelPriceCatalogManagementService(repository, {
decisionMode,
authorizer: {
async authorize() {
return createModelPriceCatalogPolicyDecision({
effect: 'allow',
revision: 'platform-policy-1',
reasons: ['catalog_operator'],
});
},
},
now: () => now,
});
return { client, repository, service, now };
}
function principal(userId, now) {
return {
subject: { type: 'user', id: userId },
authenticationId: `auth-${userId}`,
authenticatedAtMs: now - 1_000,
expiresAtMs: now + 60_000,
assurance: 'multi_factor',
};
}
function publication(userId, now, overrides = {}) {
return {
authorizationId: 'authorize-publish-1',
requestId: 'request-publish-1',
mutationId: 'publish-price-1',
provider: 'remote',
model: 'model-a',
principal: principal(userId, now),
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
...overrides,
};
}
function activation(userId, now, overrides = {}) {
return {
authorizationId: 'authorize-activate-1',
requestId: 'request-activate-1',
mutationId: 'activate-price-1',
provider: 'remote',
model: 'model-a',
principal: principal(userId, now),
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'activate',
priceRevision: 'price-1',
...overrides,
};
}
test('SQLite atomically commits catalog mutations with exact authorization facts', async () => {
const { client, repository, service, now } = await fixture();
const published = await service.publish(publication('owner', now));
const replayed = await service.publish(publication('owner', now));
assert.equal(published.status, 'created');
assert.equal(replayed.status, 'existing');
assert.deepEqual(replayed, {
status: 'existing',
publication: published.publication,
authorization: published.authorization,
});
const activated = await service.transition(activation('owner', now));
assert.equal(activated.status, 'created');
assert.equal(activated.head.activePriceRevision, 'price-1');
assert.deepEqual(
await repository.findAuthorization('authorize-activate-1'),
activated.authorization,
);
assert.deepEqual(
{
...client
.prepare(
`SELECT
(SELECT count(*) FROM "ModelPriceCatalogPublications") AS publications,
(SELECT count(*) FROM "ModelPriceCatalogHeads") AS heads,
(SELECT count(*) FROM "ModelPriceCatalogAuthorizations") AS authorizations`,
)
.get(),
},
{ publications: 1, heads: 1, authorizations: 2 },
);
assert.equal(client.prepare('PRAGMA foreign_key_check').all().length, 0);
await assert.rejects(
service.publish(
publication('owner', now, {
authorizationId: 'authorize-publish-drift',
}),
),
ModelPriceCatalogConflictError,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count FROM "ModelPriceCatalogAuthorizations"`,
)
.get().count,
2,
);
client.close();
});
test('SQLite replay accepts fresh reauthentication but preserves the first authorization fact', async () => {
const { client, repository, service, now } = await fixture();
const created = await service.publish(publication('owner', now));
const freshService = createModelPriceCatalogManagementService(repository, {
decisionMode: 'human_confirmation',
authorizer: {
async authorize() {
return createModelPriceCatalogPolicyDecision({
effect: 'allow',
revision: 'platform-policy-1',
reasons: ['catalog_operator'],
});
},
},
now: () => now + 1_000,
});
const replayed = await freshService.publish(
publication('owner', now + 1_000),
);
assert.equal(replayed.status, 'existing');
assert.deepEqual(replayed.authorization, created.authorization);
await assert.rejects(
freshService.publish(
publication('owner', now + 1_000, {
principal: {
...principal('owner', now + 1_000),
authenticationId: 'auth-different-proof',
},
}),
),
ModelPriceCatalogConflictError,
);
client.close();
});
test('SQLite authorization fence hook runs inside the catalog transaction before mutation', async () => {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
await migrateLocalModelInvocationFeature(client);
let checked = 0;
const repository = new LocalModelPriceCatalogRepository(client, {
beforeAuthorizedMutation() {
checked += 1;
const error = new Error('credential fence rejected');
error.code = 'TEST_CREDENTIAL_FENCE_REJECTED';
throw error;
},
});
const now = Date.now();
const service = createModelPriceCatalogManagementService(repository, {
decisionMode: 'human_confirmation',
authorizer: {
async authorize() {
return createModelPriceCatalogPolicyDecision({
effect: 'allow',
revision: 'platform-policy-1',
reasons: ['catalog_operator'],
});
},
},
now: () => now,
});
await assert.rejects(service.publish(publication('owner', now)), {
code: 'MODEL_PRICE_CATALOG_UNAVAILABLE',
});
assert.equal(checked, 1);
assert.deepEqual(
{
...client
.prepare(
`SELECT
(SELECT count(*) FROM "ModelPriceCatalogPublications") AS publications,
(SELECT count(*) FROM "ModelPriceCatalogAuthorizations") AS authorizations`,
)
.get(),
},
{ publications: 0, authorizations: 0 },
);
assert.equal(client.isTransaction, false);
client.close();
});
test('authorized activation rejects legacy raw publication without evidence', async () => {
const { client, repository, service, now } = await fixture();
await repository.publish(
createModelPriceCatalogPublishCommand({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
mutationId: 'legacy-publish-price-1',
publishedByUserId: 'owner',
}),
);
await assert.rejects(
service.transition(activation('owner', now)),
ModelPriceCatalogConflictError,
);
assert.equal(
client
.prepare(`SELECT count(*) AS count FROM "ModelPriceCatalogHeads"`)
.get().count,
0,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count FROM "ModelPriceCatalogAuthorizations"`,
)
.get().count,
0,
);
client.close();
});
test('SQLite enforces separation of duty again inside the catalog transaction', async () => {
const { client, repository, service, now } = await fixture(
'separation_of_duty',
);
await service.publish(publication('publisher', now));
await assert.rejects(
service.transition(activation('publisher', now)),
ModelPriceCatalogManagementSeparationOfDutyError,
);
const directCommand = createModelPriceCatalogTransitionCommand({
provider: 'remote',
model: 'model-a',
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'activate',
priceRevision: 'price-1',
mutationId: 'direct-activate-price-1',
changedByUserId: 'publisher',
});
const directAuthorization = createModelPriceCatalogAuthorizationCommand({
authorizationId: 'direct-same-user',
requestId: 'direct-same-user-request',
operation: 'activate',
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
catalogCommandDigest: directCommand.commandDigest,
principal: principal('publisher', now),
policy: createModelPriceCatalogPolicyDecision({
effect: 'allow',
revision: 'platform-policy-1',
reasons: ['catalog_operator'],
}),
decisionMode: 'separation_of_duty',
});
await assert.rejects(
repository.transitionAuthorized(directCommand, directAuthorization),
ModelPriceCatalogConflictError,
);
const reviewed = await service.transition(activation('reviewer', now));
assert.equal(reviewed.head.activePriceRevision, 'price-1');
assert.equal(
client
.prepare(`SELECT count(*) AS count FROM "ModelPriceCatalogHeads"`)
.get().count,
1,
);
assert.equal(
await repository
.findCurrent('remote', 'model-a')
.then((head) => head.activePriceRevision),
'price-1',
);
client.close();
});
@@ -0,0 +1,255 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { DatabaseSync } = require('node:sqlite');
const {
InvalidModelPriceCatalogError,
ModelPriceCatalogConflictError,
ModelPriceCatalogUnavailableError,
createModelPriceCatalogPublishCommand,
createModelPriceCatalogTransitionCommand,
} = require('../dist/pricing/modelPriceCatalog.js');
const {
LocalModelPriceCatalogRepository,
} = require('../dist/pricing/storage/localModelPriceCatalogRepository.js');
const {
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
function createMainSqliteContract(client) {
client.exec(`
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (id TEXT PRIMARY KEY);
CREATE TABLE "RunEvents" (id TEXT PRIMARY KEY);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (mutation_id TEXT PRIMARY KEY);
`);
}
async function fixture() {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
await migrateLocalModelInvocationFeature(client);
return {
client,
repository: new LocalModelPriceCatalogRepository(client),
};
}
function publish(revision, mutationId, rate = 150_000) {
return createModelPriceCatalogPublishCommand({
provider: 'remote',
model: 'model-a',
priceRevision: revision,
currency: 'USD',
inputMicrosPerMillionTokens: rate,
outputMicrosPerMillionTokens: rate * 4,
mutationId,
publishedByUserId: 'user-admin',
});
}
function transition(head, action, revision, mutationId) {
return createModelPriceCatalogTransitionCommand({
provider: 'remote',
model: 'model-a',
expectedGeneration: head?.generation ?? 0,
expectedHeadDigest: head?.headDigest ?? null,
action,
priceRevision: revision,
mutationId,
changedByUserId: 'user-admin',
});
}
test('SQLite durable catalog publishes, activates, switches and revokes exactly', async () => {
const { client, repository } = await fixture();
const firstCommand = publish('price-1', 'publish-price-1');
const first = await repository.publish(firstCommand);
assert.equal(first.status, 'created');
assert.deepEqual(await repository.publish(firstCommand), {
status: 'existing',
publication: first.publication,
});
assert.equal(
await repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
}),
null,
);
const firstActivationCommand = transition(
null,
'activate',
'price-1',
'activate-price-1',
);
const firstActivation = await repository.transition(firstActivationCommand);
assert.equal(firstActivation.status, 'created');
assert.deepEqual(await repository.transition(firstActivationCommand), {
status: 'existing',
head: firstActivation.head,
});
assert.equal(
(
await repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
})
).catalogDigest,
first.publication.entry.catalogDigest,
);
const second = await repository.publish(
publish('price-2', 'publish-price-2', 200_000),
);
const secondActivation = await repository.transition(
transition(firstActivation.head, 'activate', 'price-2', 'activate-price-2'),
);
assert.equal(
await repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
}),
null,
);
assert.equal(
(
await repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-2',
})
).catalogDigest,
second.publication.entry.catalogDigest,
);
const revokeFirst = await repository.transition(
transition(secondActivation.head, 'revoke', 'price-1', 'revoke-price-1'),
);
assert.equal(revokeFirst.head.activePriceRevision, 'price-2');
assert.equal(revokeFirst.head.revokedPriceRevision, 'price-1');
await assert.rejects(
repository.transition(
transition(revokeFirst.head, 'activate', 'price-1', 'reactivate-price-1'),
),
ModelPriceCatalogConflictError,
);
const revokeSecond = await repository.transition(
transition(revokeFirst.head, 'revoke', 'price-2', 'revoke-price-2'),
);
assert.equal(revokeSecond.head.activePriceRevision, null);
assert.equal(
await repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-2',
}),
null,
);
assert.equal(
client
.prepare(`SELECT count(*) AS count FROM "ModelPriceCatalogHeads"`)
.get().count,
4,
);
client.close();
});
test('SQLite catalog gives one winner and rolls stale mutations back', async () => {
const { client, repository } = await fixture();
await repository.publish(publish('price-1', 'publish-price-1'));
await repository.publish(publish('price-2', 'publish-price-2'));
const first = await repository.transition(
transition(null, 'activate', 'price-1', 'activate-price-1'),
);
const competing = await Promise.allSettled([
repository.transition(
transition(first.head, 'activate', 'price-2', 'activate-price-2-a'),
),
repository.transition(
transition(first.head, 'deactivate', null, 'deactivate-price-1-b'),
),
]);
assert.equal(
competing.filter((result) => result.status === 'fulfilled').length,
1,
);
assert.equal(
competing.filter(
(result) =>
result.status === 'rejected' &&
result.reason instanceof ModelPriceCatalogConflictError,
).length,
1,
);
assert.equal(
client
.prepare(`SELECT count(*) AS count FROM "ModelPriceCatalogHeads"`)
.get().count,
2,
);
client.close();
});
test('SQLite catalog fails closed on corrupted durable JSON', async () => {
const { client, repository } = await fixture();
await repository.publish(publish('price-1', 'publish-price-1'));
client.exec(`
PRAGMA ignore_check_constraints = ON;
UPDATE "ModelPriceCatalogPublications"
SET publication_json = '{}'
WHERE price_revision = 'price-1';
PRAGMA ignore_check_constraints = OFF;
`);
await assert.rejects(
repository.findPublication({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
}),
ModelPriceCatalogUnavailableError,
);
client.close();
});
test('SQLite catalog validates and preserves resolver cancellation', async () => {
const { client, repository } = await fixture();
await assert.rejects(
repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
signal: {},
}),
InvalidModelPriceCatalogError,
);
const controller = new AbortController();
const reason = new Error('catalog lookup cancelled');
const resolution = repository.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
signal: controller.signal,
});
controller.abort(reason);
await assert.rejects(resolution, reason);
client.close();
});
@@ -0,0 +1,349 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { DatabaseSync } = require('node:sqlite');
const {
MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
ModelProviderCredentialTransitionConflictError,
createModelProviderCredentialTransitionCommand,
} = require('../dist/model-provider-credential/modelProviderCredentialCatalog.js');
const {
ModelProviderCredentialAdministrationAuthorizationFenceConflictError,
modelProviderCredentialAdministrationOperationId,
} = require('../dist/model-provider-credential/modelProviderCredentialAdministration.js');
const {
LocalModelProviderCredentialRepository,
} = require('../dist/model-provider-credential/localModelProviderCredentialRepository.js');
const {
LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE,
migrateLocalModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
MODEL_PROVIDER_CREDENTIAL_AUDIT_SCHEMA,
MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
digestModelProviderCredentialBinding,
} = require('../dist/model-provider-credential/providerCredential.js');
const { createSecretRef } = require('@qinglong/runtime-core/secret-reference');
const PROJECT_ID = 'project-a';
const PROVIDER = 'openai-compatible';
const ACTOR = Object.freeze({ type: 'user', id: 'owner-a' });
const FENCE = Object.freeze({ projectVersion: 3, bindingVersion: 7 });
const BIND_MUTATION_ID = '019f7094-a853-4f3b-82ab-dfa08e6bd1c1';
function createMainContract(client) {
client.exec(`
PRAGMA foreign_keys = ON;
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (id TEXT PRIMARY KEY);
CREATE TABLE "RunEvents" (id TEXT PRIMARY KEY);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (mutation_id TEXT PRIMARY KEY);
CREATE TABLE "QingLong3LocalSecretEnvelopes" (
project_id TEXT NOT NULL,
secret_name TEXT NOT NULL,
version INTEGER NOT NULL,
PRIMARY KEY (project_id, secret_name, version)
);
`);
}
async function fixture(options = {}) {
const client = new DatabaseSync(':memory:');
createMainContract(client);
await migrateLocalModelInvocationFeature(client);
client
.prepare(
`INSERT INTO "QingLong3LocalSecretEnvelopes"
(project_id, secret_name, version) VALUES (?, ?, ?)`,
)
.run(PROJECT_ID, 'openai-token', 1);
return {
client,
repository: new LocalModelProviderCredentialRepository(client, {
now: options.now ?? (() => 100),
...(options.authorization
? { authorization: options.authorization }
: {}),
}),
};
}
function binding(overrides = {}) {
return Object.freeze({
schema: MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
projectId: PROJECT_ID,
provider: PROVIDER,
revision: 'credential-v1',
secretRef: createSecretRef({
projectId: PROJECT_ID,
name: 'openai-token',
version: 1,
}),
scheme: 'bearer',
...overrides,
});
}
function command(overrides = {}) {
return createModelProviderCredentialTransitionCommand({
schema: MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
mutationId: BIND_MUTATION_ID,
projectId: PROJECT_ID,
provider: PROVIDER,
expectedGeneration: 0,
action: 'bind',
binding: binding(),
changedBy: ACTOR,
...overrides,
});
}
function allowedAudit(catalogCommand, overrides = {}) {
return Object.freeze({
eventId: catalogCommand.mutationId,
requestId: 'request-administration-1',
operationId: modelProviderCredentialAdministrationOperationId(
catalogCommand.action,
),
projectId: catalogCommand.projectId,
subject: ACTOR,
authenticationId: 'authentication-1',
outcome: 'allowed',
reasons: ['project_owner'],
fence: FENCE,
occurredAtMs: 99,
...overrides,
});
}
function authorized(catalogCommand) {
return Object.freeze({
command: catalogCommand,
actor: ACTOR,
fence: FENCE,
audit: allowedAudit(catalogCommand),
});
}
function useAudit(activeBinding, requestId, occurredAtMs) {
return Object.freeze({
schema: MODEL_PROVIDER_CREDENTIAL_AUDIT_SCHEMA,
operation: 'generate',
projectId: PROJECT_ID,
provider: PROVIDER,
requestId,
bindingRevision: activeBinding.revision,
bindingDigest: digestModelProviderCredentialBinding(activeBinding),
occurredAtMs,
});
}
test('local credential repository binds an existing SecretRef and replays exactly', async () => {
const { client, repository } = await fixture();
const bind = command();
const created = await repository.commit(bind);
const replay = await repository.commit(bind);
assert.equal(created.status, 'created');
assert.equal(replay.status, 'existing');
assert.deepEqual(replay.transition, created.transition);
assert.deepEqual(
await repository.findCurrentTransition(PROJECT_ID, PROVIDER),
created.transition,
);
assert.deepEqual(
await repository.resolveModelProviderCredentialBinding({
projectId: PROJECT_ID,
provider: PROVIDER,
}),
bind.binding,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count
FROM "${LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE}"`,
)
.get().count,
13,
);
client.close();
});
test('local credential repository fails closed for missing SecretRef and stale generation', async () => {
const { client, repository } = await fixture();
const missing = command({
mutationId: '019f7094-a853-4f3b-82ab-dfa08e6bd1c2',
binding: binding({
secretRef: createSecretRef({
projectId: PROJECT_ID,
name: 'missing-token',
version: 1,
}),
}),
});
await assert.rejects(
repository.commit(missing),
ModelProviderCredentialTransitionConflictError,
);
assert.equal(
await repository.findCurrentTransition(PROJECT_ID, PROVIDER),
null,
);
await repository.commit(command());
await assert.rejects(
repository.commit(
command({
mutationId: '019f7094-a853-4f3b-82ab-dfa08e6bd1c3',
}),
),
ModelProviderCredentialTransitionConflictError,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count
FROM "ModelInvocationProviderCredentialTransitions"`,
)
.get().count,
1,
);
client.close();
});
test('authorized mutation and inspection revalidate inside the repository transaction', async () => {
const confirmations = [];
const authorization = {
confirm(input) {
assert.equal(input.value.actor.id, ACTOR.id);
assert.equal(input.value.fence.projectVersion, FENCE.projectVersion);
confirmations.push({ kind: input.kind, replay: input.replay });
},
};
const { client, repository } = await fixture({ authorization });
const bind = command();
assert.equal(
(await repository.commitAuthorized(authorized(bind))).status,
'created',
);
assert.equal(
(await repository.commitAuthorized(authorized(bind))).status,
'existing',
);
const inspected = await repository.inspectAuthorized({
projectId: PROJECT_ID,
provider: PROVIDER,
actor: ACTOR,
fence: FENCE,
audit: {
...allowedAudit(bind),
eventId: '019f7094-a853-4f3b-82ab-dfa08e6bd1c4',
operationId: 'model_provider_credential.inspect',
},
});
assert.equal(inspected.generation, 1);
assert.deepEqual(confirmations, [
{ kind: 'mutation', replay: false },
{ kind: 'mutation', replay: true },
{ kind: 'inspection', replay: false },
]);
client.close();
});
test('authorized replay fails closed when no authorization guard is installed', async () => {
const { client, repository } = await fixture();
const bind = command();
await repository.commit(bind);
await assert.rejects(
repository.commitAuthorized(authorized(bind)),
ModelProviderCredentialAdministrationAuthorizationFenceConflictError,
);
client.close();
});
test('authorization fence rejection rolls the complete credential mutation back', async () => {
const authorization = {
confirm() {
throw new ModelProviderCredentialAdministrationAuthorizationFenceConflictError();
},
};
const { client, repository } = await fixture({ authorization });
await assert.rejects(
repository.commitAuthorized(authorized(command())),
ModelProviderCredentialAdministrationAuthorizationFenceConflictError,
);
assert.deepEqual(
{
...client
.prepare(
`SELECT
(SELECT count(*) FROM "ModelInvocationProviderCredentialBindings") AS bindings,
(SELECT count(*) FROM "ModelInvocationProviderCredentialTransitions") AS transitions`,
)
.get(),
},
{ bindings: 0, transitions: 0 },
);
client.close();
});
test('credential use audit is content-free, idempotent and invalid after revoke', async () => {
const { client, repository } = await fixture();
const bind = command();
await repository.commit(bind);
await repository.record(useAudit(bind.binding, 'provider-request-1', 110));
await repository.record(useAudit(bind.binding, 'provider-request-1', 999));
assert.equal(
client
.prepare(
`SELECT count(*) AS count
FROM "ModelInvocationProviderCredentialAudits"`,
)
.get().count,
1,
);
assert.equal(
client
.prepare(
`SELECT audit_json AS value
FROM "ModelInvocationProviderCredentialAudits"`,
)
.get()
.value.includes('secretRef'),
false,
);
const revoke = command({
mutationId: '019f7094-a853-4f3b-82ab-dfa08e6bd1c5',
expectedGeneration: 1,
action: 'revoke',
binding: null,
});
await repository.commit(revoke);
assert.equal(
await repository.resolveModelProviderCredentialBinding({
projectId: PROJECT_ID,
provider: PROVIDER,
}),
null,
);
await assert.rejects(
repository.record(useAudit(bind.binding, 'provider-request-2', 120)),
ModelProviderCredentialTransitionConflictError,
);
client.close();
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,146 @@
const assert = require('node:assert/strict');
const { createHash } = require('node:crypto');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { DatabaseSync } = require('node:sqlite');
const { test } = require('node:test');
const {
LocalPluginPackagePromptOutputKeyRetirementRepository,
assertLocalPluginPackagePromptOutputKeyNotRetiring,
} = require('../dist/prompt-output/storage/localPluginPackagePromptOutputKeyRetirementRepository.js');
const {
PluginPackagePromptOutputKeyRetirementConflictError,
PluginPackagePromptOutputKeyRetirementUnavailableError,
createPluginPackagePromptOutputKeyRetirementPreparation,
pluginPackagePromptOutputKeyRetirementAbsenceProof,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRetirement.js');
const {
setupScenario,
} = require('./fixtures/pluginPackagePromptCrashFixture.cjs');
const digest = (value) => createHash('sha256').update(value).digest('hex');
async function harness(t) {
const directory = fs.mkdtempSync(
path.join(os.tmpdir(), 'ql3-prompt-output-key-retirement-'),
);
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
const databasePath = path.join(directory, 'runtime.sqlite');
await setupScenario({
databasePath,
statePath: path.join(directory, 'state.json'),
profile: 'edge',
operation: 'admission',
});
const client = new DatabaseSync(databasePath);
client.exec('PRAGMA foreign_keys = ON');
t.after(() => client.close());
const authority = {
client,
async enqueue(work) {
return work();
},
};
let nowMs = 100;
return {
client,
repository: new LocalPluginPackagePromptOutputKeyRetirementRepository({
authority,
now: () => nowMs,
}),
setNow(value) {
nowMs = value;
},
};
}
function command() {
return {
keyId: 'prompt-output-key-old',
retirementId: 'retire-prompt-output-key-old',
requestId: 'request-retire-prompt-output-key-old',
mutationId: 'mutation-retire-prompt-output-key-old',
catalogDigest: digest('catalog-before'),
materialProof: digest('material-old'),
};
}
test('SQLite appends one retirement preparation and completion with exact replay', async (t) => {
const value = await harness(t);
const prepared = await value.repository.prepare(command());
assert.equal(prepared.status, 'created');
assert.equal(prepared.preparation.preparedAtMs, 100);
assert.throws(
() =>
assertLocalPluginPackagePromptOutputKeyNotRetiring(
value.client,
command().keyId,
),
PluginPackagePromptOutputKeyRetirementConflictError,
);
const retiredCatalogDigest = digest('catalog-after');
const absenceProof = pluginPackagePromptOutputKeyRetirementAbsenceProof(
prepared.preparation,
retiredCatalogDigest,
);
value.setNow(200);
const completed = await value.repository.complete({
preparation: prepared.preparation,
retiredCatalogDigest,
absenceProof,
});
assert.equal(completed.status, 'created');
assert.equal(completed.completion.completedAtMs, 200);
value.setNow(999);
assert.equal((await value.repository.prepare(command())).status, 'existing');
assert.equal(
(
await value.repository.complete({
preparation: prepared.preparation,
retiredCatalogDigest,
absenceProof,
})
).status,
'existing',
);
assert.deepEqual(await value.repository.find(command().keyId), {
preparation: prepared.preparation,
completion: completed.completion,
});
});
test('SQLite rejects detached completion, command drift and corrupt durable JSON', async (t) => {
const value = await harness(t);
const detached = createPluginPackagePromptOutputKeyRetirementPreparation({
...command(),
preparedAtMs: 100,
});
await assert.rejects(
value.repository.complete({
preparation: detached,
retiredCatalogDigest: digest('catalog-after'),
absenceProof: digest('absence'),
}),
PluginPackagePromptOutputKeyRetirementConflictError,
);
const prepared = await value.repository.prepare(command());
await assert.rejects(
value.repository.prepare({ ...command(), requestId: 'drifted-request' }),
PluginPackagePromptOutputKeyRetirementConflictError,
);
value.client.exec('PRAGMA ignore_check_constraints = ON');
value.client
.prepare(
`UPDATE "ModelInvocationPromptOutputKeyRetirementPreparations"
SET preparation_json = '{"corrupt":true}'
WHERE key_id = ?`,
)
.run(prepared.preparation.keyId);
value.client.exec('PRAGMA ignore_check_constraints = OFF');
await assert.rejects(
value.repository.find(prepared.preparation.keyId),
PluginPackagePromptOutputKeyRetirementUnavailableError,
);
});
@@ -0,0 +1,224 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
createStepRunRecord,
transitionStepRunMutation,
} = require('@qinglong/runtime-core/step-run');
const {
InvalidModelInvocationError,
createModelInvocationCompletionCommand,
createModelInvocationMutationIdentity,
createModelInvocationStartCommand,
normalizeModelInvocationCompletionCommand,
normalizeModelInvocationStartCommand,
} = require('../dist/model-invocation/modelInvocation.js');
const NOW = 1_000_000;
function readyStepRun() {
return createStepRunRecord({
id: 'step-a',
runId: 'run-a',
stepKey: 'summarize',
kind: 'model',
definitionRef: 'prompt:summary@1',
definitionDigest: 'a'.repeat(64),
required: true,
initialStatus: 'ready',
inputRef: 'artifact:input-a',
mutationId: 'create-step-a',
createdAtMs: NOW - 1,
});
}
function audit(phase, overrides = {}) {
return {
phase,
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
provider: 'remote',
model: 'model-a',
policyRevision: 'policy-1',
requestDigest: `sha256:${'b'.repeat(64)}`,
deadlineAtMs: NOW + 10_000,
inputBytes: 128,
maxOutputTokens: 64,
outputBytes: 0,
usage: null,
errorCode: null,
occurredAtMs: NOW,
...overrides,
};
}
function startFixture(requestId = 'request-a') {
const current = readyStepRun();
const identity = createModelInvocationMutationIdentity(requestId, 'start');
const mutation = transitionStepRunMutation(
current,
{
expectedVersion: current.version,
expectedDigest: current.stepRunDigest,
mutationId: identity.mutationId,
to: 'running',
atMs: NOW,
},
{
expectedRunVersion: 1,
expectedRunEventSequence: 1,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
);
return createModelInvocationStartCommand(
audit('admitted', { requestId }),
mutation,
);
}
function completionFixture({ requestId = 'request-a', errorCode = null } = {}) {
const startCommand = startFixture(requestId);
const identity = createModelInvocationMutationIdentity(
requestId,
'completion',
);
const failed = errorCode !== null;
const timedOut = errorCode === 'MODEL_INVOCATION_DEADLINE_EXCEEDED';
const lost =
errorCode === 'MODEL_INVOCATION_ABORTED' ||
errorCode === 'MODEL_STREAM_CANCELLED';
const status = timedOut
? 'timed_out'
: lost
? 'lost'
: failed
? 'failed'
: 'succeeded';
const mutation = transitionStepRunMutation(
startCommand.stepRunMutation.stepRun,
{
expectedVersion: startCommand.start.startedStepRunVersion,
expectedDigest: startCommand.start.startedStepRunDigest,
mutationId: identity.mutationId,
to: status,
atMs: NOW + 25,
...(failed
? {
resultCode: timedOut
? 'model_deadline_exceeded'
: lost
? 'model_outcome_unknown'
: 'model_provider_failed',
errorSummary: timedOut
? 'Model invocation deadline exceeded'
: lost
? 'Model invocation outcome is unknown'
: 'Model invocation failed',
}
: { outputRef: `model-invocation:${requestId}` }),
},
{
expectedRunVersion: 2,
expectedRunEventSequence: 2,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
);
const completionAudit = audit(failed ? 'failed' : 'completed', {
requestId,
occurredAtMs: NOW + 25,
outputBytes: failed ? 0 : 12,
usage: failed ? null : { inputTokens: 5, outputTokens: 2, totalTokens: 7 },
errorCode,
});
return createModelInvocationCompletionCommand(
startCommand.start,
completionAudit,
mutation,
);
}
test('model invocation reuses one StepRun mutation chain without content', () => {
const start = startFixture();
const completion = completionFixture();
assert.deepEqual(normalizeModelInvocationStartCommand(start), start);
assert.deepEqual(
normalizeModelInvocationCompletionCommand(completion),
completion,
);
assert.equal(start.stepRunMutation.previousStatus, 'ready');
assert.equal(start.stepRunMutation.stepRun.status, 'running');
assert.equal(completion.stepRunMutation.previousStatus, 'running');
assert.equal(completion.stepRunMutation.stepRun.status, 'succeeded');
assert.equal(completion.completion.outcome, 'succeeded');
assert.equal(
JSON.stringify({ start, completion }).includes('top secret prompt'),
false,
);
});
test('deadline completion is terminal timed_out and not replayable', () => {
const completion = completionFixture({
errorCode: 'MODEL_INVOCATION_DEADLINE_EXCEEDED',
});
assert.equal(completion.completion.outcome, 'timed_out');
assert.equal(completion.stepRunMutation.stepRun.status, 'timed_out');
assert.equal(
completion.stepRunMutation.stepRun.resultCode,
'model_deadline_exceeded',
);
});
test('unknown provider outcome maps to lost for manual resolution', () => {
const completion = completionFixture({
errorCode: 'MODEL_INVOCATION_ABORTED',
});
assert.equal(completion.completion.outcome, 'outcome_unknown');
assert.equal(completion.stepRunMutation.stepRun.status, 'lost');
assert.equal(
completion.stepRunMutation.stepRun.resultCode,
'model_outcome_unknown',
);
});
test('max-length invocation IDs derive bounded stable mutation identities', () => {
const requestId = `r${'x'.repeat(127)}`;
const first = createModelInvocationMutationIdentity(requestId, 'start');
const replay = createModelInvocationMutationIdentity(requestId, 'start');
assert.deepEqual(first, replay);
assert.ok(first.mutationId.length <= 128);
assert.ok(first.eventId.length <= 128);
assert.ok(first.dedupeKey.length <= 128);
assert.doesNotThrow(() => startFixture(requestId));
});
test('trace drift and command digest tampering fail closed', () => {
const completion = completionFixture();
const drifted = {
...completion,
completion: { ...completion.completion, traceId: 'trace-b' },
};
const tampered = {
...completion,
commandDigest: '0'.repeat(64),
};
assert.throws(
() => normalizeModelInvocationCompletionCommand(drifted),
InvalidModelInvocationError,
);
assert.throws(
() => normalizeModelInvocationCompletionCommand(tampered),
InvalidModelInvocationError,
);
});
@@ -0,0 +1,93 @@
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const { test } = require('node:test');
const {
CRASH_POINTS,
setupScenario,
verifyScenario,
} = require('./fixtures/modelInvocationCrashFixture.cjs');
const FIXTURE_PATH = path.join(
__dirname,
'fixtures',
'modelInvocationCrashFixture.cjs',
);
test(
'survives the SQLite ModelInvocation start and completion crash matrix',
{ timeout: 120_000 },
async (context) => {
const reports = [];
for (const profile of ['edge', 'standalone']) {
for (const [pointName, point] of Object.entries(CRASH_POINTS)) {
const directory = fs.mkdtempSync(
path.join(os.tmpdir(), `ql3-model-invocation-${profile}-`),
);
context.after(() => {
fs.rmSync(directory, { recursive: true, force: true });
});
const databasePath = path.join(directory, 'runtime.sqlite');
const statePath = path.join(directory, 'state.json');
const markerPath = path.join(directory, 'crash-marker.json');
await setupScenario({
databasePath,
statePath,
profile,
operation: point.operation,
});
const crashed = spawnSync(
process.execPath,
[
FIXTURE_PATH,
'crash',
databasePath,
statePath,
markerPath,
pointName,
],
{
encoding: 'utf8',
timeout: 20_000,
},
);
assert.equal(
crashed.error,
undefined,
`${profile}/${pointName}: ${crashed.error?.message}`,
);
assert.equal(
crashed.signal,
'SIGKILL',
`${profile}/${pointName}: status=${crashed.status}, stderr=${crashed.stderr}`,
);
const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
assert.deepEqual(marker, {
schema: 'qinglong/sqlite-model-invocation-crash-marker@v1',
point: pointName,
pid: marker.pid,
});
reports.push(
await verifyScenario({ databasePath, statePath, pointName }),
);
}
}
assert.equal(reports.length, 14);
assert.equal(
reports.filter((report) => report.crashBeforeCommit).length,
10,
);
assert.equal(
reports.filter((report) => report.durableAfterCrash).length,
4,
);
assert.deepEqual(
[...new Set(reports.map((report) => report.journalMode))].sort(),
['delete', 'wal'],
);
assert.ok(reports.every((report) => report.integrityCheck === 'ok'));
},
);
@@ -0,0 +1,992 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { DatabaseSync } = require('node:sqlite');
const {
LOCAL_PLUGIN_PACKAGE_PROMPT_ADMISSION_MIGRATION_ID,
LOCAL_PLUGIN_PACKAGE_PROMPT_FINALIZATION_MIGRATION_ID,
LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_MIGRATION_ID,
LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_MIGRATION_ID,
LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_TOMBSTONE_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_FEATURE_ACTIVATION_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE,
LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
LOCAL_MODEL_PROVIDER_CREDENTIAL_CATALOG_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_QUOTA_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_PRICING_MIGRATION_ID,
LOCAL_MODEL_INVOCATION_USAGE_MIGRATION_ID,
LOCAL_MODEL_PRICE_CATALOG_AUTHORIZATION_MIGRATION_ID,
LOCAL_MODEL_PRICE_CATALOG_MIGRATION_ID,
POSTGRES_MODEL_INVOCATION_MIGRATION_ID,
POSTGRES_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE,
POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
POSTGRES_MODEL_INVOCATION_SCHEMA,
POSTGRES_MODEL_PROVIDER_CREDENTIAL_CATALOG_MIGRATION_ID,
POSTGRES_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_MIGRATION_ID,
POSTGRES_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_IDENTITY_MIGRATION_ID,
POSTGRES_MODEL_PROVIDER_CREDENTIAL_TEST_CONNECTION_MIGRATION_ID,
POSTGRES_MODEL_INVOCATION_QUOTA_MIGRATION_ID,
POSTGRES_MODEL_INVOCATION_PRICING_MIGRATION_ID,
POSTGRES_MODEL_INVOCATION_USAGE_MIGRATION_ID,
POSTGRES_MODEL_PRICE_CATALOG_AUTHORIZATION_MIGRATION_ID,
POSTGRES_MODEL_PRICE_CATALOG_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_ADMISSION_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_FINALIZATION_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_ROTATION_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_PRODUCT_AUTHORIZATION_MIGRATION_ID,
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_TOMBSTONE_MIGRATION_ID,
LocalModelInvocationFeatureNotReadyError,
assertLocalModelInvocationFeatureReady,
localModelInvocationMigrationDefinition,
migrateLocalModelInvocationFeature,
postgresModelInvocationMigrationDefinition,
} = require('@qinglong/ai/model-invocation-migration');
function createMainSqliteContract(client) {
client.exec(`
CREATE TABLE "QingLong3SchemaMigrations" (
migration_id TEXT PRIMARY KEY,
stream_id TEXT NOT NULL,
dialect TEXT NOT NULL,
checksum TEXT NOT NULL,
applied_at_ms INTEGER NOT NULL
);
CREATE TABLE "Runs" (id TEXT PRIMARY KEY);
CREATE TABLE "RunEvents" (id TEXT PRIMARY KEY);
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
UNIQUE (run_id, id)
);
CREATE TABLE "StepRunMutations" (mutation_id TEXT PRIMARY KEY);
`);
}
function localFeatureTables(client) {
return client
.prepare(
`SELECT name FROM sqlite_schema
WHERE type = 'table' AND
(name LIKE 'ModelInvocation%' OR name LIKE 'ModelPriceCatalog%')
ORDER BY name`,
)
.all()
.map((row) => row.name);
}
test('SQLite AI schema is an explicit independent feature migration', async () => {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
assert.deepEqual(localFeatureTables(client), []);
await migrateLocalModelInvocationFeature(client);
await migrateLocalModelInvocationFeature(client);
assert.deepEqual(localFeatureTables(client), [
'ModelInvocationCompletions',
'ModelInvocationFeatureHead',
'ModelInvocationFeatureTransitions',
'ModelInvocationPriceQuotes',
'ModelInvocationPriceSettlements',
'ModelInvocationPromptAdmissions',
'ModelInvocationPromptFinalizations',
'ModelInvocationPromptOutputArtifactTombstones',
'ModelInvocationPromptOutputArtifacts',
'ModelInvocationPromptOutputKeyRetirementCompletions',
'ModelInvocationPromptOutputKeyRetirementPreparations',
'ModelInvocationProviderCredentialAudits',
'ModelInvocationProviderCredentialBindings',
'ModelInvocationProviderCredentialTransitions',
'ModelInvocationQuotaReservations',
'ModelInvocationQuotaSettlements',
'ModelInvocationResolutions',
'ModelInvocationStarts',
'ModelInvocationUsageLedger',
'ModelPriceCatalogAuthorizations',
'ModelPriceCatalogHeads',
'ModelPriceCatalogPublications',
]);
const history = client
.prepare(
`SELECT migration_id, stream_id, checksum
FROM "${LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE}"
ORDER BY migration_id`,
)
.all();
assert.deepEqual(
history.map(({ migration_id, stream_id }) => ({
migration_id,
stream_id,
})),
[
{
migration_id: LOCAL_MODEL_INVOCATION_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_INVOCATION_USAGE_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_INVOCATION_QUOTA_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_INVOCATION_PRICING_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_PRICE_CATALOG_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_PRICE_CATALOG_AUTHORIZATION_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_INVOCATION_FEATURE_ACTIVATION_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_PLUGIN_PACKAGE_PROMPT_ADMISSION_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_PLUGIN_PACKAGE_PROMPT_FINALIZATION_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_TOMBSTONE_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id:
LOCAL_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
{
migration_id: LOCAL_MODEL_PROVIDER_CREDENTIAL_CATALOG_MIGRATION_ID,
stream_id: LOCAL_MODEL_INVOCATION_MIGRATION_STREAM_ID,
},
],
);
assert.equal(
history[0].checksum,
localModelInvocationMigrationDefinition.migrations[0].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[0].checksum,
'258e3fd9a250d53d7d0574c3c05b3f91c40c53b20a60b68a931babfc58a0451a',
);
assert.equal(
history[1].checksum,
localModelInvocationMigrationDefinition.migrations[1].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[1].checksum,
'37e5c9bbf3f459ff036a032fc564dfd8cd78325234c9d7916bfff886b1018da5',
);
assert.equal(
history[2].checksum,
localModelInvocationMigrationDefinition.migrations[2].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[2].checksum,
'fa734aac1a3f5affaf69f4fbe53a2c6ca628255ecdcde14c08b87b49d8162012',
);
assert.equal(
history[3].checksum,
localModelInvocationMigrationDefinition.migrations[3].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[3].checksum,
'572e37d2f44df43a50b51a07c1b4b0bb87fbb22e9cafbd3421ec7ab250036951',
);
assert.equal(
history[4].checksum,
localModelInvocationMigrationDefinition.migrations[4].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[4].checksum,
'20d5c288dfab65ac7ea75a96b7302f9d59cd1bfdf06af28f3868261f6e2e3013',
);
assert.equal(
history[5].checksum,
localModelInvocationMigrationDefinition.migrations[5].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[5].checksum,
'3ee48d1468569c9dc1fa9f04031a48a220161762d48eeac4cd924e2dcd7abd21',
);
assert.equal(
history[6].checksum,
localModelInvocationMigrationDefinition.migrations[6].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[6].checksum,
'2454987c61a48dc5286a883d755c709000e6fd630025373cb276723001bdcc6c',
);
assert.equal(
history[7].checksum,
localModelInvocationMigrationDefinition.migrations[7].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[7].checksum,
'7f0b675231a79a5917dab1b7088ac8c393afef448e35309ca2e3a691af45bc79',
);
assert.equal(
history[8].checksum,
localModelInvocationMigrationDefinition.migrations[8].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[8].checksum,
'bd4c6f9f72a16f7a0e8f6d7afc702c7fe1293e7fc6f60bc31f5604b30bbdd0b6',
);
assert.equal(
history[9].checksum,
localModelInvocationMigrationDefinition.migrations[9].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[9].checksum,
'79bf3edcccf273046cb8b8ab60a7a0da881efd4e641009fa3c5833013cb7a75b',
);
assert.equal(
history[10].checksum,
localModelInvocationMigrationDefinition.migrations[10].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[10].checksum,
'4283d738e3eeb99fce30d011fd7d090577aa897581ee83e691ae021eff3f369e',
);
assert.equal(
history[11].checksum,
localModelInvocationMigrationDefinition.migrations[11].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[11].checksum,
'213d255cc40c536bbdc5fa41691839e0eb8e869db5a53ed93df50295ca8d5fc5',
);
assert.equal(
history[12].checksum,
localModelInvocationMigrationDefinition.migrations[12].checksum,
);
assert.equal(
localModelInvocationMigrationDefinition.migrations[12].checksum,
'ca9bcb4370d747884a34fdeae5079fdd7ccdaadd5ba9f66dba2faab09cfa3abb',
);
assert.equal(
LOCAL_MODEL_INVOCATION_MIGRATION_PLAN_DIGEST,
'2720c6e45f82adbb03641d1c19e8ff7e1875a763a0b53d4910a46ca308800aa0',
);
assert.deepEqual(
client
.prepare(
`SELECT migration_id FROM "QingLong3SchemaMigrations"
ORDER BY migration_id`,
)
.all(),
[],
);
assert.equal(
client.prepare('PRAGMA integrity_check').get().integrity_check,
'ok',
);
client.close();
});
test('SQLite AI feature readiness is read-only and rejects partial or drifted schema', async () => {
const client = new DatabaseSync(':memory:');
client.exec('PRAGMA foreign_keys = ON');
createMainSqliteContract(client);
assert.throws(
() => assertLocalModelInvocationFeatureReady(client),
LocalModelInvocationFeatureNotReadyError,
);
await migrateLocalModelInvocationFeature(client);
assert.doesNotThrow(() => assertLocalModelInvocationFeatureReady(client));
client
.prepare(
`UPDATE "${LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE}"
SET checksum = ?
WHERE migration_id = ?`,
)
.run('f'.repeat(64), LOCAL_MODEL_PRICE_CATALOG_AUTHORIZATION_MIGRATION_ID);
assert.throws(
() => assertLocalModelInvocationFeatureReady(client),
LocalModelInvocationFeatureNotReadyError,
);
assert.equal(
client
.prepare(
`SELECT count(*) AS count
FROM "${LOCAL_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE}"`,
)
.get().count,
13,
);
client.close();
});
test('SQLite AI migration refuses to create a parallel baseline', async () => {
const client = new DatabaseSync(':memory:');
await assert.rejects(
migrateLocalModelInvocationFeature(client),
/requires the main SQLite migration stream/,
);
assert.deepEqual(localFeatureTables(client), []);
client.close();
});
test('PostgreSQL AI schema is an independent reviewed feature stream', async () => {
assert.equal(
POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
'ql3-ai-model-invocation-postgresql',
);
assert.equal(
POSTGRES_MODEL_INVOCATION_MIGRATION_ID,
'pg-9001-ai-model-invocations',
);
assert.equal(
POSTGRES_MODEL_INVOCATION_USAGE_MIGRATION_ID,
'pg-9002-ai-model-usage-ledger',
);
assert.equal(
POSTGRES_MODEL_INVOCATION_QUOTA_MIGRATION_ID,
'pg-9003-ai-model-usage-quota',
);
assert.equal(
POSTGRES_MODEL_INVOCATION_PRICING_MIGRATION_ID,
'pg-9004-ai-model-pricing-snapshots',
);
assert.equal(
POSTGRES_MODEL_PRICE_CATALOG_MIGRATION_ID,
'pg-9005-ai-model-price-catalog',
);
assert.equal(
POSTGRES_MODEL_PRICE_CATALOG_AUTHORIZATION_MIGRATION_ID,
'pg-9006-ai-model-price-catalog-authorizations',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_ADMISSION_MIGRATION_ID,
'pg-9007-ai-plugin-package-prompt-admissions',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_FINALIZATION_MIGRATION_ID,
'pg-9008-ai-plugin-package-prompt-finalizations',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_MIGRATION_ID,
'pg-9009-ai-plugin-package-prompt-output-artifacts',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_TOMBSTONE_MIGRATION_ID,
'pg-9010-ai-plugin-package-prompt-output-tombstones',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_MIGRATION_ID,
'pg-9011-ai-plugin-package-prompt-output-key-retirements',
);
assert.equal(
POSTGRES_MODEL_PROVIDER_CREDENTIAL_CATALOG_MIGRATION_ID,
'pg-9012-ai-model-provider-credential-catalog',
);
assert.equal(
POSTGRES_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_MIGRATION_ID,
'pg-9013-ai-model-provider-credential-management-boundary',
);
assert.equal(
POSTGRES_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_IDENTITY_MIGRATION_ID,
'pg-9014-ai-model-provider-credential-management-identity-ledger',
);
assert.equal(
POSTGRES_MODEL_PROVIDER_CREDENTIAL_TEST_CONNECTION_MIGRATION_ID,
'pg-9015-ai-model-provider-credential-test-connection',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_ROTATION_MIGRATION_ID,
'pg-9016-ai-plugin-package-prompt-output-key-rotation',
);
assert.equal(
POSTGRES_PLUGIN_PACKAGE_PROMPT_PRODUCT_AUTHORIZATION_MIGRATION_ID,
'pg-9017-ai-plugin-package-prompt-product-authorization',
);
assert.equal(
POSTGRES_MODEL_INVOCATION_MIGRATION_HISTORY_TABLE,
'ai_schema_migrations',
);
assert.equal(POSTGRES_MODEL_INVOCATION_SCHEMA, 'ql3_ai');
assert.equal(
postgresModelInvocationMigrationDefinition.migrationIdScheme,
'postgres-prefixed',
);
assert.match(
postgresModelInvocationMigrationDefinition.migrations[0].checksum,
/^[0-9a-f]{64}$/,
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[0].checksum,
'69f72286fba2988ba372f006eb894a7f8b89f4b1acd9da68dc1cdafc3ca96ea7',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[1].checksum,
'95ad6f46163b0bbc2583dddf492f91f767a00554683186f244d3f6a22a2ad00c',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[2].checksum,
'13ea1a904eb799bcae1b474d76b164a70748bdcca8e1e6ded9952921a291a855',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[3].checksum,
'd38b12c2640fdd9fe21dc43a4743fb3480c988fa0a87e210fd81074d87569d2f',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[4].checksum,
'7db1a80fab1aa3dee3a4c4bcae5add53758418504f63f4b7d253b090506d7864',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[5].checksum,
'486d46115e28e90604a47231fe95e3b1687649c063d93bf7ce267783f2a7165f',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[6].checksum,
'1ed94eae2225b26e89e8c5d34e265e143e8150ff1811f5d8ae1fda52a6603db0',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[7].checksum,
'8dfd02e8e4947acb03516795ae37ef7aae5ee52a25b1fe3cd1a8640782c5b235',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[8].checksum,
'cb4156b109694c2b3aaf60a870179da04e10b47dbddfc92db3a7c4a58dfd1c2d',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[9].checksum,
'8972237fa41c80d131c32b380f617e8c7720687980e9accfb08f8fb19b7d8b5f',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[10].checksum,
'843ea53460f6580801cb12428d35c5571fd36bbee64e7801d2c3f98ea39d8392',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[11].checksum,
'4c83f5dda3c922aefd77c58760881f926e63e33628120f2fe6c71a53b30a1248',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[12].checksum,
'c02a4c6b2953cc331580b6287283d33739c30c2e189d011f392c13ecea497224',
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations[13].checksum,
'02098fad764199bc5a7750483d050be5e5acdbcecd05c0975c3fe4e5be03c782',
);
assert.match(
postgresModelInvocationMigrationDefinition.migrations[14].checksum,
/^[0-9a-f]{64}$/,
);
assert.match(
postgresModelInvocationMigrationDefinition.migrations[16].checksum,
/^[0-9a-f]{64}$/,
);
assert.equal(
postgresModelInvocationMigrationDefinition.migrations.length,
17,
);
const retirementStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[10].up({
async query(statement) {
retirementStatements.push(statement);
return { rows: [] };
},
});
const retirementSql = retirementStatements.join('\n');
assert.match(
retirementSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_key_retirement_preparations"/,
);
assert.match(
retirementSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_key_retirement_completions"/,
);
assert.match(retirementSql, /TO ql3_runtime/);
assert.match(retirementSql, /TO ql3_ai_maintenance/);
const credentialStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[11].up({
async query(statement) {
credentialStatements.push(statement);
return { rows: [] };
},
});
const credentialSql = credentialStatements.join('\n');
assert.match(
credentialSql,
/CREATE TABLE "ql3_ai"\."model_provider_credential_bindings"/,
);
assert.match(
credentialSql,
/CREATE TABLE "ql3_ai"\."model_provider_credential_transitions"/,
);
assert.match(
credentialSql,
/CREATE TABLE "ql3_ai"\."model_provider_credential_audits"/,
);
assert.match(credentialSql, /TO ql3_runtime/);
assert.match(credentialSql, /TO ql3_ai_maintenance/);
const credentialManagementStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[12].up({
async query(statement) {
credentialManagementStatements.push(statement);
return { rows: [] };
},
});
const credentialManagementSql = credentialManagementStatements.join('\n');
assert.match(
credentialManagementSql,
/GRANT CONNECT ON DATABASE %I TO ql3_ai_credential_manager/,
);
assert.match(
credentialManagementSql,
/GRANT SELECT ON TABLE[\s\S]*"ql3"\."projects"[\s\S]*"ql3"\."project_role_bindings"[\s\S]*"ql3"\."security_audit_events"[\s\S]*TO ql3_ai_credential_manager/,
);
assert.match(
credentialManagementSql,
/GRANT INSERT ON TABLE "ql3"\."security_audit_events"[\s\S]*TO ql3_ai_credential_manager/,
);
assert.match(
credentialManagementSql,
/GRANT INSERT ON TABLE[\s\S]*model_provider_credential_bindings[\s\S]*model_provider_credential_transitions[\s\S]*TO ql3_ai_credential_manager/,
);
assert.doesNotMatch(
credentialManagementSql,
/GRANT[^;]*(?:model_invocation_prompt_output|ql3_ai_maintenance)/,
);
assert.match(
credentialManagementSql,
/REVOKE ALL ON TABLE[\s\S]*model_provider_credential_bindings[\s\S]*model_provider_credential_transitions[\s\S]*model_provider_credential_audits[\s\S]*FROM ql3_ai_maintenance/,
);
const credentialIdentityStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[13].up({
async query(statement) {
credentialIdentityStatements.push(statement);
return { rows: [] };
},
});
const credentialIdentitySql = credentialIdentityStatements.join('\n');
assert.match(
credentialIdentitySql,
/CREATE TABLE "ql3_ai"\."model_provider_credential_management_identity_keyset_ledger"/,
);
assert.match(
credentialIdentitySql,
/GRANT SELECT, INSERT, UPDATE[\s\S]*TO ql3_ai_credential_manager/,
);
assert.match(credentialIdentitySql, /FROM PUBLIC, ql3_ai_maintenance/);
assert.doesNotMatch(credentialIdentitySql, /GRANT[^;]*DELETE/);
const credentialTestStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[14].up({
async query(statement) {
credentialTestStatements.push(statement);
return { rows: [] };
},
});
const credentialTestSql = credentialTestStatements.join('\n');
for (const table of [
'model_provider_credential_test_plans',
'model_provider_credential_test_quota_buckets',
'model_provider_credential_test_executions',
'model_provider_credential_test_results',
]) {
assert.match(
credentialTestSql,
new RegExp(`CREATE TABLE "ql3_ai"\\."${table}"`),
);
}
assert.match(
credentialTestSql,
/GRANT CONNECT ON DATABASE %I TO ql3_ai_credential_tester/,
);
assert.match(
credentialTestSql,
/GRANT SELECT, INSERT, UPDATE ON TABLE[\s\S]*model_provider_credential_test_quota_buckets[\s\S]*TO ql3_ai_credential_manager/,
);
assert.match(
credentialTestSql,
/GRANT INSERT ON TABLE[\s\S]*model_provider_credential_test_executions[\s\S]*model_provider_credential_test_results[\s\S]*TO ql3_ai_credential_tester/,
);
for (const statement of credentialTestStatements.filter((value) =>
value.includes('TO ql3_ai_credential_tester'),
)) {
assert.doesNotMatch(statement, /GRANT[\s\S]*(?:UPDATE|DELETE)/);
}
const rotationStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[15].up({
async query(statement) {
rotationStatements.push(statement);
return { rows: [] };
},
});
const rotationSql = rotationStatements.join('\n');
assert.match(
rotationSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_key_rotation_preparations"/,
);
assert.match(
rotationSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_key_rotation_completions"/,
);
assert.match(
rotationSql,
/UNIQUE \(expected_secret_uid, expected_catalog_digest\)/,
);
assert.match(rotationSql, /TO ql3_ai_maintenance/);
assert.doesNotMatch(rotationSql, /GRANT[^;]*TO ql3_runtime/);
assert.doesNotMatch(rotationSql, /GRANT[^;]*(?:UPDATE|DELETE)/);
const productAuthorizationStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[16].up({
async query(statement) {
productAuthorizationStatements.push(statement);
return { rows: [] };
},
});
const productAuthorizationSql = productAuthorizationStatements.join('\n');
assert.match(
productAuthorizationSql,
/CREATE FUNCTION[\s\S]*plugin_package_prompt_authorize_admission/,
);
assert.match(productAuthorizationSql, /SECURITY DEFINER/);
assert.match(productAuthorizationSql, /TO ql3_runtime/);
assert.doesNotMatch(productAuthorizationSql, /GRANT[^;]*TO ql3_admin/);
const statements = [];
await postgresModelInvocationMigrationDefinition.migrations[0].up({
async query(statement) {
statements.push(statement);
return { rows: [] };
},
});
const sql = statements.join('\n');
assert.match(sql, /CREATE TABLE "ql3_ai"\."model_invocation_starts"/);
assert.match(sql, /CREATE TABLE "ql3_ai"\."model_invocation_completions"/);
assert.match(sql, /CREATE TABLE "ql3_ai"\."model_invocation_resolutions"/);
assert.match(
sql,
/FOREIGN KEY \(mutation_id\)[\s\S]*"ql3"\."step_run_mutations"/,
);
assert.match(sql, /FOREIGN KEY \(run_event_id\)[\s\S]*"ql3"\."run_events"/);
assert.match(
sql,
/REVOKE ALL ON TABLE[\s\S]*model_invocation_starts[\s\S]*FROM PUBLIC/,
);
assert.match(
sql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_resolutions[\s\S]*TO ql3_runtime/,
);
assert.doesNotMatch(sql, /model_invocation_(?:starts|completions)_step_uidx/);
assert.match(sql, /model_invocation_starts_step_history_idx/);
assert.match(sql, /model_invocation_completions_step_history_idx/);
assert.doesNotMatch(sql, /TO ql3_admin/);
assert.doesNotMatch(sql, /TO ql3_worker_ingress/);
const usageStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[1].up({
async query(statement) {
usageStatements.push(statement);
return { rows: [] };
},
});
const usageSql = usageStatements.join('\n');
assert.match(
usageSql,
/CREATE TABLE "ql3_ai"\."model_invocation_usage_ledger"/,
);
assert.match(
usageSql,
/FOREIGN KEY \(invocation_id, completion_digest\)[\s\S]*model_invocation_completions/,
);
assert.match(
usageSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_usage_ledger[\s\S]*TO ql3_runtime/,
);
assert.deepEqual(
usageStatements.filter((statement) => statement.startsWith('GRANT ')),
[
`GRANT SELECT, INSERT ON TABLE
"ql3_ai"."model_invocation_usage_ledger"
TO ql3_runtime`,
],
);
assert.doesNotMatch(usageSql, /TO ql3_admin|TO ql3_worker_ingress/);
const quotaStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[2].up({
async query(statement) {
quotaStatements.push(statement);
return { rows: [] };
},
});
const quotaSql = quotaStatements.join('\n');
assert.match(
quotaSql,
/CREATE TABLE "ql3_ai"\."model_invocation_quota_reservations"/,
);
assert.match(
quotaSql,
/CREATE TABLE "ql3_ai"\."model_invocation_quota_settlements"/,
);
assert.match(
quotaSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_quota_reservations[\s\S]*model_invocation_quota_settlements[\s\S]*TO ql3_runtime/,
);
assert.deepEqual(
quotaStatements.filter((statement) =>
/^(?:UPDATE|DELETE)\b/.test(statement),
),
[],
);
assert.doesNotMatch(quotaSql, /TO ql3_admin|TO ql3_worker_ingress/);
const pricingStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[3].up({
async query(statement) {
pricingStatements.push(statement);
return { rows: [] };
},
});
const pricingSql = pricingStatements.join('\n');
assert.match(
pricingSql,
/CREATE TABLE "ql3_ai"\."model_invocation_price_quotes"/,
);
assert.match(
pricingSql,
/CREATE TABLE "ql3_ai"\."model_invocation_price_settlements"/,
);
assert.match(
pricingSql,
/FOREIGN KEY \(invocation_id, quote_digest\)[\s\S]*model_invocation_price_quotes/,
);
assert.match(
pricingSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_price_quotes[\s\S]*model_invocation_price_settlements[\s\S]*TO ql3_runtime/,
);
assert.deepEqual(
pricingStatements.filter((statement) =>
/^(?:UPDATE|DELETE)\b/.test(statement),
),
[],
);
assert.doesNotMatch(pricingSql, /TO ql3_admin|TO ql3_worker_ingress/);
const catalogStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[4].up({
async query(statement) {
catalogStatements.push(statement);
return { rows: [] };
},
});
const catalogSql = catalogStatements.join('\n');
assert.match(
catalogSql,
/CREATE TABLE "ql3_ai"\."model_price_catalog_publications"/,
);
assert.match(
catalogSql,
/CREATE TABLE "ql3_ai"\."model_price_catalog_heads"/,
);
assert.match(
catalogSql,
/GRANT SELECT ON TABLE[\s\S]*model_price_catalog_publications[\s\S]*model_price_catalog_heads[\s\S]*TO ql3_runtime/,
);
assert.match(
catalogSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_price_catalog_publications[\s\S]*model_price_catalog_heads[\s\S]*TO ql3_admin/,
);
assert.doesNotMatch(
catalogSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*TO ql3_runtime/,
);
assert.doesNotMatch(
catalogSql,
/TO ql3_package_manager|TO ql3_package_executor|TO ql3_worker_ingress/,
);
assert.deepEqual(
catalogStatements.filter((statement) =>
/^(?:UPDATE|DELETE)\b/.test(statement),
),
[],
);
const authorizationStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[5].up({
async query(statement) {
authorizationStatements.push(statement);
return { rows: [] };
},
});
const authorizationSql = authorizationStatements.join('\n');
assert.match(
authorizationSql,
/CREATE TABLE "ql3_ai"\."model_price_catalog_authorizations"/,
);
assert.match(
authorizationSql,
/FOREIGN KEY \(publication_digest\)[\s\S]*model_price_catalog_publications/,
);
assert.match(
authorizationSql,
/FOREIGN KEY \(head_digest\)[\s\S]*model_price_catalog_heads/,
);
assert.match(
authorizationSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_price_catalog_authorizations[\s\S]*TO ql3_admin/,
);
assert.doesNotMatch(authorizationSql, /TO ql3_runtime/);
assert.deepEqual(
authorizationStatements.filter((statement) =>
/^(?:UPDATE|DELETE)\b/.test(statement),
),
[],
);
const promptAdmissionStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[6].up({
async query(statement) {
promptAdmissionStatements.push(statement);
return { rows: [] };
},
});
const promptAdmissionSql = promptAdmissionStatements.join('\n');
assert.match(
promptAdmissionSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_admissions"/,
);
assert.match(
promptAdmissionSql,
/REFERENCES "ql3"\."plugin_package_automation_publications"/,
);
assert.match(
promptAdmissionSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_prompt_admissions[\s\S]*TO ql3_runtime/,
);
assert.match(
promptAdmissionSql,
/CREATE FUNCTION[\s\S]*"ql3_ai"\."plugin_package_prompt_admission_snapshot"/,
);
assert.match(promptAdmissionSql, /plugin_package_automation_start_allowed/);
assert.match(
promptAdmissionSql,
/GRANT EXECUTE ON FUNCTION[\s\S]*plugin_package_prompt_admission_snapshot[\s\S]*TO ql3_runtime/,
);
assert.doesNotMatch(
promptAdmissionSql,
/TO ql3_admin|TO ql3_package_manager|TO ql3_worker_ingress/,
);
const promptFinalizationStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[7].up({
async query(statement) {
promptFinalizationStatements.push(statement);
return { rows: [] };
},
});
const promptFinalizationSql = promptFinalizationStatements.join('\n');
assert.match(
promptFinalizationSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_finalizations"/,
);
assert.match(
promptFinalizationSql,
/FOREIGN KEY \(event_id\)[\s\S]*REFERENCES "ql3"\."run_events"/,
);
assert.match(
promptFinalizationSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_prompt_finalizations[\s\S]*TO ql3_runtime/,
);
assert.doesNotMatch(
`${promptAdmissionSql}\n${promptFinalizationSql}`,
/GRANT (?:UPDATE|DELETE)|TO ql3_admin|TO ql3_worker_ingress/,
);
const promptOutputArtifactStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[8].up({
async query(statement) {
promptOutputArtifactStatements.push(statement);
return { rows: [] };
},
});
const promptOutputArtifactSql = promptOutputArtifactStatements.join('\n');
assert.match(
promptOutputArtifactSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_artifacts"/,
);
assert.match(
promptOutputArtifactSql,
/FOREIGN KEY \(invocation_id\)[\s\S]*model_invocation_prompt_admissions/,
);
assert.match(
promptOutputArtifactSql,
/FOREIGN KEY \(invocation_id\)[\s\S]*model_invocation_starts/,
);
assert.match(
promptOutputArtifactSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_prompt_output_artifacts[\s\S]*TO ql3_runtime/,
);
assert.doesNotMatch(
promptOutputArtifactSql,
/GRANT (?:UPDATE|DELETE)|TO ql3_admin|TO ql3_package_manager|TO ql3_package_executor|TO ql3_worker_ingress/,
);
const promptOutputTombstoneStatements = [];
await postgresModelInvocationMigrationDefinition.migrations[9].up({
async query(statement) {
promptOutputTombstoneStatements.push(statement);
return { rows: [] };
},
});
const promptOutputTombstoneSql = promptOutputTombstoneStatements.join('\n');
assert.match(
promptOutputTombstoneSql,
/CREATE TABLE "ql3_ai"\."model_invocation_prompt_output_artifact_tombstones"/,
);
assert.match(
promptOutputTombstoneSql,
/GRANT CONNECT ON DATABASE %I TO ql3_ai_maintenance/,
);
assert.match(
promptOutputTombstoneSql,
/FOREIGN KEY \(invocation_id\)[\s\S]*model_invocation_prompt_admissions/,
);
assert.match(
promptOutputTombstoneSql,
/GRANT SELECT ON TABLE[\s\S]*model_invocation_prompt_output_artifact_tombstones[\s\S]*TO ql3_runtime/,
);
assert.match(
promptOutputTombstoneSql,
/GRANT SELECT, DELETE ON TABLE[\s\S]*model_invocation_prompt_output_artifacts[\s\S]*TO ql3_ai_maintenance/,
);
assert.match(
promptOutputTombstoneSql,
/GRANT SELECT, INSERT ON TABLE[\s\S]*model_invocation_prompt_output_artifact_tombstones[\s\S]*TO ql3_ai_maintenance/,
);
assert.doesNotMatch(
promptOutputTombstoneSql,
/GRANT (?:UPDATE|DELETE)[\s\S]*model_invocation_prompt_output_artifact_tombstones|TO ql3_admin|TO ql3_package_manager|TO ql3_package_executor|TO ql3_worker_ingress/,
);
});
@@ -0,0 +1,206 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
InvalidModelPriceCatalogError,
MODEL_PRICE_CATALOG_HEAD_SCHEMA,
MODEL_PRICE_CATALOG_PUBLICATION_SCHEMA,
createModelPriceCatalogHead,
createModelPriceCatalogPublication,
createModelPriceCatalogPublishCommand,
createModelPriceCatalogTransitionCommand,
normalizeModelPriceCatalogHead,
normalizeModelPriceCatalogPublication,
normalizeModelPriceCatalogPublishCommand,
normalizeModelPriceCatalogTransitionCommand,
} = require('../dist/pricing/modelPriceCatalog.js');
const NOW = 1_000_000;
function publishCommand(overrides = {}) {
return createModelPriceCatalogPublishCommand({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
mutationId: 'publish-price-1',
publishedByUserId: 'user-admin',
...overrides,
});
}
function transitionCommand(overrides = {}) {
return createModelPriceCatalogTransitionCommand({
provider: 'remote',
model: 'model-a',
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'activate',
priceRevision: 'price-1',
mutationId: 'activate-price-1',
changedByUserId: 'user-admin',
...overrides,
});
}
test('publication binds a database time, exact price and User mutation', () => {
const command = publishCommand();
const publication = createModelPriceCatalogPublication(command, NOW);
assert.deepEqual(normalizeModelPriceCatalogPublishCommand(command), command);
assert.equal(publication.schema, MODEL_PRICE_CATALOG_PUBLICATION_SCHEMA);
assert.equal(publication.entry.publishedAtMs, NOW);
assert.equal(publication.publishedByUserId, 'user-admin');
assert.deepEqual(
normalizeModelPriceCatalogPublication(publication),
publication,
);
assert.throws(
() =>
normalizeModelPriceCatalogPublishCommand({
...command,
inputMicrosPerMillionTokens: command.inputMicrosPerMillionTokens + 1,
}),
InvalidModelPriceCatalogError,
);
});
test('head transitions activate, deactivate and permanently revoke revisions', () => {
const publication = createModelPriceCatalogPublication(publishCommand(), NOW);
const activate = transitionCommand();
const active = createModelPriceCatalogHead(
null,
activate,
publication,
false,
NOW + 1,
);
assert.deepEqual(
normalizeModelPriceCatalogTransitionCommand(activate),
activate,
);
assert.equal(active.schema, MODEL_PRICE_CATALOG_HEAD_SCHEMA);
assert.equal(active.generation, 1);
assert.equal(active.activePriceRevision, 'price-1');
assert.deepEqual(normalizeModelPriceCatalogHead(active), active);
assert.throws(
() =>
normalizeModelPriceCatalogHead({
...active,
action: 'deactivate',
}),
InvalidModelPriceCatalogError,
);
const deactivate = transitionCommand({
expectedGeneration: 1,
expectedHeadDigest: active.headDigest,
action: 'deactivate',
priceRevision: null,
mutationId: 'deactivate-price-1',
});
const inactive = createModelPriceCatalogHead(
active,
deactivate,
null,
false,
NOW + 2,
);
assert.equal(inactive.activePriceRevision, null);
assert.throws(
() =>
normalizeModelPriceCatalogHead({
...inactive,
action: 'activate',
}),
InvalidModelPriceCatalogError,
);
const revoke = transitionCommand({
expectedGeneration: 2,
expectedHeadDigest: inactive.headDigest,
action: 'revoke',
mutationId: 'revoke-price-1',
});
const revoked = createModelPriceCatalogHead(
inactive,
revoke,
publication,
false,
NOW + 3,
);
assert.equal(revoked.activePriceRevision, null);
assert.equal(revoked.revokedPriceRevision, 'price-1');
assert.deepEqual(normalizeModelPriceCatalogHead(revoked), revoked);
const reactivate = transitionCommand({
expectedGeneration: 3,
expectedHeadDigest: revoked.headDigest,
mutationId: 'reactivate-price-1',
});
assert.throws(
() =>
createModelPriceCatalogHead(
revoked,
reactivate,
publication,
true,
NOW + 4,
),
InvalidModelPriceCatalogError,
);
});
test('transition fences reject stale, detached and no-op changes', () => {
const publication = createModelPriceCatalogPublication(publishCommand(), NOW);
const active = createModelPriceCatalogHead(
null,
transitionCommand(),
publication,
false,
NOW + 1,
);
assert.throws(
() =>
createModelPriceCatalogHead(
active,
transitionCommand({ mutationId: 'stale-activation' }),
publication,
false,
NOW + 2,
),
InvalidModelPriceCatalogError,
);
assert.throws(
() =>
createModelPriceCatalogHead(
active,
transitionCommand({
expectedGeneration: 1,
expectedHeadDigest: active.headDigest,
mutationId: 'duplicate-activation',
}),
publication,
false,
NOW + 2,
),
InvalidModelPriceCatalogError,
);
assert.throws(
() =>
createModelPriceCatalogTransitionCommand({
provider: 'remote',
model: 'model-a',
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'deactivate',
priceRevision: 'price-1',
mutationId: 'invalid-deactivate',
changedByUserId: 'user-admin',
}),
InvalidModelPriceCatalogError,
);
});
@@ -0,0 +1,257 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
createModelPriceCatalogHead,
createModelPriceCatalogPublication,
createModelPriceCatalogPublishCommand,
} = require('../dist/pricing/modelPriceCatalog.js');
const {
InvalidModelPriceCatalogManagementValueError,
ModelPriceCatalogManagementAuthenticationError,
ModelPriceCatalogManagementAuthorizationError,
ModelPriceCatalogManagementSeparationOfDutyError,
createModelPriceCatalogAuthorization,
createModelPriceCatalogManagementService,
createModelPriceCatalogPolicyDecision,
normalizeModelPriceCatalogAuthorization,
normalizeModelPriceCatalogAuthorizationCommand,
} = require('../dist/pricing/modelPriceCatalogManagement.js');
const NOW = 2_000_000;
function principal(userId, assurance = 'multi_factor') {
return {
subject: { type: 'user', id: userId },
authenticationId: `auth-${userId}`,
authenticatedAtMs: NOW - 1_000,
expiresAtMs: NOW + 60_000,
assurance,
};
}
function policy(effect = 'allow') {
return createModelPriceCatalogPolicyDecision({
effect,
revision: 'platform-policy-7',
reasons: [effect === 'allow' ? 'catalog_operator' : 'catalog_denied'],
});
}
function fakeRepository(publishedByUserId = 'publisher') {
const calls = [];
return {
calls,
async findPublication(lookup) {
calls.push(['findPublication', lookup]);
return createModelPriceCatalogPublication(
createModelPriceCatalogPublishCommand({
provider: lookup.provider,
model: lookup.model,
priceRevision: lookup.priceRevision,
currency: 'USD',
inputMicrosPerMillionTokens: 100,
outputMicrosPerMillionTokens: 400,
mutationId: 'existing-publication',
publishedByUserId,
}),
NOW - 100,
);
},
async findCurrent() {
return null;
},
async findAuthorization() {
return null;
},
async publish() {
throw new Error('raw publish must not be used');
},
async transition() {
throw new Error('raw transition must not be used');
},
async resolve() {
return null;
},
async publishAuthorized(command, authorizationCommand) {
calls.push(['publishAuthorized', command, authorizationCommand]);
const publication = createModelPriceCatalogPublication(command, NOW);
const authorization = createModelPriceCatalogAuthorization(
authorizationCommand,
publication.publicationDigest,
NOW,
);
return { status: 'created', publication, authorization };
},
async transitionAuthorized(command, authorizationCommand) {
calls.push(['transitionAuthorized', command, authorizationCommand]);
const publication = await this.findPublication({
provider: command.provider,
model: command.model,
priceRevision: command.priceRevision,
});
const head = createModelPriceCatalogHead(
null,
command,
publication,
false,
NOW,
);
const authorization = createModelPriceCatalogAuthorization(
authorizationCommand,
head.headDigest,
NOW,
);
return { status: 'created', head, authorization };
},
};
}
function publishRequest(userId = 'publisher') {
return {
authorizationId: 'authorize-publish-1',
requestId: 'request-publish-1',
mutationId: 'publish-price-1',
provider: 'remote',
model: 'model-a',
principal: principal(userId),
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
};
}
function transitionRequest(userId = 'reviewer') {
return {
authorizationId: 'authorize-activate-1',
requestId: 'request-activate-1',
mutationId: 'activate-price-1',
provider: 'remote',
model: 'model-a',
principal: principal(userId),
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'activate',
priceRevision: 'price-1',
};
}
test('authorization fact binds strong User, policy, catalog command and commit', () => {
const decision = policy();
const serviceRepository = fakeRepository();
const service = createModelPriceCatalogManagementService(serviceRepository, {
decisionMode: 'human_confirmation',
authorizer: {
async authorize() {
return decision;
},
},
now: () => NOW,
});
return service.publish(publishRequest()).then((result) => {
assert.equal(result.authorization.operation, 'publish');
assert.equal(result.authorization.principal.subject.id, 'publisher');
assert.equal(result.authorization.policy.revision, 'platform-policy-7');
assert.equal(
result.authorization.resultDigest,
result.publication.publicationDigest,
);
assert.deepEqual(
normalizeModelPriceCatalogAuthorization(result.authorization),
result.authorization,
);
assert.deepEqual(
normalizeModelPriceCatalogAuthorizationCommand(
serviceRepository.calls[0][2],
),
serviceRepository.calls[0][2],
);
assert.throws(
() =>
normalizeModelPriceCatalogAuthorization({
...result.authorization,
resultDigest: 'f'.repeat(64),
}),
InvalidModelPriceCatalogManagementValueError,
);
});
});
test('management rejects weak principals and deny decisions before mutation', async () => {
const repository = fakeRepository();
let authorizations = 0;
const service = createModelPriceCatalogManagementService(repository, {
decisionMode: 'human_confirmation',
authorizer: {
async authorize() {
authorizations += 1;
return policy('deny');
},
},
now: () => NOW,
});
await assert.rejects(
service.publish({
...publishRequest(),
principal: principal('publisher', 'single_factor'),
}),
ModelPriceCatalogManagementAuthenticationError,
);
assert.equal(authorizations, 0);
await assert.rejects(
service.publish(publishRequest()),
ModelPriceCatalogManagementAuthorizationError,
);
assert.equal(authorizations, 1);
assert.equal(
repository.calls.some(([name]) => name === 'publishAuthorized'),
false,
);
});
test('cluster activation requires a different strong publishing User', async () => {
const sameUserRepository = fakeRepository('publisher');
const sameUserService = createModelPriceCatalogManagementService(
sameUserRepository,
{
decisionMode: 'separation_of_duty',
authorizer: {
async authorize() {
return policy();
},
},
now: () => NOW,
},
);
await assert.rejects(
sameUserService.transition(transitionRequest('publisher')),
ModelPriceCatalogManagementSeparationOfDutyError,
);
assert.equal(
sameUserRepository.calls.some(([name]) => name === 'transitionAuthorized'),
false,
);
const reviewedRepository = fakeRepository('publisher');
const reviewedService = createModelPriceCatalogManagementService(
reviewedRepository,
{
decisionMode: 'separation_of_duty',
authorizer: {
async authorize() {
return policy();
},
},
now: () => NOW,
},
);
const result = await reviewedService.transition(
transitionRequest('reviewer'),
);
assert.equal(result.head.activePriceRevision, 'price-1');
assert.equal(result.authorization.principal.subject.id, 'reviewer');
assert.equal(result.authorization.decisionMode, 'separation_of_duty');
});
@@ -0,0 +1,123 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
InvalidModelProviderCredentialAdministrationMutationError,
modelProviderCredentialAdministrationOperationId,
normalizeAuthorizedModelProviderCredentialTransitionMutation,
} = require('../dist/model-provider-credential/modelProviderCredentialAdministration.js');
const {
MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
createModelProviderCredentialTransitionCommand,
} = require('../dist/model-provider-credential/modelProviderCredentialCatalog.js');
const {
MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
} = require('../dist/model-provider-credential/providerCredential.js');
const { createSecretRef } = require('@qinglong/runtime-core/secret-reference');
const MUTATION_ID = '019f7094-a853-4f3b-82ab-dfa08e6bd1c1';
function command(overrides = {}) {
return createModelProviderCredentialTransitionCommand({
schema: MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
mutationId: MUTATION_ID,
projectId: 'project-a',
provider: 'openai-compatible',
expectedGeneration: 0,
action: 'bind',
binding: {
schema: MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
projectId: 'project-a',
provider: 'openai-compatible',
revision: 'credential-v1',
secretRef: createSecretRef({
projectId: 'project-a',
name: 'openai-token',
}),
scheme: 'bearer',
},
changedBy: { type: 'user', id: 'owner-a' },
...overrides,
});
}
function mutation(overrides = {}) {
const { command: commandOverrides, ...mutationOverrides } = overrides;
const catalogCommand = command(commandOverrides);
const fence = { projectVersion: 3, bindingVersion: 7 };
return {
command: catalogCommand,
actor: { type: 'user', id: 'owner-a' },
fence,
audit: {
eventId: catalogCommand.mutationId,
requestId: 'request-1',
operationId: modelProviderCredentialAdministrationOperationId(
catalogCommand.action,
),
projectId: catalogCommand.projectId,
subject: { type: 'user', id: 'owner-a' },
authenticationId: 'authentication-1',
outcome: 'allowed',
reasons: ['project_owner'],
fence,
occurredAtMs: 100,
},
...mutationOverrides,
};
}
test('bind administration binds actor, Project fence and allowed audit', () => {
const normalized =
normalizeAuthorizedModelProviderCredentialTransitionMutation(mutation());
assert.equal(normalized.command.action, 'bind');
assert.equal(normalized.audit.operationId, 'model_provider_credential.bind');
assert.deepEqual(normalized.actor, { type: 'user', id: 'owner-a' });
assert.deepEqual(normalized.fence, {
projectVersion: 3,
bindingVersion: 7,
});
});
test('revoke administration uses the exact revoke audit operation', () => {
const normalized =
normalizeAuthorizedModelProviderCredentialTransitionMutation(
mutation({
command: {
action: 'revoke',
binding: null,
expectedGeneration: 1,
},
}),
);
assert.equal(normalized.command.action, 'revoke');
assert.equal(
normalized.audit.operationId,
'model_provider_credential.revoke',
);
});
test('administration rejects actor, Project, audit and fence drift', () => {
const candidate = mutation();
for (const drift of [
{ actor: { type: 'user', id: 'owner-b' } },
{ audit: { ...candidate.audit, projectId: 'project-b' } },
{ audit: { ...candidate.audit, outcome: 'denied' } },
{
audit: {
...candidate.audit,
operationId: 'model_provider_credential.revoke',
},
},
{ fence: { projectVersion: 3, bindingVersion: 8 } },
]) {
assert.throws(
() =>
normalizeAuthorizedModelProviderCredentialTransitionMutation({
...candidate,
...drift,
}),
InvalidModelProviderCredentialAdministrationMutationError,
);
}
});
@@ -0,0 +1,103 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
InvalidModelProviderCredentialTransitionError,
ModelProviderCredentialTransitionConflictError,
createModelProviderCredentialTransition,
createModelProviderCredentialTransitionCommand,
modelProviderCredentialBindingForTransition,
normalizeModelProviderCredentialTransition,
} = require('../dist/model-provider-credential/modelProviderCredentialCatalog.js');
const {
MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
} = require('../dist/model-provider-credential/providerCredential.js');
const { createSecretRef } = require('@qinglong/runtime-core/secret-reference');
function binding(overrides = {}) {
return {
schema: MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
projectId: 'project-a',
provider: 'openai-compatible',
revision: 'credential-v1',
secretRef: createSecretRef({
projectId: 'project-a',
name: 'openai-token',
}),
scheme: 'bearer',
...overrides,
};
}
function command(overrides = {}) {
return createModelProviderCredentialTransitionCommand({
schema: MODEL_PROVIDER_CREDENTIAL_TRANSITION_COMMAND_SCHEMA,
mutationId: 'credential-bind-1',
projectId: 'project-a',
provider: 'openai-compatible',
expectedGeneration: 0,
action: 'bind',
binding: binding(),
changedBy: { type: 'user', id: 'owner-a' },
...overrides,
});
}
test('credential catalog creates an immutable bind/revoke hash chain', () => {
const bind = command();
const first = createModelProviderCredentialTransition(bind, null, 10);
assert.equal(first.generation, 1);
assert.equal(first.action, 'bind');
assert.equal(first.previousTransitionDigest, null);
assert.deepEqual(
modelProviderCredentialBindingForTransition(first, bind.binding),
bind.binding,
);
assert.deepEqual(normalizeModelProviderCredentialTransition(first), first);
const revoke = command({
mutationId: 'credential-revoke-2',
expectedGeneration: 1,
action: 'revoke',
binding: null,
});
const second = createModelProviderCredentialTransition(revoke, first, 20);
assert.equal(second.generation, 2);
assert.equal(second.action, 'revoke');
assert.equal(second.previousTransitionDigest, first.transitionDigest);
assert.equal(modelProviderCredentialBindingForTransition(second, null), null);
});
test('credential catalog rejects cross-Project binding and stale CAS', () => {
assert.throws(
() => command({ binding: binding({ projectId: 'project-b' }) }),
InvalidModelProviderCredentialTransitionError,
);
const firstCommand = command();
const first = createModelProviderCredentialTransition(firstCommand, null, 1);
assert.throws(
() => createModelProviderCredentialTransition(command(), first, 2),
ModelProviderCredentialTransitionConflictError,
);
});
test('credential transition tampering is detected before storage use', () => {
const first = createModelProviderCredentialTransition(command(), null, 1);
assert.throws(
() =>
normalizeModelProviderCredentialTransition({
...first,
activeBindingRevision: 'credential-v2',
}),
InvalidModelProviderCredentialTransitionError,
);
assert.throws(
() =>
modelProviderCredentialBindingForTransition(
first,
binding({ revision: 'credential-v2' }),
),
/unavailable/,
);
});
@@ -0,0 +1,143 @@
const assert = require('node:assert/strict');
const { randomUUID } = require('node:crypto');
const test = require('node:test');
const {
InvalidModelProviderCredentialTestConnectionError,
createModelProviderCredentialTestAllowlist,
createModelProviderCredentialTestExecution,
createModelProviderCredentialTestPlan,
createModelProviderCredentialTestResult,
normalizeModelProviderCredentialTestAllowlist,
normalizeModelProviderCredentialTestExecution,
normalizeModelProviderCredentialTestPlan,
normalizeModelProviderCredentialTestResult,
resolveModelProviderCredentialTestEndpoint,
} = require('../dist/model-provider-credential/modelProviderCredentialTestConnection.js');
function endpoint(overrides = {}) {
return {
provider: 'openai-compatible',
adapter: 'openai-compatible',
baseUrl: 'https://provider.example.test/v1/',
revision: 'provider-test-v1',
deadlineMs: 5_000,
maxResponseBytes: 64 * 1_024,
maxModels: 64,
maxCostMicrousd: 0,
retryLimit: 0,
...overrides,
};
}
function allowlist() {
return createModelProviderCredentialTestAllowlist({
revision: 'catalog-v1',
providers: [endpoint()],
});
}
test('freezes an exact HTTPS allowlist with zero retry and zero cost', () => {
const catalog = allowlist();
assert.deepEqual(
normalizeModelProviderCredentialTestAllowlist(catalog),
catalog,
);
assert.equal(catalog.providers[0].retryLimit, 0);
assert.equal(catalog.providers[0].maxCostMicrousd, 0);
assert.equal(
resolveModelProviderCredentialTestEndpoint(catalog, 'openai-compatible')
.configDigest,
catalog.providers[0].configDigest,
);
assert.throws(
() =>
createModelProviderCredentialTestAllowlist({
revision: 'catalog-v1',
providers: [endpoint({ baseUrl: 'http://metadata.internal/' })],
}),
InvalidModelProviderCredentialTestConnectionError,
);
assert.throws(
() =>
createModelProviderCredentialTestAllowlist({
revision: 'catalog-v1',
providers: [endpoint({ retryLimit: 1 })],
}),
InvalidModelProviderCredentialTestConnectionError,
);
});
test('binds one short-lived plan to the server-selected endpoint and fence', () => {
const selected = allowlist().providers[0];
const plan = createModelProviderCredentialTestPlan({
testId: randomUUID(),
requestId: 'provider-test-request-1',
projectId: 'project-a',
provider: selected.provider,
endpoint: selected,
requestedBy: { type: 'user', id: 'owner-a' },
fence: { projectVersion: 7, bindingVersion: 9 },
plannedAtMs: 1_000,
expiresAtMs: 61_000,
});
assert.deepEqual(normalizeModelProviderCredentialTestPlan(plan), plan);
assert.equal(JSON.stringify(plan).includes('secretRef'), false);
assert.throws(
() =>
normalizeModelProviderCredentialTestPlan({
...plan,
endpoint: { ...plan.endpoint, maxCostMicrousd: 1 },
}),
InvalidModelProviderCredentialTestConnectionError,
);
});
test('creates immutable execution intent before a content-free result', () => {
const testId = randomUUID();
const executionId = randomUUID();
const execution = createModelProviderCredentialTestExecution({
executionId,
testId,
planDigest: 'a'.repeat(64),
startedAtMs: 2_000,
});
assert.deepEqual(
normalizeModelProviderCredentialTestExecution(execution),
execution,
);
const result = createModelProviderCredentialTestResult({
executionId,
testId,
planDigest: execution.planDigest,
outcome: 'reachable',
modelCount: 12,
durationMs: 250,
completedAtMs: 2_250,
});
assert.deepEqual(normalizeModelProviderCredentialTestResult(result), result);
assert.deepEqual(Object.keys(result).sort(), [
'completedAtMs',
'durationMs',
'executionId',
'modelCount',
'outcome',
'planDigest',
'resultDigest',
'schema',
'testId',
]);
assert.throws(
() =>
createModelProviderCredentialTestResult({
executionId,
testId,
planDigest: execution.planDigest,
outcome: 'unreachable',
modelCount: 1,
durationMs: 250,
completedAtMs: 2_250,
}),
InvalidModelProviderCredentialTestConnectionError,
);
});
@@ -0,0 +1,271 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
OpenAiCompatibleConfigurationError,
OpenAiCompatibleProtocolError,
OpenAiCompatibleProvider,
} = require('../dist/model-gateway/openAiCompatibleProvider.js');
function context() {
return {
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
deadlineAtMs: Date.now() + 10_000,
};
}
function request() {
return {
provider: 'openai-compatible',
model: 'model-a',
messages: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 32,
};
}
test('remote endpoints require HTTPS while explicit loopback HTTP remains possible', () => {
assert.throws(
() =>
new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'http://models.example.test/v1/',
}),
OpenAiCompatibleConfigurationError,
);
assert.doesNotThrow(
() =>
new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'http://127.0.0.1:8080/v1/',
allowPlaintextLoopback: true,
}),
);
});
test('generate sends one bounded OpenAI-compatible request without retry', async () => {
const calls = [];
const credentialRequests = [];
let credentialDisposed = 0;
const instance = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
credentials: {
async authorizationHeader(request) {
credentialRequests.push(request);
return {
value: 'Bearer ephemeral-token',
dispose() {
credentialDisposed += 1;
},
};
},
},
async fetch(url, init) {
assert.equal(credentialDisposed, 0);
calls.push({ url: String(url), init });
return new Response(
JSON.stringify({
model: 'model-a',
choices: [
{
message: { role: 'assistant', content: 'world' },
finish_reason: 'stop',
},
],
usage: {
prompt_tokens: 2,
completion_tokens: 1,
total_tokens: 3,
},
}),
{
status: 200,
headers: { 'content-type': 'application/json' },
},
);
},
});
const result = await instance.generate(request(), context());
assert.equal(calls.length, 1);
assert.equal(credentialDisposed, 1);
assert.deepEqual(credentialRequests, [
{
operation: 'generate',
provider: 'openai-compatible',
projectId: 'project-a',
requestId: 'request-a',
},
]);
assert.equal(calls[0].url, 'https://models.example.test/v1/chat/completions');
assert.equal(calls[0].init.headers.authorization, 'Bearer ephemeral-token');
assert.deepEqual(JSON.parse(calls[0].init.body), {
model: 'model-a',
messages: [{ role: 'user', content: 'hello' }],
max_tokens: 32,
stream: false,
});
assert.deepEqual(result, {
provider: 'openai-compatible',
model: 'model-a',
text: 'world',
finishReason: 'stop',
usage: { inputTokens: 2, outputTokens: 1, totalTokens: 3 },
});
});
test('credential leases are disposed on network failure and malformed leases never reach fetch', async () => {
let disposed = 0;
const failing = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
credentials: {
async authorizationHeader() {
return {
value: 'Bearer short-lived',
dispose() {
disposed += 1;
},
};
},
},
async fetch() {
throw new Error('network unavailable');
},
});
await assert.rejects(
failing.generate(request(), context()),
/network unavailable/,
);
assert.equal(disposed, 1);
let calls = 0;
const malformed = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
credentials: {
async authorizationHeader() {
return {
value: 'Bearer value',
dispose() {
disposed += 1;
},
retained: true,
};
},
},
async fetch() {
calls += 1;
throw new Error('must not run');
},
});
await assert.rejects(
malformed.generate(request(), context()),
OpenAiCompatibleConfigurationError,
);
assert.equal(calls, 0);
assert.equal(disposed, 2);
});
test('adapter rejects provider identity drift before network access', async () => {
let calls = 0;
const instance = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
async fetch() {
calls += 1;
throw new Error('must not run');
},
});
await assert.rejects(
instance.generate(
{ ...request(), provider: 'another-provider' },
context(),
),
/request provider does not match the adapter/,
);
assert.equal(calls, 0);
});
test('stream parses arbitrarily split CRLF SSE and preserves final usage', async () => {
const encoder = new TextEncoder();
const payload = [
'data: {"choices":[{"delta":{"content":"hel"},"finish_reason":null}]}\r',
'\n\r\ndata: {"choices":[{"delta":{"content":"lo"},"finish_reason":"stop"}]}\r\n\r\n',
'data: {"choices":[],"usage":{"prompt_tokens":2,"completion_tokens":1,"total_tokens":3}}\r\n\r\n',
'data: [DONE]\r\n\r\n',
];
const instance = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
async fetch(_url, init) {
assert.equal(JSON.parse(init.body).stream_options.include_usage, true);
return new Response(
new ReadableStream({
start(controller) {
for (const part of payload)
controller.enqueue(encoder.encode(part));
controller.close();
},
}),
{
status: 200,
headers: { 'content-type': 'text/event-stream' },
},
);
},
});
const chunks = [];
for await (const chunk of instance.stream(request(), context())) {
chunks.push(chunk);
}
assert.equal(chunks.map((chunk) => chunk.delta).join(''), 'hello');
assert.equal(chunks[1].finishReason, 'stop');
assert.deepEqual(chunks[2].usage, {
inputTokens: 2,
outputTokens: 1,
totalTokens: 3,
});
});
test('protocol rejects missing usage and over-limit responses', async () => {
const missingUsage = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
async fetch() {
return new Response(
JSON.stringify({
model: 'model-a',
choices: [
{
message: { content: 'world' },
finish_reason: 'stop',
},
],
}),
);
},
});
await assert.rejects(
missingUsage.generate(request(), context()),
OpenAiCompatibleProtocolError,
);
const tooLarge = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
maxResponseBytes: 32,
async fetch() {
return new Response(JSON.stringify({ data: [{ id: 'x'.repeat(64) }] }));
},
});
await assert.rejects(tooLarge.listModels(), OpenAiCompatibleProtocolError);
});
@@ -0,0 +1,103 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
createPluginPackagePromptCatalogResult,
PLUGIN_PACKAGE_PROMPT_CATALOG_SCHEMA,
} = require('../dist/prompt/pluginPackagePromptCatalog.js');
const {
PostgresPluginPackagePromptCatalogService,
} = require('../dist/prompt/postgresPluginPackagePromptApplication.js');
const {
createInitialPluginPackageAutomationPublication,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
const {
pluginPackageTaskReconciliationFixture,
} = require('../../../test/contracts/pluginPackageTaskReconciliationRepositoryContract.cjs');
function publication() {
const source = pluginPackageTaskReconciliationFixture('prompt-catalog', {
profile: 'cluster-control',
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
description: 'Summarizes input',
template: 'Private template {{subject}}.',
parameters: [
{
name: 'subject',
description: 'Text to summarize',
required: true,
},
],
},
],
});
return createInitialPluginPackageAutomationPublication(
source.revision,
source.registry,
20_000,
);
}
test('catalog projection excludes Prompt template content', () => {
const current = publication();
const result = createPluginPackagePromptCatalogResult(
current.target.projectId,
current.target.packageName,
current,
);
assert.equal(result.schema, PLUGIN_PACKAGE_PROMPT_CATALOG_SCHEMA);
assert.deepEqual(result.prompts, [
{
id: 'summary',
name: 'Summary',
description: 'Summarizes input',
parameters: [
{
name: 'subject',
description: 'Text to summarize',
required: true,
},
],
},
]);
assert.equal(JSON.stringify(result).includes('Private template'), false);
});
test('PostgreSQL catalog reads one current publication and returns empty for absence', async () => {
const current = publication();
const queries = [];
const service = new PostgresPluginPackagePromptCatalogService({
async query(sql, parameters) {
queries.push({ sql, parameters });
return { rows: [{ publicationJson: current }] };
},
});
const result = await service.inspect(
current.target.projectId,
current.target.packageName,
);
assert.equal(result.found, true);
assert.equal(queries.length, 1);
assert.match(queries[0].sql, /LIMIT 2/);
const absent = new PostgresPluginPackagePromptCatalogService({
async query() {
return { rows: [] };
},
});
assert.deepEqual(
await absent.inspect(current.target.projectId, current.target.packageName),
{
schema: PLUGIN_PACKAGE_PROMPT_CATALOG_SCHEMA,
projectId: current.target.projectId,
packageName: current.target.packageName,
found: false,
publicationState: null,
prompts: [],
},
);
});
@@ -0,0 +1,124 @@
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const { test } = require('node:test');
const {
CRASH_POINTS,
setupScenario,
verifyScenario,
} = require('./fixtures/pluginPackagePromptCrashFixture.cjs');
const FIXTURE_PATH = path.join(
__dirname,
'fixtures',
'pluginPackagePromptCrashFixture.cjs',
);
test(
'survives the SQLite Package Prompt admission and finalization crash matrix',
{ timeout: 180_000 },
async (context) => {
const reports = [];
for (const profile of ['edge', 'standalone']) {
for (const [pointName, point] of Object.entries(CRASH_POINTS)) {
const directory = fs.mkdtempSync(
path.join(os.tmpdir(), `ql3-package-prompt-${profile}-`),
);
context.after(() => {
fs.rmSync(directory, { recursive: true, force: true });
});
const databasePath = path.join(directory, 'runtime.sqlite');
const statePath = path.join(directory, 'state.json');
const markerPath = path.join(directory, 'crash-marker.json');
await setupScenario({
databasePath,
statePath,
profile,
operation: point.operation,
});
const crashed = spawnSync(
process.execPath,
[
FIXTURE_PATH,
'crash',
databasePath,
statePath,
markerPath,
pointName,
],
{
encoding: 'utf8',
timeout: 30_000,
},
);
assert.equal(
crashed.error,
undefined,
`${profile}/${pointName}: ${crashed.error?.message}`,
);
assert.equal(
crashed.signal,
'SIGKILL',
`${profile}/${pointName}: status=${crashed.status}, stderr=${crashed.stderr}`,
);
const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
assert.deepEqual(marker, {
schema: 'qinglong/sqlite-plugin-package-prompt-crash-marker@v1',
point: pointName,
pid: marker.pid,
});
reports.push(
await verifyScenario({ databasePath, statePath, pointName }),
);
}
}
assert.equal(reports.length, 20);
assert.equal(
reports.filter((report) => report.operation === 'admission').length,
10,
);
assert.equal(
reports.filter((report) => report.operation === 'finalization').length,
10,
);
assert.equal(
reports.filter((report) => report.crashBeforeCommit).length,
16,
);
assert.equal(
reports.filter((report) => report.durableAfterCrash).length,
4,
);
assert.deepEqual(
[...new Set(reports.map((report) => report.journalMode))].sort(),
['delete', 'wal'],
);
assert.ok(reports.every((report) => report.integrityCheck === 'ok'));
assert.ok(reports.every((report) => report.foreignKeyCheck === 'ok'));
assert.ok(reports.every((report) => report.exactReplay));
assert.ok(reports.every((report) => report.contentFree));
assert.ok(reports.every((report) => !report.physicalPowerLossProven));
context.diagnostic(
`QL3_RESOURCE_EVIDENCE=${JSON.stringify({
schemaVersion: 1,
workload: 'plugin_package_prompt_outer_transaction_crash_matrix',
profiles: ['edge', 'standalone'],
operations: ['admission', 'finalization'],
crashPointsPerProfile: 10,
scenarios: reports.length,
crashBeforeCommit: 16,
durableAfterCrash: 4,
exactReplay: true,
contentFree: true,
integrityCheck: 'ok',
foreignKeyCheck: 'ok',
promptAdmissionFinalizationCrashProven: true,
physicalPowerLossProven: false,
})}`,
);
},
);
@@ -0,0 +1,223 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
InvalidPluginPackagePromptExecutionPlanError,
PLUGIN_PACKAGE_PROMPT_EXECUTION_PLAN_SCHEMA,
createPluginPackagePromptAdmissionBundle,
normalizePluginPackagePromptExecutionPlan,
pluginPackagePromptExecutionPlanDigest,
preparePluginPackagePromptExecution,
} = require('../dist/prompt/pluginPackagePromptExecution.js');
const {
pluginPackageAutomationPublicationDigest,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
function publication(overrides = {}) {
const unsigned = {
schema: 'qinglong/plugin-package-automation-publication@v1',
target: {
projectId: 'project-a',
packageName: 'package-a',
installationId: 'installation-a',
lockDigest: '1'.repeat(64),
generation: 3,
generationDigest: '2'.repeat(64),
materializedRevisionDigest: '3'.repeat(64),
},
state: 'active',
version: 1,
previousPublicationDigest: null,
lifecycleEventDigest: null,
definitions: {
workflows: [],
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}} for {{audience}}.',
parameters: [
{ name: 'audience', required: false },
{ name: 'subject', required: true },
],
},
],
},
publishedAtMs: 1_000,
...overrides,
};
return {
...unsigned,
publicationDigest: pluginPackageAutomationPublicationDigest(unsigned),
};
}
function prepare(overrides = {}) {
const active = publication();
return preparePluginPackagePromptExecution({
publication: active,
expectedPublicationDigest: active.publicationDigest,
promptId: 'summary',
requestId: 'prompt-request-a',
traceId: 'trace-a',
requestedBySubject: { type: 'user', id: 'user-a' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'QingLong 3.0' },
provider: 'openai-compatible',
model: 'model-a',
maxOutputTokens: 512,
temperature: 0.2,
plannedAtMs: 2_000,
deadlineAtMs: 62_000,
...overrides,
});
}
test('prepares a content-free immutable Prompt execution plan', () => {
const first = prepare();
const second = prepare();
assert.deepEqual(first, second);
assert.equal(first.plan.schema, PLUGIN_PACKAGE_PROMPT_EXECUTION_PLAN_SCHEMA);
assert.deepEqual(first.plan.output, { mode: 'live_only' });
assert.equal(
first.request.messages[0].content,
'Summarize QingLong 3.0 for .',
);
assert.match(first.plan.invocationId, /^ppi:[0-9a-f]{32}$/);
assert.match(first.plan.runId, /^ppr:[0-9a-f]{32}$/);
assert.match(first.plan.stepRunId, /^pps:[0-9a-f]{32}$/);
assert.match(first.plan.modelRequestDigest, /^sha256:[0-9a-f]{64}$/);
const durable = JSON.stringify(first.plan);
assert.equal(durable.includes('QingLong 3.0'), false);
assert.equal(durable.includes('Summarize '), false);
assert.equal(Object.isFrozen(first.plan), true);
});
test('binds explicit durable output retention and preserves legacy live-only replay', () => {
const durable = prepare({
output: {
mode: 'durable_artifact',
retentionPolicy: {
revision: 'edge-output-v1',
retentionMs: 86_400_000,
},
},
}).plan;
assert.equal(durable.output.mode, 'durable_artifact');
assert.match(durable.output.retentionPolicyDigest, /^[0-9a-f]{64}$/);
assert.notEqual(durable.planDigest, prepare().plan.planDigest);
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...durable,
output: {
...durable.output,
retentionPolicyDigest: 'f'.repeat(64),
},
}),
InvalidPluginPackagePromptExecutionPlanError,
);
const current = prepare().plan;
const {
output: _output,
planDigest: _planDigest,
...legacyUnsigned
} = current;
const legacy = {
...legacyUnsigned,
planDigest: pluginPackagePromptExecutionPlanDigest(legacyUnsigned),
};
assert.equal(
normalizePluginPackagePromptExecutionPlan(legacy).output,
undefined,
);
});
test('binds parameter presence and content without recursively rendering values', () => {
const omitted = prepare();
const empty = prepare({
parameters: { subject: 'QingLong 3.0', audience: '' },
});
const literal = prepare({
parameters: { subject: '{{audience}}', audience: 'operators' },
});
assert.notEqual(omitted.plan.parameterDigest, empty.plan.parameterDigest);
assert.equal(
literal.request.messages[0].content,
'Summarize {{audience}} for operators.',
);
});
test('rejects stale publication, missing or widened parameters and unsafe budgets', () => {
const active = publication();
assert.throws(
() =>
preparePluginPackagePromptExecution({
...prepare().plan,
publication: active,
expectedPublicationDigest: 'f'.repeat(64),
promptId: 'summary',
requestId: 'request-b',
traceId: 'trace-b',
requestedBySubject: { type: 'user', id: 'user-b' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'x' },
provider: 'provider-a',
model: 'model-a',
maxOutputTokens: 1,
plannedAtMs: 2_000,
deadlineAtMs: 3_000,
}),
InvalidPluginPackagePromptExecutionPlanError,
);
assert.throws(() => prepare({ parameters: {} }), /subject is required/);
assert.throws(
() => prepare({ parameters: { subject: 'x', extra: 'y' } }),
/undeclared name/,
);
assert.throws(
() => prepare({ deadlineAtMs: 2_000 + 5 * 60_000 + 1 }),
/deadline/,
);
assert.throws(() => prepare({ maxOutputTokens: 32_769 }), /maxOutputTokens/);
});
test('creates one model StepRun admission without persisting Prompt content', () => {
const prepared = prepare();
const bundle = createPluginPackagePromptAdmissionBundle(prepared.plan);
assert.equal(bundle.run.status, 'running');
assert.equal(bundle.run.version, 2);
assert.equal(bundle.run.eventSequence, 2);
assert.equal(bundle.run.triggerType, 'plugin_package_prompt');
assert.equal(bundle.stepMutation.stepRun.kind, 'model');
assert.equal(bundle.stepMutation.stepRun.status, 'ready');
assert.equal(bundle.stepMutation.expectedRunVersion, 1);
assert.equal(bundle.stepMutation.event.sequence, 2);
assert.equal(bundle.receipt.finalRunVersion, 2);
assert.equal(bundle.receipt.invocationId, prepared.plan.invocationId);
const durable = JSON.stringify(bundle);
assert.equal(durable.includes('QingLong 3.0'), false);
assert.equal(durable.includes('Summarize '), false);
});
test('normalizer rejects identity and digest drift', () => {
const plan = prepare().plan;
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...plan,
runId: 'ppr:drift',
}),
InvalidPluginPackagePromptExecutionPlanError,
);
assert.throws(
() =>
normalizePluginPackagePromptExecutionPlan({
...plan,
parameterDigest: 'f'.repeat(64),
}),
InvalidPluginPackagePromptExecutionPlanError,
);
});
@@ -0,0 +1,251 @@
const assert = require('node:assert/strict');
const { DatabaseSync } = require('node:sqlite');
const { test } = require('node:test');
const {
PLUGIN_PACKAGE_PROMPT_EXECUTION_INSPECTION_SCHEMA,
normalizeAuthorizedPluginPackagePromptExecutionInspection,
normalizePluginPackagePromptExecutionInspectionResult,
} = require('../dist/prompt/pluginPackagePromptExecutionInspection.js');
const {
LocalPluginPackagePromptExecutionInspectionRepository,
} = require('../dist/prompt/localPluginPackagePromptExecutionInspectionRepository.js');
const {
PostgresPluginPackagePromptExecutionInspectionRepository,
} = require('../dist/prompt/postgresPluginPackagePromptExecutionInspectionRepository.js');
function authorized(eventId = '00000000-0000-4000-8000-000000000001') {
return {
projectId: 'project-1',
packageName: 'example',
promptId: 'summary',
executionRequestId: 'execution-request-1',
actor: { type: 'user', id: 'owner-1' },
fence: { projectVersion: 3, bindingVersion: 7 },
audit: {
eventId,
requestId: 'inspection-request-1',
operationId: 'prompt.execution.read',
projectId: 'project-1',
subject: { type: 'user', id: 'owner-1' },
authenticationId: 'api_credential:credential-1:1',
outcome: 'allowed',
reasons: ['project_policy_allowed'],
fence: { projectVersion: 3, bindingVersion: 7 },
occurredAtMs: 2_000,
},
};
}
function terminalResult() {
return {
schema: PLUGIN_PACKAGE_PROMPT_EXECUTION_INSPECTION_SCHEMA,
found: true,
projectId: 'project-1',
packageName: 'example',
promptId: 'summary',
executionRequestId: 'execution-request-1',
execution: {
invocationId: 'invocation-1',
runId: '00000000-0000-4000-8000-000000000010',
stepRunId: 'step-1',
runStatus: 'succeeded',
runVersion: 5,
eventSequence: 5,
stepStatus: 'succeeded',
stepVersion: 3,
admittedAtMs: 1_000,
startedAtMs: 1_000,
finishedAtMs: 1_500,
finalizedAtMs: 1_500,
},
};
}
test('normalizes an exact content-free execution inspection contract', () => {
const command = normalizeAuthorizedPluginPackagePromptExecutionInspection(
authorized(),
);
const result = normalizePluginPackagePromptExecutionInspectionResult(
terminalResult(),
);
assert.equal(command.executionRequestId, 'execution-request-1');
assert.equal(result.execution.runStatus, 'succeeded');
assert.equal(JSON.stringify(result).includes('template'), false);
assert.throws(() =>
normalizePluginPackagePromptExecutionInspectionResult({
...terminalResult(),
execution: { ...terminalResult().execution, privateOutput: 'secret' },
}),
);
});
test('SQLite inspection commits authorization, exact read and audit replay atomically', async (t) => {
const database = new DatabaseSync(':memory:');
t.after(() => database.close());
database.exec(`
CREATE TABLE "QingLong3SecurityAuditEvents" (event_id TEXT PRIMARY KEY);
CREATE TABLE "ModelInvocationPromptAdmissions" (
request_id TEXT PRIMARY KEY, invocation_id TEXT, run_id TEXT,
step_run_id TEXT, project_id TEXT, package_name TEXT, prompt_id TEXT,
admitted_at_ms INTEGER
);
CREATE TABLE "Runs" (
id TEXT PRIMARY KEY, project_id TEXT, status TEXT, version INTEGER,
event_sequence INTEGER, started_at_ms INTEGER, finished_at_ms INTEGER
);
CREATE TABLE "StepRuns" (
id TEXT, run_id TEXT, status TEXT, version INTEGER,
PRIMARY KEY (run_id, id)
);
CREATE TABLE "ModelInvocationPromptFinalizations" (
request_id TEXT PRIMARY KEY, finalized_at_ms INTEGER
);
`);
database
.prepare(
`INSERT INTO "ModelInvocationPromptAdmissions" VALUES
(?, ?, ?, ?, ?, ?, ?, ?)`,
)
.run(
'execution-request-1',
'invocation-1',
'00000000-0000-4000-8000-000000000010',
'step-1',
'project-1',
'example',
'summary',
1_000,
);
database
.prepare(`INSERT INTO "Runs" VALUES (?, ?, ?, ?, ?, ?, ?)`)
.run(
'00000000-0000-4000-8000-000000000010',
'project-1',
'succeeded',
5,
5,
1_000,
1_500,
);
database
.prepare(`INSERT INTO "StepRuns" VALUES (?, ?, ?, ?)`)
.run('step-1', '00000000-0000-4000-8000-000000000010', 'succeeded', 3);
database
.prepare(`INSERT INTO "ModelInvocationPromptFinalizations" VALUES (?, ?)`)
.run('execution-request-1', 1_500);
const replays = [];
const repository = new LocalPluginPackagePromptExecutionInspectionRepository(
{
client: database,
async enqueue(work) {
return work();
},
},
{
confirm(inspection, replay) {
assert.equal(database.isTransaction, true);
replays.push(replay);
if (!replay) {
database
.prepare(`INSERT INTO "QingLong3SecurityAuditEvents" VALUES (?)`)
.run(inspection.audit.eventId);
}
},
},
);
assert.deepEqual(
await repository.inspectAuthorized(authorized()),
terminalResult(),
);
assert.deepEqual(
await repository.inspectAuthorized(authorized()),
terminalResult(),
);
assert.deepEqual(replays, [false, true]);
});
test('PostgreSQL inspection uses one serializable authorization snapshot', async () => {
const queries = [];
let released = 0;
const client = {
async query(sql, parameters = []) {
queries.push({ sql, parameters });
if (sql.includes('FROM "ql3"."api_credentials"')) {
return {
rows: [
{
version: 1,
state: 'active',
subjectType: 'user',
subjectId: 'owner-1',
notBeforeAtMs: 0,
expiresAtMs: 10_000,
subjectStatus: 'active',
nowMs: 2_000,
},
],
};
}
if (sql.includes('FROM "ql3"."projects"')) {
return { rows: [{ status: 'active', version: 3 }] };
}
if (sql.includes('FROM "ql3"."project_role_bindings"')) {
return { rows: [{ state: 'active', version: 7 }] };
}
if (sql.includes('model_invocation_prompt_admissions" AS admission')) {
return {
rows: [
{
invocationId: 'invocation-1',
runId: '00000000-0000-4000-8000-000000000010',
stepRunId: 'step-1',
admittedAtMs: '1000',
runStatus: 'succeeded',
runVersion: 5,
eventSequence: 5,
startedAtMs: 1000,
finishedAtMs: 1500,
stepStatus: 'succeeded',
stepVersion: 3,
finalizedAtMs: 1500,
},
],
};
}
return { rows: [] };
},
release() {
released += 1;
},
};
const repository =
new PostgresPluginPackagePromptExecutionInspectionRepository({
async query() {
return { rows: [] };
},
async connect() {
return client;
},
});
assert.deepEqual(
await repository.inspectAuthorized(authorized()),
terminalResult(),
);
assert.equal(released, 1);
assert.match(queries[0].sql, /BEGIN ISOLATION LEVEL SERIALIZABLE READ WRITE/);
const target = queries.find(({ sql }) =>
sql.includes('model_invocation_prompt_admissions" AS admission'),
);
assert.deepEqual(target.parameters, [
'execution-request-1',
'project-1',
'example',
'summary',
]);
assert.match(target.sql, /LIMIT 2/);
assert.equal(
queries.some(({ sql }) => sql.includes('security_audit_events')),
true,
);
});
@@ -0,0 +1,291 @@
const assert = require('node:assert/strict');
const { DatabaseSync } = require('node:sqlite');
const { test } = require('node:test');
const {
InvalidPluginPackagePromptExecutionOutputReadError,
PLUGIN_PACKAGE_PROMPT_EXECUTION_OUTPUT_READ_RESULT_SCHEMA,
PluginPackagePromptExecutionOutputReadService,
PluginPackagePromptExecutionOutputReadUnavailableError,
} = require('../dist/prompt-output/pluginPackagePromptExecutionOutputRead.js');
const {
LocalPluginPackagePromptExecutionOutputReferenceRepository,
} = require('../dist/prompt-output/storage/localPluginPackagePromptExecutionOutputReferenceRepository.js');
const {
PostgresPluginPackagePromptExecutionOutputReferenceRepository,
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptExecutionOutputReferenceRepository.js');
const {
pluginPackagePromptOutputArtifactIdentity,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const PRINCIPAL = Object.freeze({
subject: Object.freeze({ type: 'user', id: 'owner-1' }),
authenticationId: 'authentication-1',
authenticatedAtMs: 1_000,
expiresAtMs: 10_000,
assurance: 'multi_factor',
});
const TARGET = Object.freeze({
projectId: 'project-1',
packageName: 'example',
promptId: 'summary',
executionRequestId: 'execution-request-1',
});
const REFERENCE = Object.freeze({
runId: '00000000-0000-4000-8000-000000000010',
artifactId: pluginPackagePromptOutputArtifactIdentity('invocation-1'),
artifactDigest: 'a'.repeat(64),
});
const OUTPUT_REFERENCE = Object.freeze({
schema: 'qinglong/plugin-package-prompt-output-artifact-reference@v1',
artifactId: REFERENCE.artifactId,
projectId: TARGET.projectId,
runId: REFERENCE.runId,
stepRunId: 'step-1',
invocationId: 'invocation-1',
contentDigest: 'b'.repeat(64),
outputBytes: 14,
retentionPolicyDigest: 'c'.repeat(64),
retentionEligibleAtMs: 20_000,
keyId: 'key-1',
algorithm: 'aes-256-gcm',
artifactDigest: REFERENCE.artifactDigest,
});
const RESULT = Object.freeze({
provider: 'provider-1',
model: 'model-1',
text: 'private output',
finishReason: 'stop',
usage: Object.freeze({ inputTokens: 2, outputTokens: 3, totalTokens: 5 }),
});
test('resolves one execution request before delegating protected output read', async () => {
const calls = [];
const service = new PluginPackagePromptExecutionOutputReadService({
references: {
async find(target) {
calls.push({ kind: 'reference', target });
return REFERENCE;
},
},
outputs: {
async read(command) {
calls.push({ kind: 'output', command });
return {
schema: 'qinglong/plugin-package-prompt-output-read-result@v1',
status: 'available',
reference: OUTPUT_REFERENCE,
result: RESULT,
};
},
},
});
const value = await service.read({ principal: PRINCIPAL, ...TARGET });
assert.deepEqual(value, {
schema: PLUGIN_PACKAGE_PROMPT_EXECUTION_OUTPUT_READ_RESULT_SCHEMA,
status: 'available',
...TARGET,
reference: OUTPUT_REFERENCE,
result: RESULT,
});
assert.deepEqual(calls[0], { kind: 'reference', target: TARGET });
assert.deepEqual(calls[1], {
kind: 'output',
command: {
principal: PRINCIPAL,
projectId: TARGET.projectId,
...REFERENCE,
},
});
});
test('masks absent, live-only, tombstoned and cross-target output as not found', async () => {
let outputReads = 0;
const absent = new PluginPackagePromptExecutionOutputReadService({
references: {
async find() {
return null;
},
},
outputs: {
async read() {
outputReads += 1;
throw new Error('unreachable');
},
},
});
assert.deepEqual(await absent.read({ principal: PRINCIPAL, ...TARGET }), {
schema: PLUGIN_PACKAGE_PROMPT_EXECUTION_OUTPUT_READ_RESULT_SCHEMA,
status: 'not_found',
...TARGET,
});
assert.equal(outputReads, 0);
const unavailableOutput = new PluginPackagePromptExecutionOutputReadService({
references: {
async find() {
return REFERENCE;
},
},
outputs: {
async read() {
return {
schema: 'qinglong/plugin-package-prompt-output-read-result@v1',
status: 'not_found',
};
},
},
});
assert.equal(
(await unavailableOutput.read({ principal: PRINCIPAL, ...TARGET })).status,
'not_found',
);
await assert.rejects(
unavailableOutput.read({
principal: PRINCIPAL,
...TARGET,
packageName: '../invalid',
}),
InvalidPluginPackagePromptExecutionOutputReadError,
);
});
test('rejects widened output envelopes before returning content', async () => {
const widened = new PluginPackagePromptExecutionOutputReadService({
references: {
async find() {
return REFERENCE;
},
},
outputs: {
async read() {
return {
schema: 'qinglong/plugin-package-prompt-output-read-result@v1',
status: 'available',
reference: OUTPUT_REFERENCE,
result: { ...RESULT, privateTrace: 'must-not-escape' },
};
},
},
});
await assert.rejects(
widened.read({ principal: PRINCIPAL, ...TARGET }),
PluginPackagePromptExecutionOutputReadUnavailableError,
);
});
function sqliteRepository(database) {
return new LocalPluginPackagePromptExecutionOutputReferenceRepository({
client: database,
async enqueue(work) {
return work();
},
});
}
test('SQLite locator requires an exact terminal durable binding', async (t) => {
const database = new DatabaseSync(':memory:');
t.after(() => database.close());
database.exec(`
CREATE TABLE "ModelInvocationPromptAdmissions" (
request_id TEXT PRIMARY KEY, invocation_id TEXT, run_id TEXT,
step_run_id TEXT, project_id TEXT, package_name TEXT, prompt_id TEXT
);
CREATE TABLE "ModelInvocationPromptFinalizations" (
request_id TEXT PRIMARY KEY, run_status TEXT
);
CREATE TABLE "ModelInvocationCompletions" (
invocation_id TEXT PRIMARY KEY, outcome TEXT
);
CREATE TABLE "Runs" (
id TEXT PRIMARY KEY, project_id TEXT, status TEXT
);
CREATE TABLE "StepRuns" (
id TEXT, run_id TEXT, status TEXT, output_ref TEXT,
PRIMARY KEY (run_id, id)
);
CREATE TABLE "ModelInvocationPromptOutputArtifacts" (
artifact_id TEXT PRIMARY KEY, project_id TEXT, run_id TEXT,
step_run_id TEXT, invocation_id TEXT, artifact_digest TEXT
);
`);
database
.prepare(
`INSERT INTO "ModelInvocationPromptAdmissions" VALUES
(?, ?, ?, ?, ?, ?, ?)`,
)
.run(
TARGET.executionRequestId,
'invocation-1',
REFERENCE.runId,
'step-1',
TARGET.projectId,
TARGET.packageName,
TARGET.promptId,
);
database
.prepare(`INSERT INTO "ModelInvocationPromptFinalizations" VALUES (?, ?)`)
.run(TARGET.executionRequestId, 'succeeded');
database
.prepare(`INSERT INTO "ModelInvocationCompletions" VALUES (?, ?)`)
.run('invocation-1', 'succeeded');
database
.prepare(`INSERT INTO "Runs" VALUES (?, ?, ?)`)
.run(REFERENCE.runId, TARGET.projectId, 'succeeded');
database
.prepare(`INSERT INTO "StepRuns" VALUES (?, ?, ?, ?)`)
.run('step-1', REFERENCE.runId, 'succeeded', REFERENCE.artifactId);
database
.prepare(
`INSERT INTO "ModelInvocationPromptOutputArtifacts" VALUES
(?, ?, ?, ?, ?, ?)`,
)
.run(
REFERENCE.artifactId,
TARGET.projectId,
REFERENCE.runId,
'step-1',
'invocation-1',
REFERENCE.artifactDigest,
);
const repository = sqliteRepository(database);
assert.deepEqual(await repository.find(TARGET), REFERENCE);
assert.equal(
await repository.find({ ...TARGET, promptId: 'another-prompt' }),
null,
);
database.prepare(`UPDATE "StepRuns" SET output_ref = NULL`).run();
assert.equal(await repository.find(TARGET), null);
});
test('PostgreSQL locator uses the existing request primary key and terminal joins', async () => {
const calls = [];
const repository =
new PostgresPluginPackagePromptExecutionOutputReferenceRepository({
async query(sql, parameters) {
calls.push({ sql, parameters });
return {
rows: [
{
runId: REFERENCE.runId,
artifactId: REFERENCE.artifactId,
artifactDigest: REFERENCE.artifactDigest,
},
],
};
},
});
assert.deepEqual(await repository.find(TARGET), REFERENCE);
assert.deepEqual(calls[0].parameters, [
TARGET.executionRequestId,
TARGET.projectId,
TARGET.packageName,
TARGET.promptId,
]);
assert.match(calls[0].sql, /admission\.request_id = \$1/);
assert.match(calls[0].sql, /step\.output_ref = artifact\.artifact_id/);
assert.match(calls[0].sql, /LIMIT 2/);
assert.equal(calls[0].sql.includes('artifact_json'), false);
assert.equal(calls[0].sql.includes('ciphertext'), false);
});
@@ -0,0 +1,153 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
InvalidPluginPackagePromptOutputArtifactError,
PluginPackagePromptOutputArtifactUnavailableError,
createPluginPackagePromptOutputArtifact,
normalizePluginPackagePromptOutputArtifact,
normalizePluginPackagePromptOutputArtifactReference,
openPluginPackagePromptOutputArtifact,
pluginPackagePromptOutputArtifactIdentity,
pluginPackagePromptOutputArtifactReference,
pluginPackagePromptOutputArtifactRetentionPolicyDigest,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const KEY = Buffer.alloc(32, 7);
const NONCE = Buffer.alloc(12, 9);
const RETENTION = Object.freeze({
revision: 'edge-default-v1',
retentionMs: 86_400_000,
});
const RESULT = Object.freeze({
provider: 'openai-compatible',
model: 'bounded-model',
text: 'private durable answer: ql3-artifact-secret',
finishReason: 'stop',
usage: Object.freeze({
inputTokens: 12,
outputTokens: 7,
totalTokens: 19,
costMicros: 42,
}),
});
function create(overrides = {}) {
return createPluginPackagePromptOutputArtifact(
{
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
invocationId: 'invocation-a',
requestedBy: { type: 'user', id: 'user-a' },
result: RESULT,
retentionPolicy: RETENTION,
keyId: 'prompt-key-1',
key: Buffer.from(KEY),
sealedAtMs: 1_700_000_000_000,
...overrides,
},
() => Buffer.from(NONCE),
);
}
test('Prompt output Artifact encrypts bounded result and opens exact content', () => {
const artifact = create();
const serialized = JSON.stringify(artifact);
assert.equal(
artifact.artifactId,
pluginPackagePromptOutputArtifactIdentity('invocation-a'),
);
assert.equal(
artifact.retentionPolicyDigest,
pluginPackagePromptOutputArtifactRetentionPolicyDigest(RETENTION),
);
assert.equal(artifact.retentionEligibleAtMs, 1_700_086_400_000);
assert.equal(artifact.outputBytes, Buffer.byteLength(RESULT.text, 'utf8'));
assert.equal(serialized.includes(RESULT.text), false);
assert.equal(serialized.includes('ql3-artifact-secret'), false);
assert.deepEqual(
openPluginPackagePromptOutputArtifact(artifact, Buffer.from(KEY)),
RESULT,
);
assert.deepEqual(
normalizePluginPackagePromptOutputArtifact(artifact),
artifact,
);
});
test('Prompt output Artifact reference is content-free and identity-bound', () => {
const artifact = create();
const reference = pluginPackagePromptOutputArtifactReference(artifact);
assert.deepEqual(
normalizePluginPackagePromptOutputArtifactReference(reference),
reference,
);
assert.equal(JSON.stringify(reference).includes(RESULT.text), false);
assert.equal(reference.artifactDigest, artifact.artifactDigest);
assert.equal(reference.contentDigest, artifact.contentDigest);
assert.equal(reference.keyId, artifact.keyId);
assert.equal(reference.retentionPolicyDigest, artifact.retentionPolicyDigest);
assert.throws(
() =>
normalizePluginPackagePromptOutputArtifactReference({
...reference,
invocationId: 'invocation-b',
}),
InvalidPluginPackagePromptOutputArtifactError,
);
});
test('Prompt output Artifact rejects metadata and ciphertext tampering', () => {
const artifact = create();
assert.throws(
() =>
normalizePluginPackagePromptOutputArtifact({
...artifact,
projectId: 'project-b',
}),
InvalidPluginPackagePromptOutputArtifactError,
);
const ciphertext = Buffer.from(artifact.ciphertext, 'base64url');
ciphertext[0] ^= 1;
const tampered = {
...artifact,
ciphertext: ciphertext.toString('base64url'),
};
assert.throws(
() => normalizePluginPackagePromptOutputArtifact(tampered),
InvalidPluginPackagePromptOutputArtifactError,
);
const wrongKeyArtifact = create();
assert.throws(
() =>
openPluginPackagePromptOutputArtifact(
wrongKeyArtifact,
Buffer.alloc(32, 8),
),
PluginPackagePromptOutputArtifactUnavailableError,
);
});
test('Prompt output Artifact rejects unsafe retention and key material', () => {
assert.throws(
() =>
create({
retentionPolicy: { revision: 'bad', retentionMs: 1 },
}),
InvalidPluginPackagePromptOutputArtifactError,
);
assert.throws(
() => create({ key: Buffer.alloc(31) }),
PluginPackagePromptOutputArtifactUnavailableError,
);
assert.throws(
() => create({ sealedAtMs: Number.MAX_SAFE_INTEGER }),
InvalidPluginPackagePromptOutputArtifactError,
);
});
@@ -0,0 +1,205 @@
const assert = require('node:assert/strict');
const { createHash, generateKeyPairSync, sign } = require('node:crypto');
const { test } = require('node:test');
const {
PluginPackagePromptOutputExternalCustodyUntrustedError,
createPluginPackagePromptOutputExternalCustodyReceipt,
normalizePluginPackagePromptOutputExternalCustodyReceipt,
verifyPluginPackagePromptOutputExternalCustodyReceipt,
verifyPluginPackagePromptOutputRecoveredMaterial,
verifyPluginPackagePromptOutputWrappedBackup,
} = require('../dist/prompt-output/custody/pluginPackagePromptOutputExternalCustody.js');
const {
createPluginPackagePromptOutputArtifact,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const {
pluginPackagePromptOutputKeyRotationMaterialProof,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRotation.js');
const MATERIAL = Buffer.alloc(32, 0x5a);
const WRAPPED = Buffer.from('kms-wrapped-prompt-output-key-material');
const CATALOG_DIGEST = '1'.repeat(64);
const WRAPPING_KEY_REF_DIGEST = '2'.repeat(64);
const { publicKey, privateKey } = generateKeyPairSync('ed25519');
function receipt(overrides = {}) {
return createPluginPackagePromptOutputExternalCustodyReceipt(
{
custodyId: 'custody-001',
keyId: 'prompt-key-001',
materialProof: pluginPackagePromptOutputKeyRotationMaterialProof(
'prompt-key-001',
MATERIAL,
),
sourceGeneration: 4,
sourceCatalogDigest: CATALOG_DIGEST,
wrappingProvider: 'vault-transit',
wrappingKeyRefDigest: WRAPPING_KEY_REF_DIGEST,
wrappedMaterialDigest: createHash('sha256').update(WRAPPED).digest('hex'),
wrappedMaterialBytes: WRAPPED.length,
createdAtMs: 1_700_000_000_000,
...overrides,
},
{
publicKey,
sign: (digest) => sign(null, digest, privateKey),
},
);
}
function artifact(overrides = {}) {
return createPluginPackagePromptOutputArtifact(
{
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
invocationId: 'invocation-a',
requestedBy: { type: 'user', id: 'user-a' },
result: {
provider: 'openai-compatible',
model: 'bounded-model',
text: 'private recovered answer',
finishReason: 'stop',
usage: {
inputTokens: 5,
outputTokens: 3,
totalTokens: 8,
costMicros: 11,
},
},
retentionPolicy: {
revision: 'retention-v1',
retentionMs: 86_400_000,
},
keyId: 'prompt-key-001',
key: Buffer.from(MATERIAL),
sealedAtMs: 1_700_000_000_000,
...overrides,
},
() => Buffer.alloc(12, 0x33),
);
}
test('binds a signed content-free custody receipt to exact wrapped bytes', () => {
const value = receipt();
assert.deepEqual(
normalizePluginPackagePromptOutputExternalCustodyReceipt(value),
value,
);
assert.deepEqual(
verifyPluginPackagePromptOutputExternalCustodyReceipt(value, publicKey),
value,
);
const verified = verifyPluginPackagePromptOutputWrappedBackup(
value,
publicKey,
WRAPPED,
);
assert.equal(verified.custodyId, 'custody-001');
assert.equal(verified.wrappedMaterialBytes, WRAPPED.length);
const serialized = JSON.stringify(value);
assert.equal(serialized.includes(MATERIAL.toString('base64url')), false);
assert.equal(serialized.includes(WRAPPED.toString('base64url')), false);
assert.equal(serialized.includes('kms-wrapped-prompt'), false);
});
test('verifies recovered material against durable fact and opens an Artifact', () => {
const custody = receipt();
const encrypted = artifact();
const proof = verifyPluginPackagePromptOutputRecoveredMaterial({
recoveryId: 'recovery-001',
requestId: 'request-001',
receipt: custody,
trustedPublicKey: publicKey,
durableKeyFact: {
keyId: custody.keyId,
materialProof: custody.materialProof,
catalogDigest: custody.sourceCatalogDigest,
},
material: MATERIAL,
artifact: encrypted,
verifiedAtMs: 1_700_000_001_000,
});
assert.equal(proof.artifactId, encrypted.artifactId);
assert.equal(proof.artifactDigest, encrypted.artifactDigest);
assert.equal(proof.contentDigest, encrypted.contentDigest);
assert.equal(proof.keyId, custody.keyId);
assert.equal(proof.proofDigest.length, 64);
const serialized = JSON.stringify(proof);
assert.equal(serialized.includes('private recovered answer'), false);
assert.equal(serialized.includes(MATERIAL.toString('base64url')), false);
});
test('rejects untrusted receipt, wrapped bytes, durable fact and material drift', () => {
const custody = receipt();
const otherKeys = generateKeyPairSync('ed25519');
assert.throws(
() =>
verifyPluginPackagePromptOutputExternalCustodyReceipt(
custody,
otherKeys.publicKey,
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
assert.throws(
() =>
verifyPluginPackagePromptOutputWrappedBackup(
custody,
publicKey,
Buffer.from('different wrapped material'),
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
for (const candidate of [
{
durableKeyFact: {
keyId: custody.keyId,
materialProof: '3'.repeat(64),
catalogDigest: custody.sourceCatalogDigest,
},
material: MATERIAL,
},
{
durableKeyFact: {
keyId: custody.keyId,
materialProof: custody.materialProof,
catalogDigest: custody.sourceCatalogDigest,
},
material: Buffer.alloc(32, 0x5b),
},
]) {
assert.throws(
() =>
verifyPluginPackagePromptOutputRecoveredMaterial({
recoveryId: 'recovery-001',
requestId: 'request-001',
receipt: custody,
trustedPublicKey: publicKey,
durableKeyFact: candidate.durableKeyFact,
material: candidate.material,
artifact: artifact(),
verifiedAtMs: 1_700_000_001_000,
}),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
}
});
test('rejects a custody receipt with a tampered signature', () => {
const custody = receipt();
const signature = Buffer.from(custody.signature, 'base64url');
signature[0] ^= 0x01;
assert.throws(
() =>
verifyPluginPackagePromptOutputExternalCustodyReceipt(
{
...custody,
signature: signature.toString('base64url'),
},
publicKey,
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
});
@@ -0,0 +1,110 @@
const assert = require('node:assert/strict');
const { createHash, generateKeyPairSync, sign } = require('node:crypto');
const { test } = require('node:test');
const {
PLUGIN_PACKAGE_PROMPT_OUTPUT_EXTERNAL_CUSTODY_BUNDLE_SCHEMA,
createPluginPackagePromptOutputExternalCustodyBundle,
openPluginPackagePromptOutputExternalCustodyBundle,
} = require('../dist/prompt-output/custody/pluginPackagePromptOutputExternalCustodyBundle.js');
const {
InvalidPluginPackagePromptOutputExternalCustodyError,
PluginPackagePromptOutputExternalCustodyUntrustedError,
createPluginPackagePromptOutputExternalCustodyReceipt,
} = require('../dist/prompt-output/custody/pluginPackagePromptOutputExternalCustody.js');
function fixture(byte = 0x51) {
const keys = generateKeyPairSync('ed25519');
const wrappedMaterial = Buffer.from(`external-provider-wrapped-${byte}`);
const receipt = createPluginPackagePromptOutputExternalCustodyReceipt(
{
custodyId: 'provider-neutral-custody-001',
keyId: 'prompt-output-key-001',
materialProof: '1'.repeat(64),
sourceGeneration: 3,
sourceCatalogDigest: '2'.repeat(64),
wrappingProvider: 'external-kms',
wrappingKeyRefDigest: '3'.repeat(64),
wrappedMaterialDigest: createHash('sha256')
.update(wrappedMaterial)
.digest('hex'),
wrappedMaterialBytes: wrappedMaterial.byteLength,
createdAtMs: 1_700_000_000_000,
},
{
publicKey: keys.publicKey,
sign: (message) => sign(null, message, keys.privateKey),
},
);
const bundle = createPluginPackagePromptOutputExternalCustodyBundle(
receipt,
keys.publicKey,
wrappedMaterial,
);
return { keys, wrappedMaterial, receipt, bundle };
}
test('creates and opens one provider-neutral atomic custody bundle', () => {
const value = fixture();
const opened = openPluginPackagePromptOutputExternalCustodyBundle(
value.bundle,
value.keys.publicKey,
);
try {
assert.equal(
value.bundle.schema,
PLUGIN_PACKAGE_PROMPT_OUTPUT_EXTERNAL_CUSTODY_BUNDLE_SCHEMA,
);
assert.equal(opened.bundleDigest, value.bundle.bundleDigest);
assert.equal(opened.receipt.receiptDigest, value.receipt.receiptDigest);
assert.deepEqual(opened.wrappedMaterial, value.wrappedMaterial);
} finally {
opened.wrappedMaterial.fill(0);
}
});
test('rejects split-file substitution even when the receipt remains valid', () => {
const left = fixture(0x51);
const right = fixture(0x52);
assert.throws(
() =>
openPluginPackagePromptOutputExternalCustodyBundle(
{ ...left.bundle, wrappedMaterial: right.bundle.wrappedMaterial },
left.keys.publicKey,
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
});
test('rejects bundle digest drift and extra fields', () => {
const value = fixture();
assert.throws(
() =>
openPluginPackagePromptOutputExternalCustodyBundle(
{ ...value.bundle, bundleDigest: '4'.repeat(64) },
value.keys.publicKey,
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
assert.throws(
() =>
openPluginPackagePromptOutputExternalCustodyBundle(
{ ...value.bundle, providerConfig: 'must-not-be-embedded' },
value.keys.publicKey,
),
InvalidPluginPackagePromptOutputExternalCustodyError,
);
});
test('rejects a valid bundle under a different custody signing authority', () => {
const value = fixture();
const other = generateKeyPairSync('ed25519');
assert.throws(
() =>
openPluginPackagePromptOutputExternalCustodyBundle(
value.bundle,
other.publicKey,
),
PluginPackagePromptOutputExternalCustodyUntrustedError,
);
});
@@ -0,0 +1,302 @@
const assert = require('node:assert/strict');
const { createHash, generateKeyPairSync, sign } = require('node:crypto');
const { test } = require('node:test');
const {
PluginPackagePromptOutputRecoveryAuthorizationUntrustedError,
createPluginPackagePromptOutputExternalRecoveryAuthorization,
normalizePluginPackagePromptOutputExternalRecoveryAuthorization,
verifyAuthorizedPluginPackagePromptOutputRecoveredMaterial,
verifyPluginPackagePromptOutputExternalRecoveryAuthorization,
} = require('../dist/prompt-output/custody/pluginPackagePromptOutputExternalRecoveryAuthorization.js');
const {
createPluginPackagePromptOutputExternalCustodyReceipt,
} = require('../dist/prompt-output/custody/pluginPackagePromptOutputExternalCustody.js');
const {
createPluginPackagePromptOutputArtifact,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const {
pluginPackagePromptOutputKeyRotationMaterialProof,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRotation.js');
const NOW = 1_700_000_000_000;
const MATERIAL = Buffer.alloc(32, 0x4a);
const WRAPPED = Buffer.from('external-kms-wrapped-material');
const CATALOG_DIGEST = '1'.repeat(64);
const POLICY_DIGEST = '2'.repeat(64);
const WRAPPING_KEY_REF_DIGEST = '3'.repeat(64);
const custodyKeys = generateKeyPairSync('ed25519');
const approverAKeys = generateKeyPairSync('ed25519');
const approverBKeys = generateKeyPairSync('ed25519');
function artifact() {
return createPluginPackagePromptOutputArtifact(
{
projectId: 'project-recovery',
runId: 'run-recovery',
stepRunId: 'step-recovery',
invocationId: 'invocation-recovery',
requestedBy: { type: 'user', id: 'requester-user' },
result: {
provider: 'openai-compatible',
model: 'bounded-model',
text: 'historical private answer',
finishReason: 'stop',
usage: {
inputTokens: 5,
outputTokens: 4,
totalTokens: 9,
costMicros: 12,
},
},
retentionPolicy: {
revision: 'recovery-retention-v1',
retentionMs: 86_400_000,
},
keyId: 'prompt-key-recovery',
key: Buffer.from(MATERIAL),
sealedAtMs: NOW - 60_000,
},
() => Buffer.alloc(12, 0x31),
);
}
function receipt() {
return createPluginPackagePromptOutputExternalCustodyReceipt(
{
custodyId: 'custody-recovery',
keyId: 'prompt-key-recovery',
materialProof: pluginPackagePromptOutputKeyRotationMaterialProof(
'prompt-key-recovery',
MATERIAL,
),
sourceGeneration: 7,
sourceCatalogDigest: CATALOG_DIGEST,
wrappingProvider: 'external-kms',
wrappingKeyRefDigest: WRAPPING_KEY_REF_DIGEST,
wrappedMaterialDigest: createHash('sha256').update(WRAPPED).digest('hex'),
wrappedMaterialBytes: WRAPPED.length,
createdAtMs: NOW - 120_000,
},
{
publicKey: custodyKeys.publicKey,
sign: (message) => sign(null, message, custodyKeys.privateKey),
},
);
}
function signer(userId, authenticationId, keys, approvedAtMs) {
return {
userId,
authenticationId,
authenticatedAtMs: approvedAtMs - 1_000,
approvedAtMs,
publicKey: keys.publicKey,
sign: (message) => sign(null, message, keys.privateKey),
};
}
function authorization(encrypted, custody, overrides = {}) {
return createPluginPackagePromptOutputExternalRecoveryAuthorization(
{
recoveryId: 'recovery-001',
requestId: 'request-001',
custodyId: custody.custodyId,
custodyReceiptDigest: custody.receiptDigest,
keyId: custody.keyId,
artifactId: encrypted.artifactId,
artifactDigest: encrypted.artifactDigest,
policyDigest: POLICY_DIGEST,
requestedBy: {
userId: 'requester-user',
authenticationId: 'requester-auth-001',
authenticatedAtMs: NOW - 5_000,
},
requestedAtMs: NOW,
expiresAtMs: NOW + 10 * 60_000,
...overrides,
},
[
signer('reviewer-b', 'reviewer-b-auth', approverBKeys, NOW + 2_000),
signer('reviewer-a', 'reviewer-a-auth', approverAKeys, NOW + 1_000),
],
);
}
function trustedApprovers() {
return [
{ userId: 'reviewer-a', publicKey: approverAKeys.publicKey },
{ userId: 'reviewer-b', publicKey: approverBKeys.publicKey },
];
}
test('binds two distinct strong approvers to one exact recovery request', () => {
const encrypted = artifact();
const custody = receipt();
const value = authorization(encrypted, custody);
assert.deepEqual(
normalizePluginPackagePromptOutputExternalRecoveryAuthorization(value),
value,
);
assert.deepEqual(
verifyPluginPackagePromptOutputExternalRecoveryAuthorization(
value,
trustedApprovers(),
NOW + 3_000,
),
value,
);
assert.deepEqual(
value.approvals.map(({ userId }) => userId),
['reviewer-a', 'reviewer-b'],
);
assert.equal(value.permission, 'artifact.read');
assert.equal(value.purpose, 'lost-key-recovery-verification');
});
test('returns only an authorization-bound content-free recovery proof', () => {
const encrypted = artifact();
const custody = receipt();
const proof = verifyAuthorizedPluginPackagePromptOutputRecoveredMaterial({
authorization: authorization(encrypted, custody),
trustedApprovers: trustedApprovers(),
receipt: custody,
trustedCustodyPublicKey: custodyKeys.publicKey,
wrappedMaterial: WRAPPED,
durableKeyFact: {
keyId: custody.keyId,
materialProof: custody.materialProof,
catalogDigest: custody.sourceCatalogDigest,
},
material: MATERIAL,
artifact: encrypted,
verifiedAtMs: NOW + 3_000,
});
assert.equal(proof.artifactId, encrypted.artifactId);
assert.equal(proof.authorizationDigest.length, 64);
assert.equal(proof.recoveryProofDigest.length, 64);
assert.equal(proof.proofDigest.length, 64);
const serialized = JSON.stringify(proof);
assert.equal(serialized.includes('historical private answer'), false);
assert.equal(serialized.includes(MATERIAL.toString('base64url')), false);
assert.equal(serialized.includes(WRAPPED.toString('base64url')), false);
});
test('rejects requester self-approval, duplicate identity and stale authentication', () => {
const encrypted = artifact();
const custody = receipt();
for (const signers of [
[
signer(
'requester-user',
'requester-review-auth',
approverAKeys,
NOW + 1_000,
),
signer('reviewer-b', 'reviewer-b-auth', approverBKeys, NOW + 2_000),
],
[
signer('reviewer-a', 'same-auth', approverAKeys, NOW + 1_000),
signer('reviewer-b', 'same-auth', approverBKeys, NOW + 2_000),
],
[
{
...signer('reviewer-a', 'reviewer-a-auth', approverAKeys, NOW + 1_000),
authenticatedAtMs: NOW - 10 * 60_000,
},
signer('reviewer-b', 'reviewer-b-auth', approverBKeys, NOW + 2_000),
],
]) {
assert.throws(() =>
createPluginPackagePromptOutputExternalRecoveryAuthorization(
{
recoveryId: 'recovery-001',
requestId: 'request-001',
custodyId: custody.custodyId,
custodyReceiptDigest: custody.receiptDigest,
keyId: custody.keyId,
artifactId: encrypted.artifactId,
artifactDigest: encrypted.artifactDigest,
policyDigest: POLICY_DIGEST,
requestedBy: {
userId: 'requester-user',
authenticationId: 'requester-auth-001',
authenticatedAtMs: NOW - 5_000,
},
requestedAtMs: NOW,
expiresAtMs: NOW + 10 * 60_000,
},
signers,
),
);
}
});
test('rejects signature, trusted approver, expiry and exact fact drift', () => {
const encrypted = artifact();
const custody = receipt();
const approved = authorization(encrypted, custody);
const signature = Buffer.from(approved.approvals[0].signature, 'base64url');
signature[0] ^= 1;
assert.throws(
() =>
verifyPluginPackagePromptOutputExternalRecoveryAuthorization(
{
...approved,
approvals: [
{
...approved.approvals[0],
signature: signature.toString('base64url'),
},
approved.approvals[1],
],
},
trustedApprovers(),
NOW + 3_000,
),
PluginPackagePromptOutputRecoveryAuthorizationUntrustedError,
);
assert.throws(
() =>
verifyPluginPackagePromptOutputExternalRecoveryAuthorization(
approved,
[
trustedApprovers()[0],
{
userId: 'reviewer-b',
publicKey: generateKeyPairSync('ed25519').publicKey,
},
],
NOW + 3_000,
),
PluginPackagePromptOutputRecoveryAuthorizationUntrustedError,
);
assert.throws(
() =>
verifyPluginPackagePromptOutputExternalRecoveryAuthorization(
approved,
trustedApprovers(),
NOW + 11 * 60_000,
),
PluginPackagePromptOutputRecoveryAuthorizationUntrustedError,
);
assert.throws(
() =>
verifyAuthorizedPluginPackagePromptOutputRecoveredMaterial({
authorization: approved,
trustedApprovers: trustedApprovers(),
receipt: custody,
trustedCustodyPublicKey: custodyKeys.publicKey,
wrappedMaterial: WRAPPED,
durableKeyFact: {
keyId: custody.keyId,
materialProof: custody.materialProof,
catalogDigest: custody.sourceCatalogDigest,
},
material: MATERIAL,
artifact: { ...encrypted, artifactDigest: '4'.repeat(64) },
verifiedAtMs: NOW + 3_000,
}),
PluginPackagePromptOutputRecoveryAuthorizationUntrustedError,
);
});
@@ -0,0 +1,125 @@
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const test = require('node:test');
const {
PluginPackagePromptOutputFileKeyring,
provisionPluginPackagePromptOutputFileKeyring,
rotatePluginPackagePromptOutputFileKeyring,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputFileKeyring.js');
const {
PluginPackagePromptOutputKeyRetirementConflictError,
PluginPackagePromptOutputKeyRetirementUnavailableError,
createPluginPackagePromptOutputKeyRetirementPreparation,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRetirement.js');
function fixture(t) {
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-output-keys-'));
fs.chmodSync(directory, 0o700);
const filePath = path.join(directory, 'prompt-output-keyring.json');
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
return { directory, filePath };
}
function preparation(material, overrides = {}) {
return createPluginPackagePromptOutputKeyRetirementPreparation({
keyId: material.keyId,
retirementId: 'retirement-a',
requestId: 'request-a',
mutationId: 'mutation-a',
catalogDigest: material.catalogDigest,
materialProof: material.materialProof,
preparedAtMs: 10_000,
...overrides,
});
}
test('file keyring rotates then retires one inactive key with exact recovery', async (t) => {
const { filePath } = fixture(t);
const initial = await provisionPluginPackagePromptOutputFileKeyring(filePath);
assert.equal(initial.generation, 1);
assert.equal(initial.keyIds.length, 1);
assert.deepEqual(initial.retiredKeyIds, []);
assert.equal(fs.statSync(filePath).mode & 0o777, 0o600);
const keyring = new PluginPackagePromptOutputFileKeyring(filePath);
const firstMaterial = await keyring.active();
assert.equal(firstMaterial.keyId, initial.activeKeyId);
assert.equal(firstMaterial.key.length, 32);
firstMaterial.key.fill(0);
const rotated = await rotatePluginPackagePromptOutputFileKeyring({
filePath,
expectedActiveKeyId: initial.activeKeyId,
expectedCatalogDigest: initial.catalogDigest,
});
assert.equal(rotated.generation, 2);
assert.notEqual(rotated.activeKeyId, initial.activeKeyId);
assert.deepEqual(
[...rotated.keyIds].sort(),
[initial.activeKeyId, rotated.activeKeyId].sort(),
);
const inactive = await keyring.inspect(initial.activeKeyId);
assert.equal(inactive.state, 'inactive');
const prepared = preparation(inactive);
const retired = await keyring.retire({ preparation: prepared });
assert.equal(retired.state, 'absent');
assert.deepEqual(await keyring.inspect(initial.activeKeyId), retired);
assert.deepEqual(await keyring.retire({ preparation: prepared }), retired);
assert.equal(await keyring.resolve(initial.activeKeyId), null);
const final = await keyring.summary();
assert.equal(final.generation, 3);
assert.deepEqual(final.keyIds, [rotated.activeKeyId]);
assert.deepEqual(final.retiredKeyIds, [initial.activeKeyId]);
const active = await keyring.active();
assert.equal(active.keyId, rotated.activeKeyId);
active.key.fill(0);
});
test('file keyring rejects active, stale and corrupt retirement authority', async (t) => {
const { directory, filePath } = fixture(t);
const initial = await provisionPluginPackagePromptOutputFileKeyring(filePath);
const keyring = new PluginPackagePromptOutputFileKeyring(filePath);
const active = await keyring.inspect(initial.activeKeyId);
assert.equal(active.state, 'active');
await assert.rejects(
keyring.retire({ preparation: preparation(active) }),
PluginPackagePromptOutputKeyRetirementConflictError,
);
const rotated = await rotatePluginPackagePromptOutputFileKeyring({
filePath,
expectedActiveKeyId: initial.activeKeyId,
expectedCatalogDigest: initial.catalogDigest,
});
const inactive = await keyring.inspect(initial.activeKeyId);
await assert.rejects(
keyring.retire({
preparation: preparation(inactive, { catalogDigest: 'f'.repeat(64) }),
}),
PluginPackagePromptOutputKeyRetirementConflictError,
);
const lockPath = `${filePath}.lock`;
fs.mkdirSync(lockPath, { mode: 0o700 });
fs.writeFileSync(
path.join(lockPath, 'owner.json'),
`${JSON.stringify({ pid: 99_999_999, token: 'dead' })}\n`,
{ mode: 0o600 },
);
const retired = await keyring.retire({ preparation: preparation(inactive) });
assert.equal(retired.state, 'absent');
assert.equal(fs.existsSync(lockPath), false);
const manifest = JSON.parse(fs.readFileSync(filePath, 'utf8'));
manifest.retirements[initial.activeKeyId].absenceProof = '0'.repeat(64);
fs.writeFileSync(filePath, `${JSON.stringify(manifest)}\n`, { mode: 0o600 });
await assert.rejects(
keyring.inspect(initial.activeKeyId),
PluginPackagePromptOutputKeyRetirementUnavailableError,
);
assert.equal(rotated.generation, 2);
assert.equal(fs.statSync(directory).mode & 0o777, 0o700);
});
@@ -0,0 +1,210 @@
const assert = require('node:assert/strict');
const { createHash } = require('node:crypto');
const { test } = require('node:test');
const {
InvalidPluginPackagePromptOutputKeyRetirementError,
PluginPackagePromptOutputKeyRetirementConflictError,
PluginPackagePromptOutputKeyRetirementCoordinator,
PluginPackagePromptOutputKeyRetirementUnavailableError,
createPluginPackagePromptOutputKeyRetirementCompletion,
createPluginPackagePromptOutputKeyRetirementPreparation,
normalizePluginPackagePromptOutputKeyRetirementCompletion,
normalizePluginPackagePromptOutputKeyRetirementPreparation,
pluginPackagePromptOutputKeyRetirementAbsenceProof,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRetirement.js');
const digest = (value) => createHash('sha256').update(value).digest('hex');
function request() {
return {
keyId: 'prompt-output-key-old',
retirementId: 'retire-prompt-output-key-old',
requestId: 'request-retire-prompt-output-key-old',
mutationId: 'mutation-retire-prompt-output-key-old',
};
}
function harness(options = {}) {
let record = null;
let material = {
state: options.materialState ?? 'inactive',
keyId: request().keyId,
catalogDigest: digest('catalog-before'),
materialProof: digest('material-old'),
};
let retireCalls = 0;
let failRetireResponse = options.failRetireResponse ?? false;
let failCompleteResponse = options.failCompleteResponse ?? false;
const repository = {
async find() {
return record;
},
async prepare(command) {
if (options.liveArtifacts) {
throw new PluginPackagePromptOutputKeyRetirementUnavailableError();
}
const preparation =
createPluginPackagePromptOutputKeyRetirementPreparation({
...command,
preparedAtMs: 100,
});
if (record) {
assert.deepEqual(record.preparation, preparation);
return { status: 'existing', preparation: record.preparation };
}
record = { preparation, completion: null };
return { status: 'created', preparation };
},
async complete(command) {
const completion = createPluginPackagePromptOutputKeyRetirementCompletion(
{
...command,
completedAtMs: 200,
},
);
if (record.completion) {
assert.deepEqual(record.completion, completion);
return { status: 'existing', completion: record.completion };
}
record = { ...record, completion };
if (failCompleteResponse) {
failCompleteResponse = false;
throw new Error('completion response lost');
}
return { status: 'created', completion };
},
};
const materials = {
async inspect() {
return { ...material };
},
async retire(command) {
retireCalls += 1;
assert.equal(command.preparation.keyId, material.keyId);
assert.equal(command.preparation.catalogDigest, material.catalogDigest);
assert.equal(command.preparation.materialProof, material.materialProof);
material = {
state: 'absent',
keyId: command.preparation.keyId,
catalogDigest: digest('catalog-after'),
absenceProof: pluginPackagePromptOutputKeyRetirementAbsenceProof(
record.preparation,
digest('catalog-after'),
),
};
if (failRetireResponse) {
failRetireResponse = false;
throw new Error('retirement response lost');
}
return { ...material };
},
};
return {
coordinator: new PluginPackagePromptOutputKeyRetirementCoordinator({
repository,
materials,
}),
record: () => record,
retireCalls: () => retireCalls,
setMaterial(next) {
material = next;
},
};
}
test('normalizes exact content-free preparation and completion receipts', () => {
const preparation = createPluginPackagePromptOutputKeyRetirementPreparation({
...request(),
catalogDigest: digest('catalog'),
materialProof: digest('material'),
preparedAtMs: 100,
});
const completion = createPluginPackagePromptOutputKeyRetirementCompletion({
preparation,
retiredCatalogDigest: digest('retired-catalog'),
absenceProof: digest('absence'),
completedAtMs: 200,
});
assert.deepEqual(
normalizePluginPackagePromptOutputKeyRetirementPreparation(preparation),
preparation,
);
assert.deepEqual(
normalizePluginPackagePromptOutputKeyRetirementCompletion(completion),
completion,
);
assert.throws(
() =>
normalizePluginPackagePromptOutputKeyRetirementPreparation({
...preparation,
widened: true,
}),
InvalidPluginPackagePromptOutputKeyRetirementError,
);
});
test('prepares a durable fence before retiring inactive material', async () => {
const value = harness();
const retired = await value.coordinator.retire(request());
assert.equal(retired.status, 'completed');
assert.equal(value.retireCalls(), 1);
assert.deepEqual(value.record(), {
preparation: retired.preparation,
completion: retired.completion,
});
assert.equal((await value.coordinator.retire(request())).status, 'existing');
assert.equal(value.retireCalls(), 1);
});
test('rejects active material and live Artifact coverage', async () => {
const active = harness({ materialState: 'active' });
await assert.rejects(
active.coordinator.retire(request()),
PluginPackagePromptOutputKeyRetirementConflictError,
);
assert.equal(active.record(), null);
const referenced = harness({ liveArtifacts: true });
await assert.rejects(
referenced.coordinator.retire(request()),
PluginPackagePromptOutputKeyRetirementUnavailableError,
);
assert.equal(referenced.retireCalls(), 0);
});
test('recovers when material retirement succeeded but its response was lost', async () => {
const value = harness({ failRetireResponse: true });
await assert.rejects(
value.coordinator.retire(request()),
PluginPackagePromptOutputKeyRetirementUnavailableError,
);
assert.equal(value.record().completion, null);
const recovered = await value.coordinator.retire(request());
assert.equal(recovered.status, 'completed');
assert.equal(value.retireCalls(), 1);
});
test('recovers completion response loss and rejects material drift', async () => {
const responseLoss = harness({ failCompleteResponse: true });
await assert.rejects(
responseLoss.coordinator.retire(request()),
PluginPackagePromptOutputKeyRetirementUnavailableError,
);
assert.equal(
(await responseLoss.coordinator.retire(request())).status,
'existing',
);
const drift = harness({ failRetireResponse: true });
await assert.rejects(drift.coordinator.retire(request()));
drift.setMaterial({
state: 'absent',
keyId: request().keyId,
catalogDigest: digest('drifted-catalog'),
absenceProof: digest('drifted-absence'),
});
await assert.rejects(
drift.coordinator.retire(request()),
PluginPackagePromptOutputKeyRetirementConflictError,
);
});
@@ -0,0 +1,190 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
PluginPackagePromptOutputKeyRotationConflictError,
PluginPackagePromptOutputKeyRotationCoordinator,
PluginPackagePromptOutputKeyRotationUnavailableError,
createPluginPackagePromptOutputKeyRotationCompletion,
createPluginPackagePromptOutputKeyRotationPreparation,
normalizePluginPackagePromptOutputKeyRotationCompletion,
normalizePluginPackagePromptOutputKeyRotationPreparation,
pluginPackagePromptOutputKeyRotationMaterialProof,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRotation.js');
function request() {
return {
rotationId: 'rotation-001',
requestId: 'request-001',
mutationId: 'mutation-001',
expectedSecretUid: 'secret-uid-001',
expectedActiveKeyId: 'prompt-key-one',
expectedCatalogDigest: '1'.repeat(64),
newKeyId: 'prompt-key-two',
};
}
function state(material) {
return {
generation: 2,
previousActiveKeyId: 'prompt-key-one',
activeKeyId: 'prompt-key-two',
catalogDigest: '2'.repeat(64),
materialProof: pluginPackagePromptOutputKeyRotationMaterialProof(
'prompt-key-two',
material,
),
};
}
function memoryRepository(options = {}) {
let record = null;
let clock = 1_000;
let failedAfterComplete = false;
return {
get record() {
return record;
},
async find(rotationId) {
return record?.preparation.rotationId === rotationId ? record : null;
},
async prepare(command) {
const candidate = createPluginPackagePromptOutputKeyRotationPreparation({
...command,
preparedAtMs: clock++,
});
if (record) {
return { status: 'existing', preparation: record.preparation };
}
record = { preparation: candidate, completion: null };
return { status: 'created', preparation: candidate };
},
async complete(command) {
if (record.completion) {
return { status: 'existing', completion: record.completion };
}
const completion = createPluginPackagePromptOutputKeyRotationCompletion({
...command,
completedAtMs: clock++,
});
record = { ...record, completion };
if (options.failOnceAfterComplete && !failedAfterComplete) {
failedAfterComplete = true;
throw new PluginPackagePromptOutputKeyRotationUnavailableError();
}
return { status: 'created', completion };
},
};
}
test('creates content-free rotation facts and exact replay skips material mutation', async () => {
const material = Buffer.alloc(32, 0x42);
const repository = memoryRepository();
let rotations = 0;
const coordinator = new PluginPackagePromptOutputKeyRotationCoordinator({
repository,
materials: {
async rotate() {
rotations += 1;
return state(material);
},
},
});
const completed = await coordinator.rotate({ request: request(), material });
assert.equal(completed.status, 'completed');
assert.equal(rotations, 1);
const replay = await coordinator.rotate({ request: request(), material });
assert.equal(replay.status, 'existing');
assert.equal(rotations, 1);
assert.deepEqual(replay.completion, completed.completion);
assert.deepEqual(
normalizePluginPackagePromptOutputKeyRotationPreparation(
completed.preparation,
),
completed.preparation,
);
assert.deepEqual(
normalizePluginPackagePromptOutputKeyRotationCompletion(
completed.completion,
),
completed.completion,
);
const durable = JSON.stringify(repository.record);
assert.equal(durable.includes(material.toString('base64url')), false);
assert.equal(durable.includes(material.toString('hex')), false);
});
test('resumes after preparation and converges after completion response loss', async () => {
const material = Buffer.alloc(32, 0x51);
const repository = memoryRepository({ failOnceAfterComplete: true });
await repository.prepare({
request: request(),
materialProof: pluginPackagePromptOutputKeyRotationMaterialProof(
request().newKeyId,
material,
),
});
let rotations = 0;
const coordinator = new PluginPackagePromptOutputKeyRotationCoordinator({
repository,
materials: {
async rotate() {
rotations += 1;
return state(material);
},
},
});
await assert.rejects(
coordinator.rotate({ request: request(), material }),
PluginPackagePromptOutputKeyRotationUnavailableError,
);
assert.equal(rotations, 1);
const replay = await coordinator.rotate({ request: request(), material });
assert.equal(replay.status, 'existing');
assert.equal(rotations, 1);
});
test('a prepared rotation rejects changed staged material and drifted successor', async () => {
const original = Buffer.alloc(32, 0x61);
const changed = Buffer.alloc(32, 0x62);
const repository = memoryRepository();
await repository.prepare({
request: request(),
materialProof: pluginPackagePromptOutputKeyRotationMaterialProof(
request().newKeyId,
original,
),
});
const coordinator = new PluginPackagePromptOutputKeyRotationCoordinator({
repository,
materials: {
async rotate() {
return state(original);
},
},
});
await assert.rejects(
coordinator.rotate({ request: request(), material: changed }),
PluginPackagePromptOutputKeyRotationConflictError,
);
const fresh = memoryRepository();
const drifted = new PluginPackagePromptOutputKeyRotationCoordinator({
repository: fresh,
materials: {
async rotate() {
return {
...state(original),
catalogDigest: '3'.repeat(64),
activeKeyId: 'other-key',
};
},
},
});
await assert.rejects(
drifted.rotate({ request: request(), material: original }),
PluginPackagePromptOutputKeyRotationConflictError,
);
});
@@ -0,0 +1,83 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
PluginPackagePromptOutputKeyRetirementConflictError,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyRetirement.js');
const {
pluginPackagePromptOutputKeyringCatalogDigest,
rotatePluginPackagePromptOutputKeyringManifest,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyringManifest.js');
function initial() {
return Object.freeze({
schema: 'qinglong/plugin-package-prompt-output-file-keyring@v1',
generation: 1,
activeKeyId: 'prompt-key-one',
keys: Object.freeze({
'prompt-key-one': Buffer.alloc(32, 0x11).toString('base64url'),
}),
retirements: Object.freeze({}),
});
}
function request(manifest, material = Buffer.alloc(32, 0x22)) {
return {
expectedActiveKeyId: 'prompt-key-one',
expectedCatalogDigest:
pluginPackagePromptOutputKeyringCatalogDigest(manifest),
newKeyId: 'prompt-key-two',
material,
};
}
test('rotates staged material while retaining history and exactly replays', () => {
const before = initial();
const staged = Buffer.alloc(32, 0x22);
const rotated = rotatePluginPackagePromptOutputKeyringManifest(
before,
request(before, staged),
);
assert.equal(rotated.changed, true);
assert.equal(rotated.state.generation, 2);
assert.equal(rotated.state.previousActiveKeyId, 'prompt-key-one');
assert.equal(rotated.state.activeKeyId, 'prompt-key-two');
assert.deepEqual(Object.keys(rotated.manifest.keys).sort(), [
'prompt-key-one',
'prompt-key-two',
]);
assert.equal(
rotated.manifest.keys['prompt-key-one'],
before.keys['prompt-key-one'],
);
assert.deepEqual(staged, Buffer.alloc(32, 0x22));
const replay = rotatePluginPackagePromptOutputKeyringManifest(
rotated.manifest,
request(before, staged),
);
assert.equal(replay.changed, false);
assert.deepEqual(replay.state, rotated.state);
assert.equal(replay.manifest, rotated.manifest);
});
test('rejects stale winners, changed material and key identity reuse', () => {
const before = initial();
const operation = request(before);
const rotated = rotatePluginPackagePromptOutputKeyringManifest(
before,
operation,
);
for (const [manifest, candidate] of [
[rotated.manifest, { ...operation, material: Buffer.alloc(32, 0x33) }],
[before, { ...operation, expectedCatalogDigest: '0'.repeat(64) }],
[before, { ...operation, newKeyId: 'prompt-key-one' }],
]) {
assert.throws(
() => rotatePluginPackagePromptOutputKeyringManifest(manifest, candidate),
(error) =>
error instanceof PluginPackagePromptOutputKeyRetirementConflictError ||
error.code === 'PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_INVALID',
);
}
});
@@ -0,0 +1,172 @@
const assert = require('node:assert/strict');
const fs = require('node:fs/promises');
const os = require('node:os');
const path = require('node:path');
const { afterEach, test } = require('node:test');
const {
PluginPackagePromptOutputProjectedKeyring,
PluginPackagePromptOutputProjectedKeyringUnavailableError,
createPluginPackagePromptOutputProjectedKeyring,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputProjectedKeyring.js');
const {
PLUGIN_PACKAGE_PROMPT_OUTPUT_KEYRING_MANIFEST_SCHEMA,
canonicalPluginPackagePromptOutputKeyringManifest,
} = require('../dist/prompt-output/key-management/pluginPackagePromptOutputKeyringManifest.js');
const roots = [];
afterEach(async () => {
await Promise.all(
roots
.splice(0)
.map((root) => fs.rm(root, { recursive: true, force: true })),
);
});
function manifest(generation, activeKeyId, keys) {
return Object.freeze({
schema: PLUGIN_PACKAGE_PROMPT_OUTPUT_KEYRING_MANIFEST_SCHEMA,
generation,
activeKeyId,
keys: Object.freeze(keys),
retirements: Object.freeze({}),
});
}
async function tempRoot() {
const root = await fs.mkdtemp(
path.join(os.tmpdir(), 'ql3-projected-keyring-'),
);
roots.push(root);
return root;
}
async function publish(root, generationName, bytes, mode = 0o440) {
const generation = path.join(root, generationName);
await fs.mkdir(generation, { mode: 0o750 });
const target = path.join(generation, 'keyring.json');
await fs.writeFile(target, bytes, { mode });
await fs.chmod(target, mode);
const next = path.join(root, '..data-next');
await fs.symlink(generationName, next);
await fs.rename(next, path.join(root, '..data'));
try {
await fs.symlink('..data/keyring.json', path.join(root, 'keyring.json'));
} catch (error) {
if (error.code !== 'EEXIST') throw error;
}
}
test('projected keyring follows bounded Kubernetes atomic rotation without caching', async () => {
const root = await tempRoot();
const keyOne = Buffer.alloc(32, 0x11).toString('base64url');
const keyTwo = Buffer.alloc(32, 0x22).toString('base64url');
await publish(
root,
'..2026_08_02_01',
canonicalPluginPackagePromptOutputKeyringManifest(
manifest(1, 'prompt-key-one', { 'prompt-key-one': keyOne }),
),
);
const provider = await createPluginPackagePromptOutputProjectedKeyring({
rootDirectory: root,
});
const first = await provider.active();
assert.equal(first.keyId, 'prompt-key-one');
assert.deepEqual(Buffer.from(first.key), Buffer.alloc(32, 0x11));
first.key.fill(0);
await publish(
root,
'..2026_08_02_02',
canonicalPluginPackagePromptOutputKeyringManifest(
manifest(2, 'prompt-key-two', {
'prompt-key-one': keyOne,
'prompt-key-two': keyTwo,
}),
),
);
const second = await provider.active();
assert.equal(second.keyId, 'prompt-key-two');
assert.deepEqual(Buffer.from(second.key), Buffer.alloc(32, 0x22));
const historical = await provider.resolve('prompt-key-one');
assert.ok(historical);
assert.deepEqual(Buffer.from(historical.key), Buffer.alloc(32, 0x11));
second.key.fill(0);
historical.key.fill(0);
});
test('projected keyring rejects noncanonical, writable and escaped material', async () => {
const key = Buffer.alloc(32, 0x33).toString('base64url');
const value = manifest(1, 'prompt-key-one', { 'prompt-key-one': key });
const noncanonicalRoot = await tempRoot();
await publish(
noncanonicalRoot,
'..2026_08_02_01',
Buffer.from(`${JSON.stringify(value, null, 2)}\n`, 'utf8'),
);
await assert.rejects(
() =>
createPluginPackagePromptOutputProjectedKeyring({
rootDirectory: noncanonicalRoot,
}),
PluginPackagePromptOutputProjectedKeyringUnavailableError,
);
const writableRoot = await tempRoot();
await publish(
writableRoot,
'..2026_08_02_01',
canonicalPluginPackagePromptOutputKeyringManifest(value),
0o640,
);
await assert.rejects(
() =>
new PluginPackagePromptOutputProjectedKeyring({
rootDirectory: writableRoot,
}).active(),
PluginPackagePromptOutputProjectedKeyringUnavailableError,
);
const escapedRoot = await tempRoot();
const externalRoot = await tempRoot();
const external = path.join(externalRoot, 'keyring.json');
await fs.writeFile(
external,
canonicalPluginPackagePromptOutputKeyringManifest(value),
{ mode: 0o440 },
);
await fs.symlink(external, path.join(escapedRoot, 'keyring.json'));
await assert.rejects(
() =>
new PluginPackagePromptOutputProjectedKeyring({
rootDirectory: escapedRoot,
}).verify(),
PluginPackagePromptOutputProjectedKeyringUnavailableError,
);
});
test('projected keyring rejects ambiguous roots and file names', async () => {
const root = await tempRoot();
const rootLink = `${root}-link`;
roots.push(rootLink);
await fs.symlink(root, rootLink);
await assert.rejects(
() =>
new PluginPackagePromptOutputProjectedKeyring({
rootDirectory: rootLink,
}).verify(),
PluginPackagePromptOutputProjectedKeyringUnavailableError,
);
assert.throws(
() =>
new PluginPackagePromptOutputProjectedKeyring({
rootDirectory: root,
dataFileName: '../keyring.json',
}),
PluginPackagePromptOutputProjectedKeyringUnavailableError,
);
});
@@ -0,0 +1,228 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
createPluginPackagePromptOutputArtifact,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const {
InvalidPluginPackagePromptOutputReadError,
PluginPackagePromptOutputReadService,
PluginPackagePromptOutputReadUnavailableError,
} = require('../dist/prompt-output/pluginPackagePromptOutputRead.js');
const NOW = 1_700_000_000_000;
const KEY = Buffer.alloc(32, 7);
const PRINCIPAL = Object.freeze({
subject: Object.freeze({ type: 'user', id: 'user-a' }),
authenticationId: 'auth-a',
authenticatedAtMs: NOW - 1_000,
expiresAtMs: NOW + 60_000,
assurance: 'multi_factor',
});
const RESULT = Object.freeze({
provider: 'openai-compatible',
model: 'bounded-model',
text: 'private durable output',
finishReason: 'stop',
usage: Object.freeze({
inputTokens: 5,
outputTokens: 3,
totalTokens: 8,
costMicros: 11,
}),
});
function artifact() {
return createPluginPackagePromptOutputArtifact(
{
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
invocationId: 'invocation-a',
requestedBy: PRINCIPAL.subject,
result: RESULT,
retentionPolicy: { revision: 'retention-v1', retentionMs: 86_400_000 },
keyId: 'prompt-key-1',
key: Buffer.from(KEY),
sealedAtMs: NOW - 1_000,
},
() => Buffer.alloc(12, 9),
);
}
function harness(overrides = {}) {
const stored = artifact();
const calls = [];
let resolvedKey;
const service = new PluginPackagePromptOutputReadService({
artifacts: {
async find(id) {
calls.push(`find:${id}`);
return stored;
},
async put() {
throw new Error('unreachable');
},
},
authorizer: {
async authorize(request) {
calls.push(`authorize:${request.artifactId}`);
return { effect: 'allow' };
},
},
retention: {
async inspect(request) {
calls.push(`retention:${request.reference.artifactId}`);
return { state: 'retained' };
},
},
keys: {
async active() {
throw new Error('read must not request active key');
},
async resolve(keyId) {
calls.push(`key:${keyId}`);
resolvedKey = Buffer.from(KEY);
return { keyId, key: resolvedKey };
},
},
now: () => NOW,
...overrides,
});
return { service, stored, calls, resolvedKey: () => resolvedKey };
}
function command(stored, overrides = {}) {
return {
principal: PRINCIPAL,
projectId: stored.projectId,
runId: stored.runId,
artifactId: stored.artifactId,
artifactDigest: stored.artifactDigest,
...overrides,
};
}
test('reads only after metadata, policy and retention and wipes resolved key', async () => {
const state = harness();
const result = await state.service.read(command(state.stored));
assert.equal(result.status, 'available');
assert.deepEqual(result.result, RESULT);
assert.equal(result.reference.artifactDigest, state.stored.artifactDigest);
assert.deepEqual(state.calls, [
`find:${state.stored.artifactId}`,
`authorize:${state.stored.artifactId}`,
`retention:${state.stored.artifactId}`,
'key:prompt-key-1',
]);
assert.equal(
state.resolvedKey().every((byte) => byte === 0),
true,
);
});
test('masks absent and identity-drifted Artifacts before policy or key access', async () => {
const missingCalls = [];
const missing = harness({
artifacts: {
async find() {
missingCalls.push('find');
return null;
},
async put() {
throw new Error('unreachable');
},
},
});
assert.equal(
(await missing.service.read(command(missing.stored))).status,
'not_found',
);
assert.deepEqual(missingCalls, ['find']);
const drift = harness();
assert.equal(
(
await drift.service.read(
command(drift.stored, { projectId: 'project-b' }),
)
).status,
'not_found',
);
assert.deepEqual(drift.calls, [`find:${drift.stored.artifactId}`]);
});
test('masks policy denial and tombstone without resolving key material', async () => {
const denied = harness({
authorizer: {
async authorize() {
return { effect: 'deny', reasonCode: 'artifact_read_denied' };
},
},
});
assert.equal(
(await denied.service.read(command(denied.stored))).status,
'not_found',
);
assert.equal(
denied.calls.some((call) => call.startsWith('key:')),
false,
);
const tombstoned = harness({
retention: {
async inspect() {
return {
state: 'tombstoned',
tombstonedAtMs: NOW - 1,
tombstoneDigest: 'a'.repeat(64),
};
},
},
});
assert.equal(
(await tombstoned.service.read(command(tombstoned.stored))).status,
'not_found',
);
assert.equal(
tombstoned.calls.some((call) => call.startsWith('key:')),
false,
);
});
test('fails closed for invalid requests, corrupt decisions and missing keys', async () => {
const invalid = harness();
await assert.rejects(
invalid.service.read(command(invalid.stored, { artifactDigest: 'bad' })),
InvalidPluginPackagePromptOutputReadError,
);
assert.deepEqual(invalid.calls, []);
const corruptDecision = harness({
authorizer: {
async authorize() {
return { effect: 'allow', widened: true };
},
},
});
await assert.rejects(
corruptDecision.service.read(command(corruptDecision.stored)),
PluginPackagePromptOutputReadUnavailableError,
);
const missingKey = harness({
keys: {
async active() {
throw new Error('unreachable');
},
async resolve() {
return null;
},
},
});
await assert.rejects(
missingKey.service.read(command(missingKey.stored)),
PluginPackagePromptOutputReadUnavailableError,
);
});
@@ -0,0 +1,81 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
InvalidPluginPackagePromptOutputRetentionPolicyCatalogError,
createPluginPackagePromptOutputRetentionPolicyCatalogResolver,
} = require('../dist/prompt-output/pluginPackagePromptOutputRetention');
const {
pluginPackagePromptOutputArtifactRetentionPolicyDigest,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact');
function entry(projectId, revision, retentionMs) {
const policy = { revision, retentionMs };
return {
projectId,
policy,
policyDigest:
pluginPackagePromptOutputArtifactRetentionPolicyDigest(policy),
};
}
test('resolves one exact digest-bound Project retention policy', async () => {
const expected = entry('project-a', 'retention-v1', 3_600_000);
const resolver =
createPluginPackagePromptOutputRetentionPolicyCatalogResolver({
schemaVersion: 1,
policies: [expected, entry('project-b', 'retention-v2', 7_200_000)],
});
assert.deepEqual(
await resolver.resolve({
projectId: expected.projectId,
revision: expected.policy.revision,
}),
expected.policy,
);
assert.equal(
await resolver.resolve({
projectId: expected.projectId,
revision: 'retention-v2',
}),
null,
);
});
test('rejects rewritten, duplicate, widened and unbounded policy catalogs', () => {
const expected = entry('project-a', 'retention-v1', 3_600_000);
assert.throws(
() =>
createPluginPackagePromptOutputRetentionPolicyCatalogResolver({
schemaVersion: 1,
policies: [{ ...expected, policyDigest: '0'.repeat(64) }],
}),
InvalidPluginPackagePromptOutputRetentionPolicyCatalogError,
);
assert.throws(
() =>
createPluginPackagePromptOutputRetentionPolicyCatalogResolver({
schemaVersion: 1,
policies: [expected, expected],
}),
InvalidPluginPackagePromptOutputRetentionPolicyCatalogError,
);
assert.throws(
() =>
createPluginPackagePromptOutputRetentionPolicyCatalogResolver({
schemaVersion: 1,
policies: [{ ...expected, enabled: true }],
}),
InvalidPluginPackagePromptOutputRetentionPolicyCatalogError,
);
assert.throws(
() =>
createPluginPackagePromptOutputRetentionPolicyCatalogResolver({
schemaVersion: 1,
policies: Array.from({ length: 129 }, (_, index) =>
entry(`project-${index}`, 'retention-v1', 3_600_000),
),
}),
InvalidPluginPackagePromptOutputRetentionPolicyCatalogError,
);
});
@@ -0,0 +1,997 @@
const assert = require('node:assert/strict');
const { createRequire } = require('node:module');
const path = require('node:path');
const test = require('node:test');
const {
createStepRunRecord,
transitionStepRunMutation,
} = require('@qinglong/runtime-core/step-run');
const {
ModelInvocationConflictError,
createModelInvocationCompletionCommand,
createModelInvocationMutationIdentity,
createModelInvocationStartCommand,
} = require('../dist/model-invocation/modelInvocation.js');
const {
migratePostgresModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
PostgresModelInvocationRepository,
} = require('../dist/model-invocation/postgresModelInvocationRepository.js');
const {
DurableModelInvocationCoordinator,
DurableModelInvocationRecovery,
} = require('../dist/model-invocation/durableModelInvocationCoordinator.js');
const {
DurableModelInvocationResolutionCoordinator,
} = require('../dist/model-invocation/modelInvocationResolution.js');
const {
BoundedModelGateway,
ModelInvocationReplayBlockedError,
} = require('../dist/model-gateway/gateway.js');
const {
ModelInvocationProjectQuotaExceededError,
createModelInvocationQuotaAdmission,
} = require('../dist/usage/usageQuota.js');
const {
StaticModelPriceCatalog,
createModelPriceCatalogEntry,
} = require('../dist/pricing/pricing.js');
const migrationConnectionString =
process.env.QL3_TEST_POSTGRES_MIGRATION_URL ??
process.env.QL3_TEST_POSTGRES_URL;
const runtimeConnectionString =
process.env.QL3_TEST_POSTGRES_RUNTIME_URL ?? migrationConnectionString;
if (!migrationConnectionString) {
test(
'PostgreSQL ModelInvocation integration requires QL3_TEST_POSTGRES_URL',
{
skip: true,
},
);
} else {
const clusterRequire = createRequire(
path.resolve(__dirname, '../../ql3-cluster-postgres/package.json'),
);
const { Pool } = clusterRequire('pg');
const {
runPostgresMigrations,
} = require('../../ql3-cluster-postgres/dist/migration/migration.js');
const {
assertPostgresSchemaReady,
} = require('../../ql3-cluster-postgres/dist/schema/schemaReadiness.js');
const NOW = 2_000_000;
const RUN_ID = '51000000-0000-4000-8000-000000000001';
const CONFLICT_RUN_ID = '51000000-0000-4000-8000-000000000002';
const FAULT_RUN_ID = '51000000-0000-4000-8000-000000000003';
const QUOTA_RUN_A_ID = '51000000-0000-4000-8000-000000000004';
const QUOTA_RUN_B_ID = '51000000-0000-4000-8000-000000000005';
const PRICING_RUN_ID = '51000000-0000-4000-8000-000000000006';
function pool(connectionString, applicationName) {
return new Pool({
connectionString,
ssl: false,
max: 4,
application_name: applicationName,
});
}
function commitResponseLossPool(basePool) {
let injected = false;
return {
query(text, values) {
return basePool.query(text, values);
},
async connect() {
const client = await basePool.connect();
return {
async query(text, values) {
const result = await client.query(text, values);
if (!injected && /^\s*COMMIT\s*$/i.test(text)) {
injected = true;
const error = new Error('injected response loss after COMMIT');
error.code = 'ECONNRESET';
throw error;
}
return result;
},
release() {
client.release();
},
};
},
wasInjected() {
return injected;
},
};
}
function audit(phase, overrides = {}) {
return {
phase,
projectId: 'project-ai',
runId: RUN_ID,
stepRunId: 'model-step-ai',
traceId: 'trace-ai',
requestId: 'request-ai',
provider: 'remote',
model: 'model-ai',
policyRevision: 'policy-1',
requestDigest: `sha256:${'b'.repeat(64)}`,
deadlineAtMs: NOW + 10_000,
inputBytes: 128,
maxOutputTokens: 64,
outputBytes: 0,
usage: null,
errorCode: null,
occurredAtMs: NOW,
...overrides,
};
}
function readyStep(runId, stepRunId, mutationId) {
return createStepRunRecord({
id: stepRunId,
runId,
stepKey: 'summarize',
kind: 'model',
definitionRef: 'prompt:summary@1',
definitionDigest: 'a'.repeat(64),
required: true,
initialStatus: 'ready',
inputRef: `artifact:${stepRunId}:input`,
mutationId,
createdAtMs: NOW - 1,
});
}
function startCommand(ready, auditRecord = audit('admitted')) {
const identity = createModelInvocationMutationIdentity(
auditRecord.requestId,
'start',
);
return createModelInvocationStartCommand(
auditRecord,
transitionStepRunMutation(
ready,
{
expectedVersion: ready.version,
expectedDigest: ready.stepRunDigest,
mutationId: identity.mutationId,
to: 'running',
atMs: auditRecord.occurredAtMs,
},
{
expectedRunVersion: 1,
expectedRunEventSequence: 1,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
}
function completionCommand(start) {
const identity = createModelInvocationMutationIdentity(
start.start.invocationId,
'completion',
);
const completedAudit = audit('completed', {
runId: start.start.runId,
stepRunId: start.start.stepRunId,
traceId: start.start.traceId,
requestId: start.start.invocationId,
occurredAtMs: NOW + 25,
outputBytes: 12,
usage: { inputTokens: 5, outputTokens: 2, totalTokens: 7 },
});
return createModelInvocationCompletionCommand(
start.start,
completedAudit,
transitionStepRunMutation(
start.stepRunMutation.stepRun,
{
expectedVersion: start.start.startedStepRunVersion,
expectedDigest: start.start.startedStepRunDigest,
mutationId: identity.mutationId,
to: 'succeeded',
atMs: completedAudit.occurredAtMs,
outputRef: `model-invocation:${start.start.invocationId}`,
},
{
expectedRunVersion: 2,
expectedRunEventSequence: 2,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
}
async function deleteFixture(client, runId) {
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_price_settlements"
WHERE invocation_id IN (
SELECT invocation_id
FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1
)`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_quota_settlements"
WHERE invocation_id IN (
SELECT invocation_id
FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1
)`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_quota_reservations"
WHERE invocation_id IN (
SELECT invocation_id
FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1
)`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_price_quotes"
WHERE invocation_id IN (
SELECT invocation_id
FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1
)`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_resolutions"
WHERE run_id = $1`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_usage_ledger"
WHERE run_id = $1`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_completions"
WHERE run_id = $1`,
[runId],
);
await client.query(
`DELETE FROM "ql3_ai"."model_invocation_starts" WHERE run_id = $1`,
[runId],
);
await client.query(
`DELETE FROM "ql3"."step_run_mutations" WHERE run_id = $1`,
[runId],
);
await client.query(`DELETE FROM "ql3"."run_events" WHERE run_id = $1`, [
runId,
]);
await client.query(`DELETE FROM "ql3"."step_runs" WHERE run_id = $1`, [
runId,
]);
await client.query(`DELETE FROM "ql3"."runs" WHERE id = $1`, [runId]);
}
async function insertFixture(
client,
ready,
runVersion = 1,
projectId = 'project-ai',
) {
await client.query(
`INSERT INTO "ql3"."runs" (
id, project_id, task_id, task_revision, trigger_type,
execution_origin, execution_owner, status, version,
event_sequence, priority, created_at_ms
) VALUES (
$1, $4, 'task-ai', 'task-revision-ai', 'manual',
'manual', 'runtime', 'running', $2, 1, 0, $3
)`,
[ready.runId, runVersion, NOW - 1, projectId],
);
await client.query(
`INSERT INTO "ql3"."step_runs" (
id, run_id, parent_step_run_id, step_key, kind, definition_ref,
definition_digest, required, status, version, attempt_count,
input_ref, output_ref, approval_request_id, ready_at_ms,
started_at_ms, finished_at_ms, result_code, error_summary,
created_at_ms, updated_at_ms, last_mutation_id, step_run_digest,
step_run_json
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13,
$14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24::jsonb
)`,
[
ready.id,
ready.runId,
ready.parentStepRunId,
ready.stepKey,
ready.kind,
ready.definitionRef,
ready.definitionDigest,
ready.required,
ready.status,
ready.version,
ready.attemptCount,
ready.inputRef,
ready.outputRef,
ready.approvalRequestId,
ready.readyAtMs,
ready.startedAtMs,
ready.finishedAtMs,
ready.resultCode,
ready.errorSummary,
ready.createdAtMs,
ready.updatedAtMs,
ready.lastMutationId,
ready.stepRunDigest,
JSON.stringify(ready),
],
);
}
test('PostgreSQL migration and repository preserve atomic model invocation facts', async () => {
const migrationPool = pool(
migrationConnectionString,
'ql3-ai-model-invocation-migration-test',
);
const runtimePool = pool(
runtimeConnectionString,
'ql3-ai-model-invocation-runtime-test',
);
try {
await runPostgresMigrations({ pool: migrationPool });
await migratePostgresModelInvocationFeature(migrationPool);
await runPostgresMigrations({ pool: migrationPool });
await migratePostgresModelInvocationFeature(migrationPool);
assert.equal((await assertPostgresSchemaReady(runtimePool)).ready, true);
const privileges = await runtimePool.query(
`SELECT
has_table_privilege(
current_user, 'ql3_ai.model_invocation_starts', 'SELECT'
) AS start_select,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_starts', 'INSERT'
) AS start_insert,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_starts', 'UPDATE'
) AS start_update,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_starts', 'DELETE'
) AS start_delete,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_completions', 'SELECT'
) AS completion_select,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_completions', 'INSERT'
) AS completion_insert,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_resolutions', 'SELECT'
) AS resolution_select,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_resolutions', 'INSERT'
) AS resolution_insert,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_resolutions', 'UPDATE'
) AS resolution_update,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_resolutions', 'DELETE'
) AS resolution_delete,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_usage_ledger', 'SELECT'
) AS usage_select,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_usage_ledger', 'INSERT'
) AS usage_insert,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_usage_ledger', 'UPDATE'
) AS usage_update,
has_table_privilege(
current_user, 'ql3_ai.model_invocation_usage_ledger', 'DELETE'
) AS usage_delete,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_reservations', 'SELECT'
) AS quota_reservation_select,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_reservations', 'INSERT'
) AS quota_reservation_insert,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_reservations', 'UPDATE'
) AS quota_reservation_update,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_reservations', 'DELETE'
) AS quota_reservation_delete,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_settlements', 'SELECT'
) AS quota_settlement_select,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_settlements', 'INSERT'
) AS quota_settlement_insert,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_settlements', 'UPDATE'
) AS quota_settlement_update,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_quota_settlements', 'DELETE'
) AS quota_settlement_delete,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_quotes', 'SELECT'
) AS price_quote_select,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_quotes', 'INSERT'
) AS price_quote_insert,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_quotes', 'UPDATE'
) AS price_quote_update,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_quotes', 'DELETE'
) AS price_quote_delete,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_settlements', 'SELECT'
) AS price_settlement_select,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_settlements', 'INSERT'
) AS price_settlement_insert,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_settlements', 'UPDATE'
) AS price_settlement_update,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_price_settlements', 'DELETE'
) AS price_settlement_delete`,
);
assert.deepEqual(privileges.rows[0], {
start_select: true,
start_insert: true,
start_update: false,
start_delete: false,
completion_select: true,
completion_insert: true,
resolution_select: true,
resolution_insert: true,
resolution_update: false,
resolution_delete: false,
usage_select: true,
usage_insert: true,
usage_update: false,
usage_delete: false,
quota_reservation_select: true,
quota_reservation_insert: true,
quota_reservation_update: false,
quota_reservation_delete: false,
quota_settlement_select: true,
quota_settlement_insert: true,
quota_settlement_update: false,
quota_settlement_delete: false,
price_quote_select: true,
price_quote_insert: true,
price_quote_update: false,
price_quote_delete: false,
price_settlement_select: true,
price_settlement_insert: true,
price_settlement_update: false,
price_settlement_delete: false,
});
await deleteFixture(migrationPool, RUN_ID);
await deleteFixture(migrationPool, CONFLICT_RUN_ID);
await deleteFixture(migrationPool, FAULT_RUN_ID);
await deleteFixture(migrationPool, QUOTA_RUN_A_ID);
await deleteFixture(migrationPool, QUOTA_RUN_B_ID);
await deleteFixture(migrationPool, PRICING_RUN_ID);
const ready = readyStep(RUN_ID, 'model-step-ai', 'create-model-step-ai');
await insertFixture(migrationPool, ready);
const start = startCommand(ready);
const completion = completionCommand(start);
const repository = new PostgresModelInvocationRepository(runtimePool);
const authority = await repository.readAuthority({
projectId: 'project-ai',
runId: RUN_ID,
stepRunId: 'model-step-ai',
});
assert.equal(authority.stepRun.status, 'ready');
assert.equal(authority.runVersion, 1);
assert.equal((await repository.admit(start)).status, 'created');
assert.equal((await repository.admit(start)).status, 'existing');
assert.deepEqual(await repository.findStart('request-ai'), start.start);
const incomplete = await repository.listIncomplete(1);
assert.deepEqual(
incomplete.candidates.map((candidate) => candidate.invocationId),
['request-ai'],
);
assert.equal(incomplete.hasMore, false);
assert.equal((await repository.complete(completion)).status, 'created');
assert.equal((await repository.complete(completion)).status, 'existing');
assert.deepEqual(
await repository.findCompletion('request-ai'),
completion.completion,
);
const usage = await repository.findUsage('request-ai');
assert.equal(
usage.completionDigest,
completion.completion.completionDigest,
);
assert.equal(usage.totalTokens, 7);
assert.deepEqual(
await repository.summarizeProjectUsage({
projectId: 'project-ai',
fromMsInclusive: NOW,
toMsExclusive: NOW + 100,
}),
{
invocationCount: 1,
inputTokens: 5,
outputTokens: 2,
totalTokens: 7,
knownCostMicros: 0,
unknownCostInvocations: 1,
},
);
const facts = await migrationPool.query(
`SELECT
(SELECT status FROM "ql3"."step_runs"
WHERE id = 'model-step-ai') AS step_status,
(SELECT version FROM "ql3"."step_runs"
WHERE id = 'model-step-ai') AS step_version,
(SELECT version FROM "ql3"."runs" WHERE id = $1) AS run_version,
(SELECT event_sequence FROM "ql3"."runs" WHERE id = $1)
AS event_sequence,
(SELECT count(*) FROM "ql3"."run_events" WHERE run_id = $1)
AS events,
(SELECT count(*) FROM "ql3"."step_run_mutations"
WHERE run_id = $1) AS mutations,
(SELECT count(*) FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1) AS starts,
(SELECT count(*) FROM "ql3_ai"."model_invocation_completions"
WHERE run_id = $1) AS completions,
(SELECT count(*) FROM "ql3_ai"."model_invocation_usage_ledger"
WHERE run_id = $1) AS usage`,
[RUN_ID],
);
assert.deepEqual(facts.rows[0], {
step_status: 'succeeded',
step_version: 3,
run_version: 3,
event_sequence: 3,
events: '2',
mutations: '2',
starts: '1',
completions: '1',
usage: '1',
});
const quotaReadyA = readyStep(
QUOTA_RUN_A_ID,
'model-step-quota-a',
'create-model-step-quota-a',
);
const quotaReadyB = readyStep(
QUOTA_RUN_B_ID,
'model-step-quota-b',
'create-model-step-quota-b',
);
await insertFixture(migrationPool, quotaReadyA);
await insertFixture(migrationPool, quotaReadyB);
const quotaStartA = startCommand(
quotaReadyA,
audit('admitted', {
runId: QUOTA_RUN_A_ID,
stepRunId: 'model-step-quota-a',
traceId: 'trace-quota-a',
requestId: 'request-quota-a',
}),
);
const quotaStartB = startCommand(
quotaReadyB,
audit('admitted', {
runId: QUOTA_RUN_B_ID,
stepRunId: 'model-step-quota-b',
traceId: 'trace-quota-b',
requestId: 'request-quota-b',
}),
);
const quotaPolicy = {
revision: 'quota-concurrency-1',
windowMs: 3_600_000,
maxInvocations: 1,
maxTokens: 512,
maxCostMicros: null,
};
const quotaAdmissions = [quotaStartA, quotaStartB].map((command) =>
createModelInvocationQuotaAdmission({
invocationId: command.start.invocationId,
projectId: command.start.projectId,
modelPolicyRevision: command.start.policyRevision,
reservedTokens: 256,
reservedCostMicros: null,
quota: quotaPolicy,
}),
);
const quotaResults = await Promise.allSettled([
repository.admitWithQuota(quotaStartA, quotaAdmissions[0]),
repository.admitWithQuota(quotaStartB, quotaAdmissions[1]),
]);
assert.equal(
quotaResults.filter((result) => result.status === 'fulfilled').length,
1,
JSON.stringify(
quotaResults.map((result) =>
result.status === 'fulfilled'
? { status: result.status }
: {
status: result.status,
name: result.reason?.name,
code: result.reason?.code,
message: result.reason?.message,
cause: result.reason?.cause?.message,
},
),
),
);
const quotaRejection = quotaResults.find(
(result) => result.status === 'rejected',
);
assert.ok(
quotaRejection.reason instanceof
ModelInvocationProjectQuotaExceededError,
);
const winnerIndex = quotaResults.findIndex(
(result) => result.status === 'fulfilled',
);
const winningStart = [quotaStartA, quotaStartB][winnerIndex];
const losingStart = [quotaStartA, quotaStartB][1 - winnerIndex];
assert.equal(
await repository.findStart(losingStart.start.invocationId),
null,
);
const winningReservation = await repository.findQuotaReservation(
winningStart.start.invocationId,
);
assert.equal(winningReservation.reservedTokens, 256);
assert.equal(
(await repository.completeWithQuota(completionCommand(winningStart)))
.status,
'created',
);
const winningSettlement = await repository.findQuotaSettlement(
winningStart.start.invocationId,
);
assert.equal(winningSettlement.effectiveTokens, 7);
assert.equal(winningSettlement.retainedTokenReservation, false);
assert.deepEqual(
await repository.readQuotaWindowUsage(
'project-ai',
winningReservation.reservedAtMs,
),
{
projectId: 'project-ai',
windowStartMs: winningReservation.windowStartMs,
windowEndMs: winningReservation.windowEndMs,
invocationCount: 1,
effectiveTokens: 7,
effectiveCostMicros: 0,
unknownCostInvocations: 1,
},
);
const pricingReady = readyStep(
PRICING_RUN_ID,
'model-step-pricing',
'create-model-step-pricing',
);
await insertFixture(migrationPool, pricingReady, 1, 'project-pricing');
const pricing = new StaticModelPriceCatalog([
createModelPriceCatalogEntry({
provider: 'remote',
model: 'model-ai',
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
publishedAtMs: NOW - 1,
}),
]);
const pricedGateway = new BoundedModelGateway({
providers: [
{
type: 'remote',
async listModels() {
return [{ id: 'model-ai' }];
},
async generate() {
return {
provider: 'remote',
model: 'model-ai',
text: 'priced summary',
finishReason: 'stop',
usage: {
inputTokens: 5,
outputTokens: 2,
totalTokens: 7,
costMicros: 99_999,
},
};
},
async *stream() {
throw new Error('not used');
},
},
],
pricing,
policies: {
async resolve() {
return {
revision: 'policy-priced-1',
allowedProviders: ['remote'],
allowedModels: ['model-ai'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 64,
maxTotalTokens: 256,
maxCostMicros: 100,
priceRevision: 'price-1',
projectQuota: {
revision: 'quota-priced-1',
windowMs: 3_600_000,
maxInvocations: 10,
maxTokens: 10_000,
maxCostMicros: 1_000,
},
};
},
},
audit: new DurableModelInvocationCoordinator(repository),
maxConcurrent: 1,
now: () => NOW,
});
const pricedResult = await pricedGateway.generate(
{
provider: 'remote',
model: 'model-ai',
messages: [{ role: 'user', content: 'priced prompt' }],
maxOutputTokens: 64,
},
{
projectId: 'project-pricing',
runId: PRICING_RUN_ID,
stepRunId: 'model-step-pricing',
traceId: 'trace-pricing',
requestId: 'request-pricing',
deadlineAtMs: NOW + 10_000,
},
);
const priceQuote = await repository.findPriceQuote('request-pricing');
const priceSettlement = await repository.findPriceSettlement(
'request-pricing',
);
const pricedReservation = await repository.findQuotaReservation(
'request-pricing',
);
const pricedQuotaSettlement = await repository.findQuotaSettlement(
'request-pricing',
);
assert.equal(pricedResult.usage.costMicros, 3);
assert.equal(priceQuote.reservedCostMicros, 68);
assert.equal(priceSettlement.costMicros, 3);
assert.equal(
(await repository.findUsage('request-pricing')).costMicros,
3,
);
assert.equal(pricedReservation.reservedCostMicros, 68);
assert.equal(pricedQuotaSettlement.effectiveCostMicros, 3);
const conflictReady = readyStep(
CONFLICT_RUN_ID,
'model-step-conflict',
'create-model-step-conflict',
);
await insertFixture(migrationPool, conflictReady, 2);
const conflictStart = startCommand(
conflictReady,
audit('admitted', {
runId: CONFLICT_RUN_ID,
stepRunId: 'model-step-conflict',
traceId: 'trace-conflict',
requestId: 'request-conflict',
}),
);
await assert.rejects(
repository.admit(conflictStart),
ModelInvocationConflictError,
);
const rolledBack = await migrationPool.query(
`SELECT
(SELECT count(*) FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1) AS starts,
(SELECT count(*) FROM "ql3"."run_events"
WHERE run_id = $1) AS events,
(SELECT count(*) FROM "ql3"."step_run_mutations"
WHERE run_id = $1) AS mutations`,
[CONFLICT_RUN_ID],
);
assert.deepEqual(rolledBack.rows[0], {
starts: '0',
events: '0',
mutations: '0',
});
const faultReady = readyStep(
FAULT_RUN_ID,
'model-step-fault',
'create-model-step-fault',
);
await insertFixture(migrationPool, faultReady);
const faultPool = commitResponseLossPool(runtimePool);
const faultRepository = new PostgresModelInvocationRepository(faultPool);
const faultCoordinator = new DurableModelInvocationCoordinator(
faultRepository,
);
let providerCalls = 0;
const gateway = new BoundedModelGateway({
providers: [
{
type: 'remote',
async listModels() {
return [{ id: 'model-ai' }];
},
async generate() {
providerCalls += 1;
throw new Error('provider must not run after ambiguous commit');
},
async *stream() {
throw new Error('not used');
},
},
],
pricing: {
async resolve() {
throw new Error('pricing must remain unreachable');
},
},
policies: {
async resolve() {
return {
revision: 'policy-1',
allowedProviders: ['remote'],
allowedModels: ['model-ai'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 64,
maxTotalTokens: 256,
maxCostMicros: null,
priceRevision: null,
};
},
},
audit: faultCoordinator,
maxConcurrent: 1,
now: () => NOW,
});
await assert.rejects(
gateway.generate(
{
provider: 'remote',
model: 'model-ai',
messages: [{ role: 'user', content: 'must not persist' }],
maxOutputTokens: 64,
},
{
projectId: 'project-ai',
runId: FAULT_RUN_ID,
stepRunId: 'model-step-fault',
traceId: 'trace-fault',
requestId: 'request-fault',
deadlineAtMs: NOW + 10_000,
},
),
ModelInvocationReplayBlockedError,
);
assert.equal(faultPool.wasInjected(), true);
assert.equal(providerCalls, 0);
const committedStart = await repository.findStart('request-fault');
assert.equal(committedStart.invocationId, 'request-fault');
assert.equal(
JSON.stringify(committedStart).includes('must not persist'),
false,
);
const recovery = await new DurableModelInvocationRecovery(
repository,
).recover(8);
assert.deepEqual(
{
recovered: recovery.recovered,
failed: recovery.failed,
hasMore: recovery.hasMore,
},
{ recovered: 1, failed: 0, hasMore: false },
);
const recoveredCompletion = await repository.findCompletion(
'request-fault',
);
assert.equal(recoveredCompletion.outcome, 'outcome_unknown');
assert.equal(await repository.findUsage('request-fault'), null);
const recoveredStep = await migrationPool.query(
`SELECT status FROM "ql3"."step_runs" WHERE id = 'model-step-fault'`,
);
assert.equal(recoveredStep.rows[0].status, 'lost');
const resolution = await new DurableModelInvocationResolutionCoordinator(
repository,
).resolve({
invocationId: 'request-fault',
decision: 'retry',
resolvedByUserId: 'user-ai',
resolvedAtMs: recoveredCompletion.completedAtMs + 1,
});
assert.equal(resolution.status, 'created');
const retryAtMs = recoveredCompletion.completedAtMs + 2;
assert.deepEqual(
await new DurableModelInvocationCoordinator(repository).record(
audit('admitted', {
runId: FAULT_RUN_ID,
stepRunId: 'model-step-fault',
traceId: 'trace-fault-retry',
requestId: 'request-fault-retry',
occurredAtMs: retryAtMs,
deadlineAtMs: retryAtMs + 10_000,
}),
),
{ status: 'created' },
);
const retried = await migrationPool.query(
`SELECT
(SELECT status FROM "ql3"."step_runs"
WHERE id = 'model-step-fault') AS step_status,
(SELECT attempt_count FROM "ql3"."step_runs"
WHERE id = 'model-step-fault') AS attempt_count,
(SELECT count(*) FROM "ql3_ai"."model_invocation_starts"
WHERE run_id = $1) AS starts,
(SELECT count(*) FROM "ql3_ai"."model_invocation_completions"
WHERE run_id = $1) AS completions,
(SELECT count(*) FROM "ql3_ai"."model_invocation_resolutions"
WHERE run_id = $1) AS resolutions`,
[FAULT_RUN_ID],
);
assert.deepEqual(retried.rows[0], {
step_status: 'running',
attempt_count: 2,
starts: '2',
completions: '1',
resolutions: '1',
});
} finally {
await runtimePool.end();
await migrationPool.end();
}
});
}
@@ -0,0 +1,540 @@
const assert = require('node:assert/strict');
const { randomUUID } = require('node:crypto');
const { createRequire } = require('node:module');
const path = require('node:path');
const test = require('node:test');
const {
ModelPriceCatalogConflictError,
createModelPriceCatalogPublishCommand,
createModelPriceCatalogTransitionCommand,
} = require('../dist/pricing/modelPriceCatalog.js');
const {
migratePostgresModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
ModelPriceCatalogManagementSeparationOfDutyError,
createModelPriceCatalogManagementService,
createModelPriceCatalogPolicyDecision,
} = require('../dist/pricing/modelPriceCatalogManagement.js');
const {
PostgresModelPriceCatalogReader,
PostgresModelPriceCatalogRepository,
} = require('../dist/pricing/storage/postgresModelPriceCatalogRepository.js');
const migrationConnectionString =
process.env.QL3_TEST_POSTGRES_MIGRATION_URL ??
process.env.QL3_TEST_POSTGRES_URL;
const adminConnectionString = process.env.QL3_TEST_POSTGRES_ADMIN_URL;
const runtimeConnectionString = process.env.QL3_TEST_POSTGRES_RUNTIME_URL;
if (
!migrationConnectionString ||
!adminConnectionString ||
!runtimeConnectionString
) {
test(
'PostgreSQL Model price catalog integration requires migration, admin and runtime URLs',
{ skip: true },
);
} else {
const clusterRequire = createRequire(
path.resolve(__dirname, '../../ql3-cluster-postgres/package.json'),
);
const { Pool } = clusterRequire('pg');
const {
runPostgresMigrations,
} = require('../../ql3-cluster-postgres/dist/migration/migration.js');
function pool(connectionString, applicationName) {
return new Pool({
connectionString,
ssl: false,
max: 4,
application_name: applicationName,
});
}
function publish(provider, model, revision, mutationId, rate) {
return createModelPriceCatalogPublishCommand({
provider,
model,
priceRevision: revision,
currency: 'USD',
inputMicrosPerMillionTokens: rate,
outputMicrosPerMillionTokens: rate * 4,
mutationId,
publishedByUserId: 'integration-admin',
});
}
function transition(provider, model, head, action, revision, mutationId) {
return createModelPriceCatalogTransitionCommand({
provider,
model,
expectedGeneration: head?.generation ?? 0,
expectedHeadDigest: head?.headDigest ?? null,
action,
priceRevision: revision,
mutationId,
changedByUserId: 'integration-admin',
});
}
async function assertSqlState(operation, expected) {
await assert.rejects(operation, (error) => {
assert.equal(error.code, expected);
return true;
});
}
test('PostgreSQL catalog serializes publication, activation and permanent revocation', async () => {
const suffix = randomUUID();
const provider = `integration-${suffix}`;
const model = 'model-price-catalog';
const migrationPool = pool(
migrationConnectionString,
'ql3-ai-price-catalog-migration-test',
);
const adminPool = pool(
adminConnectionString,
'ql3-ai-price-catalog-admin-test',
);
const runtimePool = pool(
runtimeConnectionString,
'ql3-ai-price-catalog-runtime-test',
);
const repository = new PostgresModelPriceCatalogRepository(adminPool);
const reader = new PostgresModelPriceCatalogReader(runtimePool);
try {
await runPostgresMigrations({ pool: migrationPool });
await migratePostgresModelInvocationFeature(migrationPool);
const firstCommand = publish(
provider,
model,
'price-1',
`publish-1-${suffix}`,
150_000,
);
const first = await repository.publish(firstCommand);
assert.equal(first.status, 'created');
assert.deepEqual(await repository.publish(firstCommand), {
status: 'existing',
publication: first.publication,
});
assert.equal(
await reader.resolve({
provider,
model,
priceRevision: 'price-1',
}),
null,
);
const second = await repository.publish(
publish(provider, model, 'price-2', `publish-2-${suffix}`, 200_000),
);
const activated = await repository.transition(
transition(
provider,
model,
null,
'activate',
'price-1',
`activate-1-${suffix}`,
),
);
assert.equal(
(
await reader.resolve({
provider,
model,
priceRevision: 'price-1',
})
).catalogDigest,
first.publication.entry.catalogDigest,
);
const competitors = await Promise.allSettled([
repository.transition(
transition(
provider,
model,
activated.head,
'activate',
'price-2',
`activate-2-${suffix}`,
),
),
repository.transition(
transition(
provider,
model,
activated.head,
'deactivate',
null,
`deactivate-1-${suffix}`,
),
),
]);
assert.equal(
competitors.filter((result) => result.status === 'fulfilled').length,
1,
);
assert.equal(
competitors.filter(
(result) =>
result.status === 'rejected' &&
result.reason instanceof ModelPriceCatalogConflictError,
).length,
1,
);
let current = await repository.findCurrent(provider, model);
if (current.activePriceRevision !== 'price-2') {
current = (
await repository.transition(
transition(
provider,
model,
current,
'activate',
'price-2',
`activate-2-after-race-${suffix}`,
),
)
).head;
}
assert.equal(
(
await reader.resolve({
provider,
model,
priceRevision: 'price-2',
})
).catalogDigest,
second.publication.entry.catalogDigest,
);
assert.equal(
await reader.resolve({
provider,
model,
priceRevision: 'price-1',
}),
null,
);
current = (
await repository.transition(
transition(
provider,
model,
current,
'revoke',
'price-1',
`revoke-1-${suffix}`,
),
)
).head;
assert.equal(current.activePriceRevision, 'price-2');
current = (
await repository.transition(
transition(
provider,
model,
current,
'revoke',
'price-2',
`revoke-2-${suffix}`,
),
)
).head;
assert.equal(current.activePriceRevision, null);
assert.equal(
await reader.resolve({
provider,
model,
priceRevision: 'price-2',
}),
null,
);
await assert.rejects(
repository.transition(
transition(
provider,
model,
current,
'activate',
'price-2',
`reactivate-2-${suffix}`,
),
),
ModelPriceCatalogConflictError,
);
const privileges = await Promise.all([
runtimePool.query(
`SELECT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'SELECT'
) AS publication_select,
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'INSERT'
) AS publication_insert,
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'SELECT'
) AS head_select,
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'INSERT'
) AS head_insert`,
),
adminPool.query(
`SELECT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'SELECT'
) AND
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'INSERT'
) AS publication_append,
NOT has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'UPDATE'
) AND NOT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_publications',
'DELETE'
) AS publication_no_rewrite,
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'SELECT'
) AND
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'INSERT'
) AS head_append,
NOT has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'UPDATE'
) AND NOT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_heads',
'DELETE'
) AS head_no_rewrite`,
),
]);
assert.deepEqual(privileges[0].rows[0], {
publication_select: true,
publication_insert: false,
head_select: true,
head_insert: false,
});
assert.deepEqual(privileges[1].rows[0], {
publication_append: true,
publication_no_rewrite: true,
head_append: true,
head_no_rewrite: true,
});
await assertSqlState(
runtimePool.query(
`INSERT INTO "ql3_ai"."model_price_catalog_publications"
(provider)
VALUES ('forbidden')`,
),
'42501',
);
await assertSqlState(
adminPool.query(
`UPDATE "ql3_ai"."model_price_catalog_heads"
SET action = action
WHERE provider = $1 AND model = $2`,
[provider, model],
),
'42501',
);
} finally {
await runtimePool.end();
await adminPool.end();
await migrationPool.end();
}
});
test('PostgreSQL atomically fences authorized catalog management and its ACL', async () => {
const suffix = randomUUID();
const provider = `authorized-${suffix}`;
const model = 'managed-price-catalog';
const now = Date.now();
const migrationPool = pool(
migrationConnectionString,
'ql3-ai-price-authorization-migration-test',
);
const adminPool = pool(
adminConnectionString,
'ql3-ai-price-authorization-admin-test',
);
const runtimePool = pool(
runtimeConnectionString,
'ql3-ai-price-authorization-runtime-test',
);
const repository = new PostgresModelPriceCatalogRepository(adminPool);
const service = createModelPriceCatalogManagementService(repository, {
decisionMode: 'separation_of_duty',
authorizer: {
async authorize() {
return createModelPriceCatalogPolicyDecision({
effect: 'allow',
revision: 'integration-platform-policy-1',
reasons: ['catalog_operator'],
});
},
},
now: () => now,
});
const principal = (userId) => ({
subject: { type: 'user', id: userId },
authenticationId: `auth-${userId}`,
authenticatedAtMs: now - 1_000,
expiresAtMs: now + 60_000,
assurance: 'multi_factor',
});
const publishRequest = {
authorizationId: `authorize-publish-${suffix}`,
requestId: `request-publish-${suffix}`,
mutationId: `publish-${suffix}`,
provider,
model,
principal: principal('integration-publisher'),
priceRevision: 'price-1',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
};
const activateRequest = {
authorizationId: `authorize-activate-${suffix}`,
requestId: `request-activate-${suffix}`,
mutationId: `activate-${suffix}`,
provider,
model,
principal: principal('integration-reviewer'),
expectedGeneration: 0,
expectedHeadDigest: null,
action: 'activate',
priceRevision: 'price-1',
};
try {
await runPostgresMigrations({ pool: migrationPool });
await migratePostgresModelInvocationFeature(migrationPool);
const publication = await service.publish(publishRequest);
assert.equal(publication.status, 'created');
assert.deepEqual(await service.publish(publishRequest), {
status: 'existing',
publication: publication.publication,
authorization: publication.authorization,
});
await assert.rejects(
service.transition({
...activateRequest,
principal: principal('integration-publisher'),
}),
ModelPriceCatalogManagementSeparationOfDutyError,
);
const activation = await service.transition(activateRequest);
assert.equal(activation.head.activePriceRevision, 'price-1');
assert.equal(
activation.authorization.principal.subject.id,
'integration-reviewer',
);
assert.deepEqual(
await repository.findAuthorization(activateRequest.authorizationId),
activation.authorization,
);
const runtimePrivileges = await runtimePool.query(
`SELECT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'SELECT'
) AS authorization_select,
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'INSERT'
) AS authorization_insert`,
);
assert.deepEqual(runtimePrivileges.rows[0], {
authorization_select: false,
authorization_insert: false,
});
const adminPrivileges = await adminPool.query(
`SELECT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'SELECT'
) AND
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'INSERT'
) AS authorization_append,
NOT has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'UPDATE'
) AND NOT
has_table_privilege(
current_user,
'ql3_ai.model_price_catalog_authorizations',
'DELETE'
) AS authorization_no_rewrite`,
);
assert.deepEqual(adminPrivileges.rows[0], {
authorization_append: true,
authorization_no_rewrite: true,
});
await assertSqlState(
runtimePool.query(
`SELECT authorization_id
FROM "ql3_ai"."model_price_catalog_authorizations"
LIMIT 1`,
),
'42501',
);
await assertSqlState(
adminPool.query(
`UPDATE "ql3_ai"."model_price_catalog_authorizations"
SET operation = operation
WHERE authorization_id = $1`,
[activation.authorization.authorizationId],
),
'42501',
);
} finally {
await runtimePool.end();
await adminPool.end();
await migrationPool.end();
}
});
}
@@ -0,0 +1,192 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
ModelProviderCredentialManagementAuditAuthorizationFenceConflictError,
ModelProviderCredentialManagementAuditUnavailableError,
PostgresModelProviderCredentialManagementAuditQueryRepository,
} = require('../dist/model-provider-credential/postgresModelProviderCredentialManagementAuditQuery.js');
const QUERY_ID = '219f7094-a853-4f3b-82ab-dfa08e6bd1c3';
function auditRow({
eventId,
requestId,
operationId,
occurredAtMs,
authenticationId = 'authentication-1',
}) {
return {
eventId,
requestId,
operationId,
projectId: 'project-a',
subjectType: 'user',
subjectId: 'owner-a',
authenticationId,
outcome: 'allowed',
reasons: ['project_owner'],
projectVersion: '3',
bindingVersion: '7',
occurredAtMs: String(occurredAtMs),
};
}
function authorized(overrides = {}) {
return {
query: {
schemaVersion: 1,
queryId: QUERY_ID,
requestId: 'audit-request-1',
projectId: 'project-a',
limit: 2,
...overrides,
},
actor: { type: 'user', id: 'owner-a' },
fence: { projectVersion: 3, bindingVersion: 7 },
audit: {
eventId: QUERY_ID,
requestId: 'audit-request-1',
operationId: 'model_provider_credential.audit.list',
projectId: 'project-a',
subject: { type: 'user', id: 'owner-a' },
authenticationId: 'authentication-1',
outcome: 'allowed',
reasons: ['project_owner'],
fence: { projectVersion: 3, bindingVersion: 7 },
occurredAtMs: 2_000,
},
};
}
function fixture(options = {}) {
const state = {
queries: [],
accessAudit: options.accessAudit ?? null,
accessAuditInserts: 0,
commitResponseLost: false,
};
const records = [
auditRow({
eventId: '319f7094-a853-4f3b-82ab-dfa08e6bd1c4',
requestId: 'request-revoke-1',
operationId: 'model_provider_credential.revoke',
occurredAtMs: 1_003,
}),
auditRow({
eventId: '119f7094-a853-4f3b-82ab-dfa08e6bd1c2',
requestId: 'request-bind-2',
operationId: 'model_provider_credential.bind',
occurredAtMs: 1_002,
}),
auditRow({
eventId: '019f7094-a853-4f3b-82ab-dfa08e6bd1c1',
requestId: 'request-bind-1',
operationId: 'model_provider_credential.bind',
occurredAtMs: 1_001,
}),
];
const client = {
async query(statement, values = []) {
state.queries.push({ statement, values });
if (statement.includes('FROM "ql3"."projects"')) {
return {
rows: [
{ status: 'active', version: String(options.projectVersion ?? 3) },
],
};
}
if (statement.includes('FROM "ql3"."project_role_bindings"')) {
return { rows: [{ state: 'active', version: '7' }] };
}
if (
statement.includes('FROM "ql3"."security_audit_events"') &&
statement.includes('WHERE event_id = $1')
) {
return { rows: state.accessAudit ? [state.accessAudit] : [] };
}
if (statement.includes('operation_id IN')) {
return { rows: records };
}
if (statement.includes('INSERT INTO "ql3"."security_audit_events"')) {
state.accessAuditInserts += 1;
state.accessAudit = auditRow({
eventId: values[0],
requestId: values[1],
operationId: values[2],
occurredAtMs: values[11],
});
return { rows: [] };
}
if (
statement === 'COMMIT' &&
options.loseCommitResponse &&
!state.commitResponseLost
) {
state.commitResponseLost = true;
const error = new Error('injected commit response loss');
error.code = 'ECONNRESET';
throw error;
}
return { rows: [] };
},
release() {},
};
return {
state,
repository:
new PostgresModelProviderCredentialManagementAuditQueryRepository({
async connect() {
return client;
},
}),
};
}
test('atomically audits and pages only content-free credential management events', async () => {
const { repository, state } = fixture();
const page = await repository.listAuthorized(authorized());
assert.equal(page.projectId, 'project-a');
assert.equal(page.records.length, 2);
assert.deepEqual(page.nextCursor, {
occurredAtMs: 1_002,
eventId: '119f7094-a853-4f3b-82ab-dfa08e6bd1c2',
});
assert.equal(state.accessAuditInserts, 1);
assert.match(
state.queries.find(({ statement }) => statement.includes('operation_id IN'))
.statement,
/model_provider_credential\.bind[\s\S]+model_provider_credential\.revoke/,
);
assert.doesNotMatch(
JSON.stringify(page),
/secretRef|bindingDigest|transitionDigest|authenticationId|openai/i,
);
});
test('converges an audit COMMIT response loss without duplicate access audit', async () => {
const { repository, state } = fixture({ loseCommitResponse: true });
await assert.rejects(
repository.listAuthorized(authorized()),
ModelProviderCredentialManagementAuditUnavailableError,
);
const replay = await repository.listAuthorized(authorized());
assert.equal(replay.records.length, 2);
assert.equal(state.accessAuditInserts, 1);
assert.equal(state.commitResponseLost, true);
});
test('rejects a stale Project fence before reading or auditing events', async () => {
const { repository, state } = fixture({ projectVersion: 4 });
await assert.rejects(
repository.listAuthorized(authorized()),
ModelProviderCredentialManagementAuditAuthorizationFenceConflictError,
);
assert.equal(
state.queries.some(({ statement }) =>
statement.includes('operation_id IN'),
),
false,
);
assert.equal(state.accessAuditInserts, 0);
});
@@ -0,0 +1,192 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
PostgresModelProviderCredentialManagementIdentityLedgerConflictError,
PostgresModelProviderCredentialManagementIdentityLedgerRepository,
PostgresModelProviderCredentialManagementIdentityLedgerUnavailableError,
PostgresModelProviderCredentialManagerNotReadyError,
assertPostgresModelProviderCredentialManagerReady,
} = require('../dist/model-provider-credential/postgresModelProviderCredentialManagementIdentityLedger.js');
const {
POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
postgresModelInvocationMigrationDefinition,
} = require('@qinglong/ai/model-invocation-migration');
function snapshot(generation, overrides = {}) {
return {
schemaVersion: 1,
generation,
digest: String.fromCharCode(64 + generation).repeat(43),
issuer: 'https://identity.example.test/',
audience: 'qinglong3-model-provider-credential-management',
activeKeyIds: [`issuer-key-${generation}`],
revokedKeyIds:
generation === 1
? []
: Array.from(
{ length: generation - 1 },
(_, index) => `issuer-key-${index + 1}`,
),
...overrides,
};
}
function fixture() {
let state;
let loseCommitResponse = false;
const queries = [];
let releases = 0;
const client = {
async query(text, values = []) {
queries.push({ text, values });
if (text.startsWith('INSERT')) {
state ??= {
generation: values[1],
digest: values[2],
issuer: values[3],
audience: values[4],
activeKeyIds: JSON.parse(values[5]),
revokedKeyIds: JSON.parse(values[6]),
};
} else if (text.startsWith('SELECT')) {
return { rows: state ? [{ ...state }] : [] };
} else if (text.startsWith('UPDATE')) {
state = {
...state,
generation: values[1],
digest: values[2],
activeKeyIds: JSON.parse(values[3]),
revokedKeyIds: JSON.parse(values[4]),
};
} else if (text === 'COMMIT' && loseCommitResponse) {
loseCommitResponse = false;
throw new Error('response lost after commit');
}
return { rows: [] };
},
release() {
releases += 1;
},
};
return {
repository:
new PostgresModelProviderCredentialManagementIdentityLedgerRepository({
async connect() {
return client;
},
async query() {
throw new Error('pool query must not bypass transaction client');
},
}),
queries,
state: () => state,
releases: () => releases,
loseNextCommitResponse() {
loseCommitResponse = true;
},
};
}
test('serializes exact identity observation and forward-only rotation', async () => {
const value = fixture();
await value.repository.observe(snapshot(1));
await value.repository.observe(snapshot(1));
await value.repository.observe(snapshot(2));
assert.deepEqual(value.state(), {
generation: 2,
digest: 'B'.repeat(43),
issuer: 'https://identity.example.test/',
audience: 'qinglong3-model-provider-credential-management',
activeKeyIds: ['issuer-key-2'],
revokedKeyIds: ['issuer-key-1'],
});
const insert = value.queries.find(({ text }) => text.startsWith('INSERT'));
assert.equal(insert.values[0], 'model-provider-credential-management');
assert.match(insert.text, /clock_timestamp\(\)/);
assert.equal(value.releases(), 3);
});
test('rejects rollback, trust-domain drift and implicit key removal', async () => {
const value = fixture();
await value.repository.observe(snapshot(2));
await assert.rejects(
value.repository.observe(snapshot(1)),
PostgresModelProviderCredentialManagementIdentityLedgerConflictError,
);
await assert.rejects(
value.repository.observe(
snapshot(3, { issuer: 'https://other.example.test/' }),
),
PostgresModelProviderCredentialManagementIdentityLedgerConflictError,
);
await assert.rejects(
value.repository.observe(
snapshot(3, { activeKeyIds: ['issuer-key-3'], revokedKeyIds: [] }),
),
PostgresModelProviderCredentialManagementIdentityLedgerConflictError,
);
});
test('converges a lost commit response without accepting malformed keys', async () => {
const value = fixture();
value.loseNextCommitResponse();
await assert.rejects(
value.repository.observe(snapshot(1)),
PostgresModelProviderCredentialManagementIdentityLedgerUnavailableError,
);
await value.repository.observe(snapshot(1));
assert.equal(value.state().generation, 1);
await assert.rejects(
value.repository.observe(
snapshot(2, { activeKeyIds: ['issuer-key-2', 'issuer-key-2'] }),
),
TypeError,
);
});
test('readiness binds exact migration history and least-privilege primary authority', async () => {
const history = postgresModelInvocationMigrationDefinition.migrations.map(
({ id, checksum }) => ({
migrationId: id,
streamId: POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
dialect: 'postgresql',
checksum,
}),
);
const queries = [];
const report = await assertPostgresModelProviderCredentialManagerReady({
async query(text) {
queries.push(text);
return queries.length === 1
? { rows: history }
: {
rows: [
{
currentUser: 'ql3_ai_credential_manager',
writablePrimary: true,
managerAuthority: true,
leastPrivilege: true,
},
],
};
},
});
assert.equal(report.ready, true);
assert.equal(report.migrationIds.at(-1).startsWith('pg-9017-'), true);
assert.match(
queries[1],
/model_provider_credential_management_identity_keyset_ledger/,
);
assert.match(queries[1], /model_provider_credential_test_plans/);
assert.match(queries[1], /model_provider_credential_test_quota_buckets/);
assert.match(queries[1], /model_invocation_prompt_output_artifacts/);
await assert.rejects(
assertPostgresModelProviderCredentialManagerReady({
async query() {
return { rows: [] };
},
}),
PostgresModelProviderCredentialManagerNotReadyError,
);
});
@@ -0,0 +1,280 @@
const assert = require('node:assert/strict');
const { randomUUID } = require('node:crypto');
const test = require('node:test');
const {
createModelProviderCredentialTestAllowlist,
createModelProviderCredentialTestPlan,
} = require('../dist/model-provider-credential/modelProviderCredentialTestConnection.js');
const {
MODEL_PROVIDER_CREDENTIAL_TEST_PLAN_OPERATION_ID,
ModelProviderCredentialTestPlanAuthorizationFenceConflictError,
ModelProviderCredentialTestPlanQuotaExceededError,
ModelProviderCredentialTestPlanUnavailableError,
PostgresModelProviderCredentialTestPlanRepository,
} = require('../dist/model-provider-credential/postgresModelProviderCredentialTestConnection.js');
function plan(overrides = {}) {
const endpoint = createModelProviderCredentialTestAllowlist({
revision: 'catalog-v1',
providers: [
{
provider: 'openai-compatible',
adapter: 'openai-compatible',
baseUrl: 'https://provider.example.test/v1/',
revision: 'endpoint-v1',
deadlineMs: 5_000,
maxResponseBytes: 64 * 1_024,
maxModels: 64,
maxCostMicrousd: 0,
retryLimit: 0,
},
],
}).providers[0];
return createModelProviderCredentialTestPlan({
testId: randomUUID(),
requestId: `request-${randomUUID()}`,
projectId: 'project-a',
provider: endpoint.provider,
endpoint,
requestedBy: { type: 'user', id: 'owner-a' },
fence: { projectVersion: 1, bindingVersion: 1 },
plannedAtMs: 100,
expiresAtMs: 60_100,
...overrides,
});
}
function authorized(value) {
return {
plan: value,
audit: {
eventId: value.testId,
requestId: value.requestId,
operationId: MODEL_PROVIDER_CREDENTIAL_TEST_PLAN_OPERATION_ID,
projectId: value.projectId,
subject: value.requestedBy,
authenticationId: 'strong-authentication-1',
outcome: 'allowed',
reasons: ['project_owner'],
fence: value.fence,
occurredAtMs: value.plannedAtMs,
},
};
}
function fixture({ projectVersion = 1, bindingVersion = 1 } = {}) {
const state = {
plans: new Map(),
audits: new Map(),
quota: { consumed: 0, receipts: new Set() },
};
let snapshot;
let loseCommit = false;
const client = {
async query(text, values = []) {
if (text.startsWith('BEGIN')) {
snapshot = structuredClone(state);
return { rows: [] };
}
if (text.includes('pg_advisory_xact_lock')) return { rows: [{}] };
if (text.includes('FROM "ql3"."projects"')) {
return { rows: [{ status: 'active', version: projectVersion }] };
}
if (text.includes('FROM "ql3"."project_role_bindings"')) {
return { rows: [{ state: 'active', version: bindingVersion }] };
}
if (
text.includes('FROM "ql3_ai"."model_provider_credential_test_plans"')
) {
const [testId, requestedProjectId, requestId] = values;
const rows = [...state.plans.values()]
.filter(
(stored) =>
stored.testId === testId ||
(stored.projectId === requestedProjectId &&
stored.requestId === requestId),
)
.map((stored) => ({ planJson: stored }));
return { rows };
}
if (text.includes('FROM "ql3"."security_audit_events"')) {
const stored = state.audits.get(values[0]);
return { rows: stored ? [stored] : [] };
}
if (text.includes('receipt_ids ? $3::text AS "hasReceipt"')) {
return {
rows:
state.quota.consumed === 0
? []
: [{ hasReceipt: state.quota.receipts.has(values[2]) }],
};
}
if (
text.startsWith('WITH database_clock AS (') &&
text.includes('INSERT INTO')
) {
const receipt = values[2];
const limit = values[4];
if (
!state.quota.receipts.has(receipt) &&
state.quota.consumed >= limit
) {
return { rows: [] };
}
if (!state.quota.receipts.has(receipt)) {
state.quota.receipts.add(receipt);
state.quota.consumed += 1;
}
return {
rows: [
{
consumedCount: state.quota.consumed,
resetAtMs: 60_100,
observedAtMs: 100,
},
],
};
}
if (
text.startsWith('WITH database_clock AS (') &&
text.includes('SELECT consumed_count')
) {
return {
rows: [
{
consumedCount: state.quota.consumed,
resetAtMs: 60_100,
observedAtMs: 100,
},
],
};
}
if (
text.startsWith(
'INSERT INTO "ql3_ai"."model_provider_credential_test_plans"',
)
) {
state.plans.set(values[0], JSON.parse(values[20]));
return { rows: [] };
}
if (text.startsWith('INSERT INTO "ql3"."security_audit_events"')) {
state.audits.set(values[0], {
eventId: values[0],
requestId: values[1],
operationId: values[2],
projectId: values[3],
subjectType: values[4],
subjectId: values[5],
authenticationId: values[6],
outcome: values[7],
reasons: JSON.parse(values[8]),
projectVersion: values[9],
bindingVersion: values[10],
occurredAtMs: values[11],
});
return { rows: [] };
}
if (text === 'COMMIT') {
snapshot = undefined;
if (loseCommit) {
loseCommit = false;
const error = new Error('lost commit response');
error.code = 'ECONNRESET';
throw error;
}
return { rows: [] };
}
if (text === 'ROLLBACK') {
if (snapshot) {
state.plans = snapshot.plans;
state.audits = snapshot.audits;
state.quota = snapshot.quota;
}
snapshot = undefined;
return { rows: [] };
}
throw new Error(`unexpected query: ${text}`);
},
release() {},
};
return {
repository: new PostgresModelProviderCredentialTestPlanRepository(
{
async connect() {
return client;
},
},
{ quotaWindowMs: 60_000, quotaLimit: 2 },
),
state: () => state,
loseNextCommitResponse() {
loseCommit = true;
},
};
}
test('atomically consumes quota, stores a plan and writes allowed audit', async () => {
const value = fixture();
const candidate = plan();
const created = await value.repository.createAuthorized(
authorized(candidate),
);
assert.equal(created.status, 'created');
assert.equal(value.state().plans.size, 1);
assert.equal(value.state().audits.size, 1);
assert.equal(value.state().quota.consumed, 1);
assert.equal(value.state().quota.receipts.has(candidate.testId), true);
});
test('converges a COMMIT response loss without consuming quota twice', async () => {
const value = fixture();
const candidate = plan();
value.loseNextCommitResponse();
await assert.rejects(
value.repository.createAuthorized(authorized(candidate)),
ModelProviderCredentialTestPlanUnavailableError,
);
const replay = await value.repository.createAuthorized(authorized(candidate));
assert.equal(replay.status, 'existing');
assert.equal(value.state().quota.consumed, 1);
});
test('replays the stored plan when API retry observes a later clock', async () => {
const value = fixture();
const candidate = plan();
await value.repository.createAuthorized(authorized(candidate));
const retried = plan({
testId: candidate.testId,
requestId: candidate.requestId,
projectId: candidate.projectId,
provider: candidate.provider,
endpoint: candidate.endpoint,
requestedBy: candidate.requestedBy,
fence: candidate.fence,
plannedAtMs: candidate.plannedAtMs + 25,
expiresAtMs: candidate.expiresAtMs + 25,
});
const replay = await value.repository.createAuthorized(authorized(retried));
assert.equal(replay.status, 'existing');
assert.deepEqual(replay.plan, candidate);
assert.equal(value.state().quota.consumed, 1);
});
test('fails a stale fence and quota excess before creating another plan', async () => {
const stale = fixture({ projectVersion: 2 });
await assert.rejects(
stale.repository.createAuthorized(authorized(plan())),
ModelProviderCredentialTestPlanAuthorizationFenceConflictError,
);
assert.equal(stale.state().quota.consumed, 0);
const limited = fixture();
await limited.repository.createAuthorized(authorized(plan()));
await limited.repository.createAuthorized(authorized(plan()));
await assert.rejects(
limited.repository.createAuthorized(authorized(plan())),
ModelProviderCredentialTestPlanQuotaExceededError,
);
assert.equal(limited.state().plans.size, 2);
});
@@ -0,0 +1,303 @@
const assert = require('node:assert/strict');
const { randomUUID } = require('node:crypto');
const test = require('node:test');
const {
createModelProviderCredentialTestAllowlist,
createModelProviderCredentialTestPlan,
createModelProviderCredentialTestResult,
} = require('../dist/model-provider-credential/modelProviderCredentialTestConnection.js');
const {
POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
postgresModelInvocationMigrationDefinition,
} = require('@qinglong/ai/model-invocation-migration');
const {
ModelProviderCredentialTestExecutionRejectedError,
ModelProviderCredentialTestExecutionUnavailableError,
PostgresModelProviderCredentialTestExecutionRepository,
PostgresModelProviderCredentialTesterNotReadyError,
assertPostgresModelProviderCredentialTesterReady,
} = require('../dist/model-provider-credential/postgresModelProviderCredentialTestConnection.js');
function contractFixture({ observedAtMs = 200 } = {}) {
const allowlist = createModelProviderCredentialTestAllowlist({
revision: 'catalog-v1',
providers: [
{
provider: 'openai-compatible',
adapter: 'openai-compatible',
baseUrl: 'https://provider.example.test/v1/',
revision: 'endpoint-v1',
deadlineMs: 5_000,
maxResponseBytes: 64 * 1_024,
maxModels: 64,
maxCostMicrousd: 0,
retryLimit: 0,
},
],
});
const plan = createModelProviderCredentialTestPlan({
testId: randomUUID(),
requestId: `request-${randomUUID()}`,
projectId: 'project-a',
provider: 'openai-compatible',
endpoint: allowlist.providers[0],
requestedBy: { type: 'user', id: 'owner-a' },
fence: { projectVersion: 1, bindingVersion: 1 },
plannedAtMs: 100,
expiresAtMs: 60_100,
});
const state = {
executions: new Map(),
results: new Map(),
executionInserts: 0,
resultInserts: 0,
};
let snapshot;
let loseCommit = false;
const client = {
async query(text, values = []) {
if (text.startsWith('BEGIN')) {
snapshot = structuredClone(state);
return { rows: [] };
}
if (text.includes('pg_advisory_xact_lock')) return { rows: [{}] };
if (
text.startsWith('WITH database_clock AS (') &&
text.includes('model_provider_credential_test_plans')
) {
return values[0] === plan.testId
? { rows: [{ planJson: plan, observedAtMs }] }
: { rows: [] };
}
if (
text.startsWith('SELECT execution.execution_json') &&
text.includes('model_provider_credential_test_executions')
) {
const execution = state.executions.get(values[0]);
if (!execution) return { rows: [] };
return {
rows: [
{
executionJson: execution,
resultJson: state.results.get(execution.executionId) ?? null,
},
],
};
}
if (
text.startsWith(
'INSERT INTO "ql3_ai"."model_provider_credential_test_executions"',
)
) {
const execution = JSON.parse(values[5]);
state.executions.set(execution.testId, execution);
state.executionInserts += 1;
return { rows: [] };
}
if (
text.startsWith(
'INSERT INTO "ql3_ai"."model_provider_credential_test_results"',
)
) {
const result = JSON.parse(values[8]);
state.results.set(result.executionId, result);
state.resultInserts += 1;
return { rows: [] };
}
if (text === 'COMMIT') {
snapshot = undefined;
if (loseCommit) {
loseCommit = false;
const error = new Error('lost commit response');
error.code = 'ECONNRESET';
throw error;
}
return { rows: [] };
}
if (text === 'ROLLBACK') {
if (snapshot) {
state.executions = snapshot.executions;
state.results = snapshot.results;
state.executionInserts = snapshot.executionInserts;
state.resultInserts = snapshot.resultInserts;
}
snapshot = undefined;
return { rows: [] };
}
throw new Error(`unexpected query: ${text}`);
},
release() {},
};
return {
allowlist,
plan,
repository: new PostgresModelProviderCredentialTestExecutionRepository({
async connect() {
return client;
},
}),
state: () => state,
loseNextCommitResponse() {
loseCommit = true;
},
};
}
test('commits an immutable execution intent before provider I/O is allowed', async () => {
const value = contractFixture();
const input = {
executionId: randomUUID(),
testId: value.plan.testId,
allowlist: value.allowlist,
};
const created = await value.repository.beginExecution(input);
assert.equal(created.status, 'created');
assert.equal(created.result, null);
assert.equal(value.state().executionInserts, 1);
const replay = await value.repository.beginExecution(input);
assert.equal(replay.status, 'existing');
assert.equal(replay.result, null);
assert.equal(value.state().executionInserts, 1);
});
test('returns existing after a begin COMMIT response loss so callers cannot reexecute', async () => {
const value = contractFixture();
const input = {
executionId: randomUUID(),
testId: value.plan.testId,
allowlist: value.allowlist,
};
value.loseNextCommitResponse();
await assert.rejects(
value.repository.beginExecution(input),
ModelProviderCredentialTestExecutionUnavailableError,
);
const recovery = await value.repository.beginExecution(input);
assert.equal(recovery.status, 'existing');
assert.equal(recovery.result, null);
assert.equal(value.state().executionInserts, 1);
});
test('rejects expired plans and exact allowlist drift before inserting intent', async () => {
const expired = contractFixture({ observedAtMs: 60_100 });
await assert.rejects(
expired.repository.beginExecution({
executionId: randomUUID(),
testId: expired.plan.testId,
allowlist: expired.allowlist,
}),
ModelProviderCredentialTestExecutionRejectedError,
);
assert.equal(expired.state().executionInserts, 0);
const drifted = contractFixture();
const changedAllowlist = createModelProviderCredentialTestAllowlist({
revision: 'catalog-v2',
providers: [
{
provider: 'openai-compatible',
adapter: 'openai-compatible',
baseUrl: 'https://provider.example.test/v2/',
revision: 'endpoint-v2',
deadlineMs: 5_000,
maxResponseBytes: 64 * 1_024,
maxModels: 64,
maxCostMicrousd: 0,
retryLimit: 0,
},
],
});
await assert.rejects(
drifted.repository.beginExecution({
executionId: randomUUID(),
testId: drifted.plan.testId,
allowlist: changedAllowlist,
}),
ModelProviderCredentialTestExecutionRejectedError,
);
assert.equal(drifted.state().executionInserts, 0);
});
test('recovers a result COMMIT response loss by exact durable replay', async () => {
const value = contractFixture();
const executionId = randomUUID();
const started = await value.repository.beginExecution({
executionId,
testId: value.plan.testId,
allowlist: value.allowlist,
});
const result = createModelProviderCredentialTestResult({
executionId,
testId: value.plan.testId,
planDigest: started.plan.planDigest,
outcome: 'reachable',
modelCount: 3,
durationMs: 40,
completedAtMs: 240,
});
value.loseNextCommitResponse();
await assert.rejects(
value.repository.complete(result),
ModelProviderCredentialTestExecutionUnavailableError,
);
const recovery = await value.repository.complete(result);
assert.equal(recovery.status, 'existing');
assert.deepEqual(recovery.result, result);
assert.equal(value.state().resultInserts, 1);
});
test('tester readiness freezes migration history and least privilege', async () => {
const history = postgresModelInvocationMigrationDefinition.migrations.map(
({ id, checksum }) => ({
migrationId: id,
streamId: POSTGRES_MODEL_INVOCATION_MIGRATION_STREAM_ID,
dialect: 'postgresql',
checksum,
}),
);
const ready = await assertPostgresModelProviderCredentialTesterReady({
async query(text) {
if (text.includes('FROM "ql3_ai"."ai_schema_migrations"')) {
return { rows: history };
}
return {
rows: [
{
currentUser: 'ql3_ai_credential_tester',
writablePrimary: true,
testerAuthority: true,
leastPrivilege: true,
},
],
};
},
});
assert.equal(ready.ready, true);
assert.equal(
ready.migrationIds.at(-1),
'pg-9017-ai-plugin-package-prompt-product-authorization',
);
await assert.rejects(
assertPostgresModelProviderCredentialTesterReady({
async query(text) {
if (text.includes('FROM "ql3_ai"."ai_schema_migrations"')) {
return { rows: history };
}
return {
rows: [
{
currentUser: 'ql3_ai_credential_tester',
writablePrimary: true,
testerAuthority: true,
leastPrivilege: false,
},
],
};
},
}),
PostgresModelProviderCredentialTesterNotReadyError,
);
});
@@ -0,0 +1,443 @@
const assert = require('node:assert/strict');
const { generateKeyPairSync, randomUUID } = require('node:crypto');
const { createRequire } = require('node:module');
const path = require('node:path');
const test = require('node:test');
const {
createInitialPluginPackageAutomationPublication,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
const {
createPluginPackagePublisherTrustSnapshot,
} = require('@qinglong/runtime-core/plugin-package-publisher-trust');
const {
activateInstall,
pluginPackageTaskReconciliationFixture,
publisherProvenanceInstallRepository,
} = require('../../../test/contracts/pluginPackageTaskReconciliationRepositoryContract.cjs');
const {
migratePostgresModelInvocationFeature,
} = require('@qinglong/ai/model-invocation-migration');
const {
bootstrapPostgresPluginPackagePromptApplication,
} = require('../dist/prompt/postgresPluginPackagePromptApplication.js');
const migrationConnectionString =
process.env.QL3_TEST_POSTGRES_MIGRATION_URL ??
process.env.QL3_TEST_POSTGRES_URL;
const runtimeConnectionString =
process.env.QL3_TEST_POSTGRES_RUNTIME_URL ?? migrationConnectionString;
const packageExecutorConnectionString =
process.env.QL3_TEST_POSTGRES_PACKAGE_EXECUTOR_URL ??
migrationConnectionString;
if (!migrationConnectionString) {
test('PostgreSQL Package Prompt integration requires QL3_TEST_POSTGRES_URL', {
skip: true,
});
} else {
const clusterRequire = createRequire(
path.resolve(__dirname, '../../ql3-cluster-postgres/package.json'),
);
const { Pool } = clusterRequire('pg');
const {
runPostgresMigrations,
} = require('../../ql3-cluster-postgres/dist/migration/migration.js');
const {
PostgresPluginPackageInstallRepository,
} = require('../../ql3-cluster-postgres/dist/plugin-package/installation/pluginPackageInstallRepository.js');
const {
PostgresPluginPackagePublisherProvenanceRepository,
} = require('../../ql3-cluster-postgres/dist/plugin-package/publisher/pluginPackagePublisherProvenanceRepository.js');
const {
PostgresPluginPackagePublisherTrustAuthorityRepository,
} = require('../../ql3-cluster-postgres/dist/plugin-package/publisher/pluginPackagePublisherTrustAuthorityRepository.js');
const {
PostgresPluginPackageMaterializedRevisionRepository,
} = require('../../ql3-cluster-postgres/dist/plugin-package/installation/pluginPackageMaterializedRevisionRepository.js');
const {
PostgresPluginPackageAutomationPublicationRepository,
} = require('../../ql3-cluster-postgres/dist/plugin-package/publication/pluginPackageAutomationPublicationRepository.js');
function pool(connectionString, applicationName) {
return new Pool({
connectionString,
ssl: false,
max: 4,
application_name: applicationName,
});
}
test('PostgreSQL executes and replays one content-free Package Prompt', async () => {
const suffix = `${process.pid}-${Date.now()}`;
const credentialId = `prompt-${suffix}`;
const fixture = pluginPackageTaskReconciliationFixture(
`ai-prompt-${suffix}`,
{
profile: 'cluster-control',
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}} for {{audience}}.',
parameters: [
{ name: 'audience', required: false },
{ name: 'subject', required: true },
],
},
],
},
);
const publication = createInitialPluginPackageAutomationPublication(
fixture.revision,
fixture.registry,
20_000,
);
const migrationPool = pool(
migrationConnectionString,
'ql3-ai-prompt-migration-test',
);
const executorPool = pool(
packageExecutorConnectionString,
'ql3-ai-prompt-package-executor-test',
);
const runtimePool = pool(
runtimeConnectionString,
'ql3-ai-prompt-runtime-test',
);
let application;
try {
await runPostgresMigrations({ pool: migrationPool });
await migratePostgresModelInvocationFeature(migrationPool);
const keyPair = generateKeyPairSync('ed25519');
const trust = createPluginPackagePublisherTrustSnapshot([
{
publisher: 'packages.contract.qinglong.dev',
keyId: 'contract-key-1',
publicKeyPem: keyPair.publicKey.export({
type: 'spki',
format: 'pem',
}),
notBeforeMs: 0,
notAfterMs: 100_000,
},
]);
await new PostgresPluginPackagePublisherTrustAuthorityRepository(
migrationPool,
).observeSnapshot({
authorityId: 'cluster',
observedBy: `ai-prompt-${suffix}`,
observedAtMs: 1,
snapshot: trust,
});
await migrationPool.query(
`INSERT INTO "ql3"."projects" (
id, name, slug, status, version, created_at_ms, updated_at_ms
) VALUES ($1, $1, $1, 'active', 1, 1, 1)
ON CONFLICT (id) DO NOTHING`,
[fixture.projectId],
);
await migrationPool.query(
`INSERT INTO "ql3"."identity_subjects" (
subject_type, subject_id, status, version, created_at_ms, updated_at_ms
) VALUES ('user', 'user-a', 'active', 1, 1, 1)
ON CONFLICT (subject_type, subject_id) DO UPDATE
SET status = 'active', version = "ql3"."identity_subjects".version + 1,
updated_at_ms = 1`,
);
await migrationPool.query(
`INSERT INTO "ql3"."api_credentials" (
credential_id, version, state, subject_type, subject_id,
pepper_key_id, secret_digest, created_at_ms, not_before_at_ms,
expires_at_ms
) VALUES ($1, 1, 'active', 'user', 'user-a', 'integration-v1',
$2, 1, 1, 9999999999999)`,
[credentialId, 'a'.repeat(64)],
);
await migrationPool.query(
`INSERT INTO "ql3"."project_role_bindings" (
project_id, subject_type, subject_id, version, state, role,
mutation_id, changed_by_type, changed_by_id, created_at_ms
) VALUES ($1, 'user', 'user-a', 1, 'active', 'operator',
$2, 'system', 'integration-test', 1)
ON CONFLICT (project_id, subject_type, subject_id, version)
DO NOTHING`,
[fixture.projectId, `ai-prompt-user-${suffix}`],
);
await activateInstall(
publisherProvenanceInstallRepository(
new PostgresPluginPackageInstallRepository(executorPool),
new PostgresPluginPackagePublisherProvenanceRepository(executorPool),
),
fixture,
);
await new PostgresPluginPackageMaterializedRevisionRepository(
executorPool,
fixture.registry,
).publish(fixture.revision);
await new PostgresPluginPackageAutomationPublicationRepository(
executorPool,
).publish(publication);
const privileges = await runtimePool.query(
`SELECT
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_admissions', 'SELECT,INSERT'
) AS admission_write,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_admissions', 'UPDATE'
) AS admission_update,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_finalizations', 'SELECT,INSERT'
) AS finalization_write,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_finalizations', 'DELETE'
) AS finalization_delete,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_output_artifacts', 'SELECT,INSERT'
) AS output_artifact_write,
has_table_privilege(
current_user,
'ql3_ai.model_invocation_prompt_output_artifacts', 'UPDATE,DELETE'
) AS output_artifact_mutation,
has_function_privilege(
current_user,
'ql3_ai.plugin_package_prompt_admission_snapshot(varchar,varchar,character,varchar,varchar,integer,integer)',
'EXECUTE'
) AS snapshot_execute`,
);
assert.deepEqual(privileges.rows[0], {
admission_write: true,
admission_update: false,
finalization_write: true,
finalization_delete: false,
output_artifact_write: true,
output_artifact_mutation: false,
snapshot_execute: true,
});
let providerCalls = 0;
application = await bootstrapPostgresPluginPackagePromptApplication({
enabled: true,
async openDatabase() {
return { pool: runtimePool, async close() {} };
},
async loadProviders() {
return {
providers: [
{
type: 'openai-compatible',
async listModels() {
return [{ id: 'vendor/model-a' }];
},
async generate() {
providerCalls += 1;
return {
provider: 'openai-compatible',
model: 'vendor/model-a',
text: 'one live PostgreSQL response',
finishReason: 'stop',
usage: {
inputTokens: 7,
outputTokens: 3,
totalTokens: 10,
},
};
},
async *stream() {
throw new Error('not used');
},
},
],
policies: {
async resolve() {
return {
revision: 'policy-1',
allowedProviders: ['openai-compatible'],
allowedModels: ['vendor/model-a'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 512,
maxTotalTokens: 1024,
maxCostMicros: null,
priceRevision: null,
};
},
},
};
},
async audit() {},
promptOutputKeys: {
async active() {
return {
keyId: 'cluster-prompt-output-key-1',
key: Buffer.alloc(32, 11),
};
},
async resolve(keyId) {
return keyId === 'cluster-prompt-output-key-1'
? { keyId, key: Buffer.alloc(32, 11) }
: null;
},
},
promptOutputRead: {
authorizer: {
async authorize() {
return { effect: 'allow' };
},
},
},
maxConcurrent: 1,
recoveryLimit: 8,
now: () => 31_000,
});
assert.equal(application.status, 'active');
assert.equal(application.readiness.currentUser, 'ql3_runtime');
const executor = application.promptExecutions;
const input = {
projectId: publication.target.projectId,
packageName: publication.target.packageName,
promptId: 'summary',
requestId: `prompt-request-${suffix}`,
traceId: `prompt-trace-${suffix}`,
auditEventId: randomUUID(),
principal: {
subject: { type: 'user', id: 'user-a' },
authenticationId: `api_credential:${credentialId}:1`,
authenticatedAtMs: 1,
expiresAtMs: 9999999999999,
assurance: 'single_factor',
},
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'private PostgreSQL input' },
provider: 'openai-compatible',
model: 'vendor/model-a',
maxOutputTokens: 512,
temperature: 0.2,
plannedAtMs: 30_000,
deadlineAtMs: 90_000,
};
const first = await executor.execute(input);
assert.equal(first.status, 'executed');
assert.equal(first.result.text, 'one live PostgreSQL response');
assert.equal(first.finalization.runStatus, 'succeeded');
const replay = await executor.execute(input);
assert.equal(replay.status, 'existing');
assert.equal(replay.result, null);
assert.deepEqual(replay.admission, first.admission);
assert.deepEqual(replay.finalization, first.finalization);
assert.equal(providerCalls, 1);
const durableInput = {
...input,
requestId: `prompt-request-durable-${suffix}`,
traceId: `prompt-trace-durable-${suffix}`,
auditEventId: randomUUID(),
output: {
mode: 'durable_artifact',
retentionPolicy: {
revision: 'cluster-output-v1',
retentionMs: 86_400_000,
},
},
};
const durableFirst = await executor.execute(durableInput);
assert.equal(durableFirst.status, 'executed');
assert.equal(durableFirst.result.text, 'one live PostgreSQL response');
assert.equal(
durableFirst.outputArtifact.artifactId.startsWith('pao:'),
true,
);
const durableReplay = await executor.execute(durableInput);
assert.equal(durableReplay.status, 'existing');
assert.equal(durableReplay.result, null);
assert.deepEqual(
durableReplay.outputArtifact,
durableFirst.outputArtifact,
);
assert.equal(providerCalls, 2);
assert.ok(application.promptExecutionOutputs);
const recoveredOutput = await application.promptExecutionOutputs.read({
principal: input.principal,
projectId: durableInput.projectId,
packageName: durableInput.packageName,
promptId: durableInput.promptId,
executionRequestId: durableInput.requestId,
});
assert.equal(recoveredOutput.status, 'available');
assert.equal(recoveredOutput.result.text, 'one live PostgreSQL response');
assert.deepEqual(recoveredOutput.reference, durableFirst.outputArtifact);
assert.equal(
(
await application.promptExecutionOutputs.read({
principal: input.principal,
projectId: durableInput.projectId,
packageName: durableInput.packageName,
promptId: 'cross-target',
executionRequestId: durableInput.requestId,
})
).status,
'not_found',
);
const outputEvidence = await runtimePool.query(
`SELECT artifact.artifact_json::text AS "artifactJson",
step.output_ref AS "outputRef"
FROM "ql3_ai"."model_invocation_prompt_output_artifacts" AS artifact
JOIN "ql3"."step_runs" AS step
ON step.id = artifact.step_run_id
AND step.run_id = artifact.run_id
WHERE artifact.invocation_id = $1`,
[durableFirst.admission.invocationId],
);
assert.equal(outputEvidence.rows.length, 1);
assert.equal(
outputEvidence.rows[0].outputRef,
durableFirst.outputArtifact.artifactId,
);
assert.equal(
outputEvidence.rows[0].artifactJson.includes(
'one live PostgreSQL response',
),
false,
);
const durable = await runtimePool.query(
`SELECT admission.plan_json, admission.receipt_json,
finalization.receipt_json, run.status, run.version,
run.event_sequence AS "eventSequence"
FROM "ql3_ai"."model_invocation_prompt_admissions" AS admission
JOIN "ql3_ai"."model_invocation_prompt_finalizations"
AS finalization USING (request_id)
JOIN "ql3"."runs" AS run ON run.id = admission.run_id
WHERE admission.request_id = $1`,
[input.requestId],
);
assert.equal(durable.rows.length, 1);
assert.deepEqual(
{
status: durable.rows[0].status,
version: durable.rows[0].version,
eventSequence: durable.rows[0].eventSequence,
},
{ status: 'succeeded', version: 5, eventSequence: 5 },
);
const durableJson = JSON.stringify(durable.rows[0]);
assert.equal(durableJson.includes('private PostgreSQL input'), false);
assert.equal(durableJson.includes('one live PostgreSQL response'), false);
} finally {
await application?.stop();
await Promise.all([
runtimePool.end(),
executorPool.end(),
migrationPool.end(),
]);
}
});
}
@@ -0,0 +1,364 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
postgresModelInvocationMigrationDefinition,
} = require('@qinglong/ai/model-invocation-migration');
const {
PostgresPluginPackagePromptApplicationUnavailableError,
PostgresPluginPackagePromptExecutionService,
assertPostgresPluginPackagePromptApplicationReady,
bootstrapPostgresPluginPackagePromptApplication,
} = require('../dist/prompt/postgresPluginPackagePromptApplication.js');
const {
createInitialPluginPackageAutomationPublication,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
const {
pluginPackageTaskReconciliationFixture,
} = require('../../../test/contracts/pluginPackageTaskReconciliationRepositoryContract.cjs');
function providers(onDispose) {
return {
providers: [
{
type: 'openai-compatible',
async listModels() {
return [{ id: 'test/model-a' }];
},
async generate() {
throw new Error('not used');
},
async *stream() {
throw new Error('not used');
},
},
],
policies: {
async resolve() {
throw new Error('not used');
},
},
dispose: onDispose,
};
}
function recoveryPool() {
return {
async query(sql) {
if (sql.includes('statement_timestamp()')) {
return { rows: [{ observedAtMs: '1000' }], rowCount: 1 };
}
if (sql.includes('model_invocation_starts')) {
return { rows: [], rowCount: 0 };
}
throw new Error(`unexpected SQL: ${sql}`);
},
async connect() {
throw new Error('not used');
},
};
}
function readiness() {
return Object.freeze({
schema: 'ql3_ai',
migrationStreamId: postgresModelInvocationMigrationDefinition.id,
migrationCount:
postgresModelInvocationMigrationDefinition.migrations.length,
currentUser: 'ql3_runtime',
runtimeAuthority: true,
appendOnly: true,
});
}
function promptProductFixture() {
const source = pluginPackageTaskReconciliationFixture('prompt-product', {
profile: 'cluster-control',
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}}.',
parameters: [{ name: 'subject', required: true }],
},
],
});
return createInitialPluginPackageAutomationPublication(
source.revision,
source.registry,
20_000,
);
}
test('Cluster Prompt product derives current publication and guards admission atomically', async () => {
const publication = promptProductFixture();
const productQueries = [];
const pool = {
async query(sql) {
productQueries.push(sql);
if (sql.includes('model_invocation_prompt_admissions'))
return { rows: [] };
if (sql.includes('plugin_package_automation_publication_heads')) {
return { rows: [{ publicationJson: publication }] };
}
throw new Error(`unexpected product query: ${sql}`);
},
async connect() {
throw new Error('not used');
},
};
const transactionQueries = [];
let credentialState = 'active';
const client = {
async query(sql, parameters = []) {
transactionQueries.push({ sql, parameters });
if (sql.includes('plugin_package_prompt_authorize_admission')) {
return { rows: [{ authorized: credentialState === 'active' }] };
}
return { rows: [] };
},
};
let executorInput;
let providerCalls = 0;
const service = new PostgresPluginPackagePromptExecutionService(
pool,
(guard) => ({
async execute(input) {
executorInput = input;
await guard.confirm({
client,
replay: false,
plan: {
requestId: input.requestId,
plannedAtMs: input.plannedAtMs,
requestedBySubject: input.requestedBySubject,
policyFence: input.policyFence,
target: {
...publication.target,
publicationDigest: publication.publicationDigest,
promptId: input.promptId,
},
},
});
providerCalls += 1;
return {
status: 'executed',
admission: { requestId: input.requestId },
finalization: { runStatus: 'succeeded' },
result: { text: 'live result' },
};
},
}),
);
const command = {
projectId: publication.target.projectId,
packageName: publication.target.packageName,
promptId: 'summary',
requestId: 'prompt-request-1',
traceId: 'prompt-trace-1',
auditEventId: '00000000-0000-4000-8000-000000000001',
principal: {
subject: { type: 'user', id: 'user-a' },
authenticationId: 'api_credential:prompt-credential:1',
authenticatedAtMs: 1,
expiresAtMs: 100_000,
assurance: 'single_factor',
},
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'private input' },
provider: 'openai-compatible',
model: 'vendor/model-a',
maxOutputTokens: 128,
plannedAtMs: 30_000,
deadlineAtMs: 90_000,
};
const result = await service.execute(command);
assert.equal(result.result.text, 'live result');
assert.equal(
executorInput.expectedPublicationDigest,
publication.publicationDigest,
);
assert.equal('publicationDigest' in command, false);
assert.equal(
productQueries.some((sql) =>
sql.includes('plugin_package_automation_publication_heads'),
),
true,
);
const authorization = transactionQueries.find(({ sql }) =>
sql.includes('plugin_package_prompt_authorize_admission'),
);
assert.equal(authorization.parameters[7], command.auditEventId);
assert.equal(authorization.parameters[8], command.requestId);
assert.equal(authorization.parameters[10], false);
assert.equal(authorization.parameters.includes('private input'), false);
assert.equal(providerCalls, 1);
credentialState = 'revoked';
await assert.rejects(
service.execute({
...command,
requestId: 'prompt-request-revoked',
auditEventId: '00000000-0000-4000-8000-000000000002',
}),
(error) => error?.code === 'PLUGIN_PACKAGE_PROMPT_ADMISSION_NOT_ALLOWED',
);
assert.equal(providerCalls, 1);
});
test('disabled Cluster Package Prompt application is database/provider loader-free', async () => {
const audits = [];
const result = await bootstrapPostgresPluginPackagePromptApplication({
async audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'disabled');
assert.equal(result.profile, 'cluster');
assert.equal(await result.stop(), 'stopped');
assert.deepEqual(audits, [{ profile: 'cluster', state: 'disabled' }]);
});
test('PostgreSQL readiness binds the exact migration stream and runtime authority', async () => {
let queries = 0;
const pool = {
async query(sql) {
queries += 1;
if (sql.includes('ai_schema_migrations')) {
return {
rows: postgresModelInvocationMigrationDefinition.migrations.map(
(migration) => ({
migrationId: migration.id,
streamId: postgresModelInvocationMigrationDefinition.id,
dialect: postgresModelInvocationMigrationDefinition.dialect,
checksum: migration.checksum,
}),
),
};
}
return {
rows: [
{
currentUser: 'ql3_runtime',
runtimeAuthority: true,
schemaUsage: true,
invocationAppendOnly: true,
promptAppendOnly: true,
catalogReadable: true,
promptSnapshotExecutable: true,
promptAuthorizationExecutable: true,
},
],
};
},
};
assert.deepEqual(
await assertPostgresPluginPackagePromptApplicationReady(pool),
readiness(),
);
assert.equal(queries, 2);
});
test('active Cluster Package Prompt application recovers before provider load and owns shutdown', async () => {
const events = [];
let databaseCloses = 0;
let providerLoads = 0;
let providerDisposals = 0;
const result = await bootstrapPostgresPluginPackagePromptApplication({
enabled: true,
async openDatabase() {
events.push('database_open');
return {
pool: recoveryPool(),
async close() {
databaseCloses += 1;
events.push('database_close');
},
};
},
async assertReady() {
events.push('readiness');
return readiness();
},
async loadProviders() {
providerLoads += 1;
events.push('providers_load');
return providers(async () => {
providerDisposals += 1;
events.push('providers_dispose');
});
},
async audit(record) {
events.push(record.state);
},
maxConcurrent: 2,
recoveryLimit: 4,
});
assert.equal(result.status, 'active');
assert.equal(result.profile, 'cluster');
assert.deepEqual(result.readiness, readiness());
assert.equal(typeof result.prompts.execute, 'function');
assert.equal(typeof result.promptExecutions.execute, 'function');
assert.equal(providerLoads, 1);
assert.ok(events.indexOf('readiness') < events.indexOf('storage_ready'));
assert.ok(
events.indexOf('recovery_ready') < events.indexOf('providers_load'),
);
assert.ok(events.indexOf('providers_load') < events.indexOf('active'));
assert.equal(await result.stop(), 'stopped');
assert.equal(await result.stop(), 'stopped');
assert.equal(providerDisposals, 1);
assert.equal(databaseCloses, 1);
assert.ok(
events.indexOf('providers_dispose') < events.indexOf('database_close'),
);
assert.equal(events.at(-1), 'stopped');
});
test('readiness failure closes PostgreSQL before provider credentials are reachable', async () => {
let databaseCloses = 0;
let providerLoads = 0;
await assert.rejects(
bootstrapPostgresPluginPackagePromptApplication({
enabled: true,
async openDatabase() {
return {
pool: recoveryPool(),
async close() {
databaseCloses += 1;
},
};
},
async assertReady() {
throw new Error('schema drift');
},
async loadProviders() {
providerLoads += 1;
return providers(async () => {});
},
async audit() {},
}),
PostgresPluginPackagePromptApplicationUnavailableError,
);
assert.equal(databaseCloses, 1);
assert.equal(providerLoads, 0);
});
test('readiness rejects migration checksum drift', async () => {
const migrations = postgresModelInvocationMigrationDefinition.migrations.map(
(migration, index) => ({
migrationId: migration.id,
streamId: postgresModelInvocationMigrationDefinition.id,
dialect: postgresModelInvocationMigrationDefinition.dialect,
checksum: index === 7 ? '0'.repeat(64) : migration.checksum,
}),
);
await assert.rejects(
assertPostgresPluginPackagePromptApplicationReady({
async query() {
return { rows: migrations };
},
}),
PostgresPluginPackagePromptApplicationUnavailableError,
);
});
@@ -0,0 +1,223 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
pluginPackageAutomationPublicationDigest,
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
const {
preparePluginPackagePromptExecution,
} = require('../dist/prompt/pluginPackagePromptExecution.js');
const {
createPluginPackagePromptOutputArtifact,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const {
PostgresPluginPackagePromptOutputArtifactRepository,
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptOutputArtifactRepository.js');
function publication() {
const unsigned = {
schema: 'qinglong/plugin-package-automation-publication@v1',
target: {
projectId: 'project-a',
packageName: 'package-a',
installationId: 'installation-a',
lockDigest: '1'.repeat(64),
generation: 1,
generationDigest: '2'.repeat(64),
materializedRevisionDigest: '3'.repeat(64),
},
state: 'active',
version: 1,
previousPublicationDigest: null,
lifecycleEventDigest: null,
definitions: {
workflows: [],
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: 'summary',
name: 'Summary',
template: 'Summarize {{subject}}.',
parameters: [{ name: 'subject', required: true }],
},
],
},
publishedAtMs: 1_000,
};
return {
...unsigned,
publicationDigest: pluginPackageAutomationPublicationDigest(unsigned),
};
}
function prepared(output) {
const active = publication();
return preparePluginPackagePromptExecution({
publication: active,
expectedPublicationDigest: active.publicationDigest,
promptId: 'summary',
requestId: 'prompt-request-a',
traceId: 'trace-a',
requestedBySubject: { type: 'user', id: 'user-a' },
policyFence: { projectVersion: 1, bindingVersion: 1 },
parameters: { subject: 'private input' },
provider: 'openai-compatible',
model: 'model-a',
maxOutputTokens: 64,
plannedAtMs: 2_000,
deadlineAtMs: 62_000,
...(output === undefined ? {} : { output }),
});
}
function row(artifact) {
return {
artifactId: artifact.artifactId,
projectId: artifact.projectId,
runId: artifact.runId,
stepRunId: artifact.stepRunId,
invocationId: artifact.invocationId,
requestedByType: artifact.requestedBy.type,
requestedById: artifact.requestedBy.id,
provider: artifact.provider,
model: artifact.model,
contentDigest: artifact.contentDigest,
outputBytes: artifact.outputBytes,
retentionPolicyRevision: artifact.retentionPolicy.revision,
retentionMs: String(artifact.retentionPolicy.retentionMs),
retentionPolicyDigest: artifact.retentionPolicyDigest,
retentionEligibleAtMs: String(artifact.retentionEligibleAtMs),
keyId: artifact.keyId,
algorithm: artifact.algorithm,
plaintextBytes: artifact.plaintextBytes,
sealedAtMs: String(artifact.sealedAtMs),
artifactDigest: artifact.artifactDigest,
artifactJson: artifact,
};
}
function fakePool(plan) {
const queries = [];
let stored = null;
const client = {
async query(sql, parameters = []) {
queries.push(sql);
if (sql.includes('model_invocation_prompt_admissions')) {
return { rows: [{ planJson: plan }] };
}
if (
sql.startsWith('SELECT artifact_id') &&
sql.includes('model_invocation_prompt_output_artifacts')
) {
return {
rows: stored && stored.artifactId === parameters[0] ? [stored] : [],
};
}
if (
sql.includes('INSERT INTO') &&
sql.includes('prompt_output_artifacts')
) {
const artifact = JSON.parse(parameters[20]);
stored = row(artifact);
return { rows: [] };
}
return { rows: [] };
},
release() {},
};
return {
queries,
async connect() {
return client;
},
async query(sql, parameters) {
return client.query(sql, parameters);
},
};
}
test('PostgreSQL Prompt output Artifact is immutable and plan-bound', async () => {
const durable = prepared({
mode: 'durable_artifact',
retentionPolicy: { revision: 'cluster-v1', retentionMs: 86_400_000 },
});
const artifact = createPluginPackagePromptOutputArtifact(
{
projectId: durable.plan.target.projectId,
runId: durable.plan.runId,
stepRunId: durable.plan.stepRunId,
invocationId: durable.plan.invocationId,
requestedBy: durable.plan.requestedBySubject,
result: {
provider: durable.plan.provider,
model: durable.plan.model,
text: 'private PostgreSQL Artifact output',
finishReason: 'stop',
usage: { inputTokens: 2, outputTokens: 3, totalTokens: 5 },
},
retentionPolicy: durable.plan.output.retentionPolicy,
keyId: 'cluster-key-1',
key: Buffer.alloc(32, 7),
sealedAtMs: 3_000,
},
() => Buffer.alloc(12, 9),
);
const pool = fakePool(durable.plan);
const repository = new PostgresPluginPackagePromptOutputArtifactRepository(
pool,
);
assert.deepEqual(await repository.put(artifact), { status: 'inserted' });
assert.deepEqual(await repository.put(artifact), { status: 'existing' });
assert.deepEqual(await repository.find(artifact.artifactId), artifact);
assert.equal(pool.queries.includes('BEGIN'), true);
assert.equal(
pool.queries.includes('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'),
true,
);
assert.equal(
pool.queries.some((sql) => /FOR (?:UPDATE|SHARE)/.test(sql)),
false,
);
assert.equal(
JSON.stringify(row(artifact)).includes(artifact.ciphertext),
true,
);
assert.equal(
JSON.stringify(row(artifact)).includes('private PostgreSQL'),
false,
);
const live = prepared();
const livePool = fakePool(live.plan);
const liveRepository =
new PostgresPluginPackagePromptOutputArtifactRepository(livePool);
const liveArtifact = createPluginPackagePromptOutputArtifact(
{
projectId: live.plan.target.projectId,
runId: live.plan.runId,
stepRunId: live.plan.stepRunId,
invocationId: live.plan.invocationId,
requestedBy: live.plan.requestedBySubject,
result: {
provider: live.plan.provider,
model: live.plan.model,
text: 'must remain live only',
finishReason: 'stop',
usage: { inputTokens: 1, outputTokens: 1, totalTokens: 2 },
},
retentionPolicy: { revision: 'cluster-v1', retentionMs: 86_400_000 },
keyId: 'cluster-key-1',
key: Buffer.alloc(32, 7),
sealedAtMs: 3_000,
},
() => Buffer.alloc(12, 9),
);
await assert.rejects(liveRepository.put(liveArtifact), {
code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_CONFLICT',
});
assert.equal(
livePool.queries.some((sql) => sql.includes('INSERT INTO')),
false,
);
});
@@ -0,0 +1,184 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
PostgresPluginPackagePromptOutputKeyRetirementRepository,
assertPostgresPluginPackagePromptOutputKeyNotRetiring,
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptOutputKeyRetirementRepository.js');
function preparationRow(preparation) {
return {
keyId: preparation.keyId,
retirementId: preparation.retirementId,
requestId: preparation.requestId,
mutationId: preparation.mutationId,
catalogDigest: preparation.catalogDigest,
materialProof: preparation.materialProof,
preparedAtMs: String(preparation.preparedAtMs),
preparationDigest: preparation.preparationDigest,
preparationJson: preparation,
};
}
function completionRow(completion) {
return {
keyId: completion.keyId,
retirementId: completion.retirementId,
requestId: completion.requestId,
mutationId: completion.mutationId,
preparationDigest: completion.preparationDigest,
retiredCatalogDigest: completion.retiredCatalogDigest,
absenceProof: completion.absenceProof,
completedAtMs: String(completion.completedAtMs),
completionDigest: completion.completionDigest,
completionJson: completion,
};
}
function storagePool(options = {}) {
const queries = [];
const preparations = new Map();
const completions = new Map();
const liveKeys = new Set(options.liveKeys ?? []);
const client = {
async query(sql, parameters = []) {
queries.push({ sql, parameters });
if (
sql.includes('key_retirement_preparations') &&
sql.includes('SELECT')
) {
const value = preparations.get(parameters[0]);
return { rows: value ? [preparationRow(value)] : [] };
}
if (
sql.includes('key_retirement_completions') &&
sql.includes('SELECT')
) {
const value = completions.get(parameters[0]);
return { rows: value ? [completionRow(value)] : [] };
}
if (sql.includes('count(*)::text')) {
return { rows: [{ count: liveKeys.has(parameters[0]) ? '1' : '0' }] };
}
if (
sql.includes('INSERT INTO') &&
sql.includes('key_retirement_preparations')
) {
const value = JSON.parse(parameters[8]);
preparations.set(value.keyId, value);
return { rows: [], rowCount: 1 };
}
if (
sql.includes('INSERT INTO') &&
sql.includes('key_retirement_completions')
) {
const value = JSON.parse(parameters[9]);
completions.set(value.keyId, value);
return { rows: [], rowCount: 1 };
}
return { rows: [], rowCount: 0 };
},
release() {},
};
return {
queries,
preparations,
completions,
client,
async connect() {
return client;
},
async query(sql, parameters) {
return client.query(sql, parameters);
},
};
}
function command() {
return {
keyId: 'cluster-key-retired',
retirementId: 'retirement-a',
requestId: 'request-a',
mutationId: 'mutation-a',
catalogDigest: '1'.repeat(64),
materialProof: '2'.repeat(64),
};
}
test('PostgreSQL appends key retirement facts behind a shared key fence', async () => {
const pool = storagePool();
const times = [10_000, 20_000, 30_000, 40_000];
const repository =
new PostgresPluginPackagePromptOutputKeyRetirementRepository({
pool,
now: () => times.shift(),
});
const prepared = await repository.prepare(command());
assert.equal(prepared.status, 'created');
assert.equal(prepared.preparation.preparedAtMs, 10_000);
const replay = await repository.prepare(command());
assert.equal(replay.status, 'existing');
assert.deepEqual(replay.preparation, prepared.preparation);
const completed = await repository.complete({
preparation: prepared.preparation,
retiredCatalogDigest: '3'.repeat(64),
absenceProof: '4'.repeat(64),
});
assert.equal(completed.status, 'created');
assert.equal(completed.completion.completedAtMs, 30_000);
const completionReplay = await repository.complete({
preparation: prepared.preparation,
retiredCatalogDigest: '3'.repeat(64),
absenceProof: '4'.repeat(64),
});
assert.equal(completionReplay.status, 'existing');
assert.deepEqual(completionReplay.completion, completed.completion);
assert.deepEqual(await repository.find(command().keyId), {
preparation: prepared.preparation,
completion: completed.completion,
});
const lockIndex = pool.queries.findIndex(({ sql }) =>
sql.includes('pg_advisory_xact_lock'),
);
const countIndex = pool.queries.findIndex(({ sql }) =>
sql.includes('count(*)::text'),
);
const insertIndex = pool.queries.findIndex(
({ sql }) =>
sql.includes('INSERT INTO') &&
sql.includes('key_retirement_preparations'),
);
assert.equal(lockIndex >= 0, true);
assert.equal(lockIndex < countIndex && countIndex < insertIndex, true);
await assert.rejects(
assertPostgresPluginPackagePromptOutputKeyNotRetiring(
pool.client,
command().keyId,
),
{ code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_CONFLICT' },
);
});
test('PostgreSQL refuses retirement while live ciphertext exists', async () => {
const pool = storagePool({ liveKeys: [command().keyId] });
const repository =
new PostgresPluginPackagePromptOutputKeyRetirementRepository({
pool,
now: () => 10_000,
});
await assert.rejects(repository.prepare(command()), {
code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_RETIREMENT_CONFLICT',
});
assert.equal(pool.preparations.size, 0);
assert.equal(
pool.queries.some(
({ sql }) =>
sql.includes('INSERT INTO') &&
sql.includes('key_retirement_preparations'),
),
false,
);
});
@@ -0,0 +1,217 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
PostgresPluginPackagePromptOutputKeyRotationRepository,
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptOutputKeyRotationRepository.js');
function preparationRow(value) {
return {
rotationId: value.rotationId,
requestId: value.requestId,
mutationId: value.mutationId,
expectedSecretUid: value.expectedSecretUid,
expectedActiveKeyId: value.expectedActiveKeyId,
expectedCatalogDigest: value.expectedCatalogDigest,
newKeyId: value.newKeyId,
materialProof: value.materialProof,
preparedAtMs: String(value.preparedAtMs),
preparationDigest: value.preparationDigest,
preparationJson: value,
};
}
function completionRow(value) {
return {
rotationId: value.rotationId,
requestId: value.requestId,
mutationId: value.mutationId,
preparationDigest: value.preparationDigest,
generation: String(value.generation),
previousActiveKeyId: value.previousActiveKeyId,
activeKeyId: value.activeKeyId,
catalogDigest: value.catalogDigest,
materialProof: value.materialProof,
completedAtMs: String(value.completedAtMs),
completionDigest: value.completionDigest,
completionJson: value,
};
}
function storagePool(options = {}) {
const queries = [];
const preparations = new Map();
const completions = new Map();
let inserts = 0;
let commitFailures = options.commitFailures ?? 0;
const client = {
async query(sql, parameters = []) {
queries.push({ sql, parameters });
if (sql.includes('key_rotation_preparations') && sql.includes('SELECT')) {
const value = preparations.get(parameters[0]);
return { rows: value ? [preparationRow(value)] : [] };
}
if (sql.includes('key_rotation_completions') && sql.includes('SELECT')) {
const value = completions.get(parameters[0]);
return { rows: value ? [completionRow(value)] : [] };
}
if (
sql.includes('INSERT INTO') &&
sql.includes('key_rotation_preparations')
) {
if (options.conflictOnSecondSource && preparations.size > 0) {
const error = new Error('unique source');
error.code = '23505';
throw error;
}
const value = JSON.parse(parameters[10]);
preparations.set(value.rotationId, value);
inserts += 1;
return { rows: [], rowCount: 1 };
}
if (
sql.includes('INSERT INTO') &&
sql.includes('key_rotation_completions')
) {
const value = JSON.parse(parameters[11]);
completions.set(value.rotationId, value);
inserts += 1;
return { rows: [], rowCount: 1 };
}
if (sql === 'COMMIT' && commitFailures > 0 && inserts > 0) {
commitFailures -= 1;
throw new Error('connection reset after durable COMMIT');
}
return { rows: [], rowCount: 0 };
},
release() {},
};
return {
queries,
preparations,
completions,
client,
async connect() {
return client;
},
async query(sql, parameters) {
return client.query(sql, parameters);
},
};
}
function request(overrides = {}) {
return {
rotationId: 'rotation-a',
requestId: 'request-a',
mutationId: 'mutation-a',
expectedSecretUid: 'secret-uid-a',
expectedActiveKeyId: 'key-a',
expectedCatalogDigest: '1'.repeat(64),
newKeyId: 'key-b',
...overrides,
};
}
function state() {
return {
generation: 2,
previousActiveKeyId: 'key-a',
activeKeyId: 'key-b',
catalogDigest: '2'.repeat(64),
materialProof: '3'.repeat(64),
};
}
test('PostgreSQL appends rotation prepare and completion behind one source fence', async () => {
const pool = storagePool();
const times = [10_000, 20_000, 30_000, 40_000];
const repository = new PostgresPluginPackagePromptOutputKeyRotationRepository(
{
pool,
now: () => times.shift(),
},
);
const prepared = await repository.prepare({
request: request(),
materialProof: '3'.repeat(64),
});
assert.equal(prepared.status, 'created');
assert.equal(prepared.preparation.preparedAtMs, 10_000);
const prepareReplay = await repository.prepare({
request: request(),
materialProof: '3'.repeat(64),
});
assert.equal(prepareReplay.status, 'existing');
const completed = await repository.complete({
preparation: prepared.preparation,
state: state(),
});
assert.equal(completed.status, 'created');
assert.equal(completed.completion.completedAtMs, 30_000);
const completionReplay = await repository.complete({
preparation: prepared.preparation,
state: state(),
});
assert.equal(completionReplay.status, 'existing');
assert.deepEqual(await repository.find('rotation-a'), {
preparation: prepared.preparation,
completion: completed.completion,
});
const lockIndex = pool.queries.findIndex(({ sql }) =>
sql.includes('pg_advisory_xact_lock'),
);
const insertIndex = pool.queries.findIndex(
({ sql }) =>
sql.includes('INSERT INTO') && sql.includes('key_rotation_preparations'),
);
assert.equal(lockIndex >= 0 && lockIndex < insertIndex, true);
assert.equal(
JSON.stringify([
...pool.preparations.values(),
...pool.completions.values(),
]).includes(Buffer.alloc(32, 0x42).toString('base64url')),
false,
);
});
test('PostgreSQL durable facts resolve COMMIT response loss and source conflicts', async () => {
const lost = storagePool({ commitFailures: 1 });
const repository = new PostgresPluginPackagePromptOutputKeyRotationRepository(
{
pool: lost,
now: () => 10_000,
},
);
await assert.rejects(
repository.prepare({ request: request(), materialProof: '3'.repeat(64) }),
{ code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_ROTATION_UNAVAILABLE' },
);
const durable = await repository.find('rotation-a');
assert.equal(durable.preparation.rotationId, 'rotation-a');
const competing = storagePool({ conflictOnSecondSource: true });
const competingRepository =
new PostgresPluginPackagePromptOutputKeyRotationRepository({
pool: competing,
now: () => 10_000,
});
await competingRepository.prepare({
request: request(),
materialProof: '3'.repeat(64),
});
await assert.rejects(
competingRepository.prepare({
request: request({
rotationId: 'rotation-b',
requestId: 'request-b',
mutationId: 'mutation-b',
newKeyId: 'key-c',
}),
materialProof: '4'.repeat(64),
}),
{ code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_KEY_ROTATION_CONFLICT' },
);
});
@@ -0,0 +1,306 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
createPluginPackagePromptOutputArtifact,
pluginPackagePromptOutputArtifactReference,
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
const {
PostgresPluginPackagePromptOutputGarbageCollector,
PostgresPluginPackagePromptOutputRetentionRepository,
assertPostgresPluginPackagePromptOutputMaintenanceReady,
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptOutputRetentionRepository.js');
const {
PostgresModelInvocationRepository,
} = require('../dist/model-invocation/postgresModelInvocationRepository.js');
function artifact() {
return createPluginPackagePromptOutputArtifact(
{
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
invocationId: 'invocation-a',
requestedBy: { type: 'user', id: 'user-a' },
result: {
provider: 'openai-compatible',
model: 'model-a',
text: 'private PostgreSQL GC output',
finishReason: 'stop',
usage: { inputTokens: 2, outputTokens: 3, totalTokens: 5 },
},
retentionPolicy: {
revision: 'cluster-v1',
retentionMs: 3_600_000,
},
keyId: 'cluster-key-1',
key: Buffer.alloc(32, 7),
sealedAtMs: 1_000,
},
() => Buffer.alloc(12, 9),
);
}
function artifactRow(value) {
return {
artifactId: value.artifactId,
projectId: value.projectId,
runId: value.runId,
stepRunId: value.stepRunId,
invocationId: value.invocationId,
requestedByType: value.requestedBy.type,
requestedById: value.requestedBy.id,
provider: value.provider,
model: value.model,
contentDigest: value.contentDigest,
outputBytes: value.outputBytes,
retentionPolicyRevision: value.retentionPolicy.revision,
retentionMs: String(value.retentionPolicy.retentionMs),
retentionPolicyDigest: value.retentionPolicyDigest,
retentionEligibleAtMs: String(value.retentionEligibleAtMs),
keyId: value.keyId,
algorithm: value.algorithm,
plaintextBytes: value.plaintextBytes,
sealedAtMs: String(value.sealedAtMs),
artifactDigest: value.artifactDigest,
artifactJson: value,
};
}
function tombstoneRow(value) {
return {
artifactId: value.reference.artifactId,
projectId: value.reference.projectId,
runId: value.reference.runId,
stepRunId: value.reference.stepRunId,
invocationId: value.reference.invocationId,
artifactDigest: value.reference.artifactDigest,
retentionPolicyDigest: value.reference.retentionPolicyDigest,
retentionEligibleAtMs: String(value.reference.retentionEligibleAtMs),
keyId: value.reference.keyId,
tombstonedAtMs: String(value.tombstonedAtMs),
tombstoneDigest: value.tombstoneDigest,
tombstoneJson: value,
};
}
function storagePool(initialArtifact, options = {}) {
let storedArtifact = initialArtifact;
let storedTombstone = null;
const queries = [];
const query = async (sql, parameters = []) => {
queries.push({ sql, parameters });
if (sql.includes('clock_timestamp()')) {
return { rows: [{ observedAtMs: '4000000' }], rowCount: 1 };
}
if (
sql.startsWith('SELECT artifact_id AS "artifactId"') &&
sql.includes('retention_eligible_at_ms <=')
) {
return {
rows: storedArtifact ? [{ artifactId: storedArtifact.artifactId }] : [],
};
}
if (
sql.includes('model_invocation_prompt_output_artifacts') &&
sql.includes('artifact_json AS "artifactJson"')
) {
return {
rows:
storedArtifact && storedArtifact.artifactId === parameters[0]
? [artifactRow(storedArtifact)]
: [],
};
}
if (sql.includes('AS "completionOutcome"')) {
return {
rows: [
{
runStatus: options.runStatus ?? 'succeeded',
stepStatus: 'succeeded',
outputRef: storedArtifact?.artifactId,
completionOutcome: 'succeeded',
finalizationStatus: 'succeeded',
},
],
};
}
if (sql.includes('model_invocation_prompt_output_artifact_tombstones')) {
if (sql.startsWith('SELECT artifact_id')) {
return {
rows:
storedTombstone &&
storedTombstone.reference.artifactId === parameters[0]
? [tombstoneRow(storedTombstone)]
: [],
};
}
if (sql.startsWith('INSERT INTO')) {
storedTombstone = JSON.parse(parameters[11]);
return { rows: [], rowCount: 1 };
}
}
if (sql.startsWith('DELETE FROM')) {
if (
storedArtifact?.artifactId === parameters[0] &&
storedArtifact.artifactDigest === parameters[1]
) {
storedArtifact = null;
return { rows: [], rowCount: 1 };
}
return { rows: [], rowCount: 0 };
}
return { rows: [], rowCount: 0 };
};
const client = { query, release() {} };
return {
queries,
get artifact() {
return storedArtifact;
},
get tombstone() {
return storedTombstone;
},
query,
async connect() {
return client;
},
};
}
test('PostgreSQL GC uses database time and atomically replaces ciphertext with a content-free tombstone', async () => {
const output = artifact();
const pool = storagePool(output);
const collector = new PostgresPluginPackagePromptOutputGarbageCollector({
pool,
policies: {
async resolve() {
return output.retentionPolicy;
},
},
limit: 1,
});
assert.deepEqual(await collector.collect(), {
scanned: 1,
tombstoned: 1,
skipped: 0,
hasMore: false,
});
assert.equal(pool.artifact, null);
assert.deepEqual(
pool.tombstone.reference,
pluginPackagePromptOutputArtifactReference(output),
);
assert.equal(
JSON.stringify(pool.tombstone).includes(output.ciphertext),
false,
);
assert.equal(
JSON.stringify(pool.tombstone).includes('private PostgreSQL GC output'),
false,
);
const insertIndex = pool.queries.findIndex(({ sql }) =>
sql.startsWith('INSERT INTO'),
);
const deleteIndex = pool.queries.findIndex(({ sql }) =>
sql.startsWith('DELETE FROM'),
);
assert.ok(insertIndex >= 0 && insertIndex < deleteIndex);
assert.ok(
pool.queries.some(({ sql }) =>
sql.startsWith('BEGIN ISOLATION LEVEL SERIALIZABLE'),
),
);
assert.ok(
pool.queries.some(({ sql }) => sql.includes('pg_advisory_xact_lock')),
);
const retention = new PostgresPluginPackagePromptOutputRetentionRepository(
pool,
);
const state = await retention.inspect({
reference: pluginPackagePromptOutputArtifactReference(output),
observedAtMs: 4_000_001,
});
assert.equal(state.state, 'tombstoned');
assert.equal(state.tombstoneDigest, pool.tombstone.tombstoneDigest);
const replay = new PostgresModelInvocationRepository(pool);
assert.deepEqual(
await replay.findPromptOutputArtifactTombstone(output.artifactId),
pool.tombstone,
);
});
test('PostgreSQL GC skips non-terminal or policy-drifted artifacts without deleting ciphertext', async () => {
const output = artifact();
const nonTerminal = storagePool(output, { runStatus: 'running' });
const terminalCollector =
new PostgresPluginPackagePromptOutputGarbageCollector({
pool: nonTerminal,
policies: {
async resolve() {
return output.retentionPolicy;
},
},
});
assert.deepEqual(await terminalCollector.collect(), {
scanned: 1,
tombstoned: 0,
skipped: 1,
hasMore: false,
});
assert.deepEqual(nonTerminal.artifact, output);
assert.equal(nonTerminal.tombstone, null);
const drifted = storagePool(output);
const policyCollector = new PostgresPluginPackagePromptOutputGarbageCollector(
{
pool: drifted,
policies: {
async resolve() {
return { revision: 'cluster-v2', retentionMs: 3_600_000 };
},
},
},
);
assert.deepEqual(await policyCollector.collect(), {
scanned: 1,
tombstoned: 0,
skipped: 1,
hasMore: false,
});
assert.deepEqual(drifted.artifact, output);
});
test('PostgreSQL GC maintenance readiness requires the exact delete-only authority', async () => {
const report = await assertPostgresPluginPackagePromptOutputMaintenanceReady({
async query(sql) {
assert.match(sql, /ql3_ai_maintenance/);
return {
rows: [
{
currentUser: 'ql3_ai_maintenance',
maintenanceAuthority: true,
schemaAuthority: true,
artifactDeleteOnly: true,
tombstoneAppendOnly: true,
keyRetirementAppendOnly: true,
keyRotationAppendOnly: true,
terminalEvidenceReadOnly: true,
},
],
};
},
});
assert.deepEqual(report, {
currentUser: 'ql3_ai_maintenance',
maintenanceAuthority: true,
artifactDeleteOnly: true,
tombstoneAppendOnly: true,
keyRetirementAppendOnly: true,
keyRotationAppendOnly: true,
terminalEvidenceReadOnly: true,
});
});
+245
View File
@@ -0,0 +1,245 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
InvalidModelPricingError,
MODEL_INVOCATION_PRICE_QUOTE_SCHEMA,
MODEL_INVOCATION_PRICE_SETTLEMENT_SCHEMA,
MODEL_PRICE_CATALOG_ENTRY_SCHEMA,
StaticModelPriceCatalog,
createModelInvocationPriceQuote,
createModelInvocationPriceSettlement,
createModelPriceCatalogEntry,
normalizeModelInvocationPriceQuote,
normalizeModelInvocationPriceSettlement,
normalizeModelPriceCatalogEntry,
priceModelUsage,
} = require('../dist/pricing/pricing.js');
const {
createModelInvocationCompletionCommand,
createModelInvocationMutationIdentity,
createModelInvocationStartCommand,
} = require('../dist/model-invocation/modelInvocation.js');
const {
createStepRunRecord,
transitionStepRunMutation,
} = require('@qinglong/runtime-core/step-run');
const NOW = 1_000_000;
function price(overrides = {}) {
return createModelPriceCatalogEntry({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-2026-07',
currency: 'USD',
inputMicrosPerMillionTokens: 150_000,
outputMicrosPerMillionTokens: 600_000,
publishedAtMs: NOW - 1,
...overrides,
});
}
function audit(phase, overrides = {}) {
return {
phase,
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
provider: 'remote',
model: 'model-a',
policyRevision: 'policy-1',
requestDigest: `sha256:${'b'.repeat(64)}`,
deadlineAtMs: NOW + 10_000,
inputBytes: 128,
maxOutputTokens: 64,
outputBytes: 0,
usage: null,
errorCode: null,
occurredAtMs: NOW,
...overrides,
};
}
function commands(usage) {
const failed = usage === null;
const ready = createStepRunRecord({
id: 'step-a',
runId: 'run-a',
stepKey: 'model',
kind: 'model',
definitionRef: 'prompt:a@1',
definitionDigest: 'a'.repeat(64),
required: true,
initialStatus: 'ready',
inputRef: 'artifact:a',
mutationId: 'create-step-a',
createdAtMs: NOW - 1,
});
const startIdentity = createModelInvocationMutationIdentity(
'request-a',
'start',
);
const start = createModelInvocationStartCommand(
audit('admitted'),
transitionStepRunMutation(
ready,
{
expectedVersion: ready.version,
expectedDigest: ready.stepRunDigest,
mutationId: startIdentity.mutationId,
to: 'running',
atMs: NOW,
},
{
expectedRunVersion: 1,
expectedRunEventSequence: 1,
eventId: startIdentity.eventId,
dedupeKey: startIdentity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
const completionIdentity = createModelInvocationMutationIdentity(
'request-a',
'completion',
);
const completion = createModelInvocationCompletionCommand(
start.start,
audit(failed ? 'failed' : 'completed', {
outputBytes: failed ? 0 : 12,
usage,
errorCode: failed ? 'MODEL_PROVIDER_FAILED' : null,
occurredAtMs: NOW + 25,
}),
transitionStepRunMutation(
start.stepRunMutation.stepRun,
{
expectedVersion: start.start.startedStepRunVersion,
expectedDigest: start.start.startedStepRunDigest,
mutationId: completionIdentity.mutationId,
to: failed ? 'failed' : 'succeeded',
...(failed
? {
resultCode: 'model_provider_failed',
errorSummary: 'Model invocation failed',
}
: { outputRef: 'model-invocation:request-a' }),
atMs: NOW + 25,
},
{
expectedRunVersion: 2,
expectedRunEventSequence: 2,
eventId: completionIdentity.eventId,
dedupeKey: completionIdentity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
),
);
return { start, completion };
}
test('catalog keeps exact immutable provider/model/revision identities', async () => {
const entry = price();
const catalog = new StaticModelPriceCatalog([entry]);
assert.equal(entry.schema, MODEL_PRICE_CATALOG_ENTRY_SCHEMA);
assert.deepEqual(normalizeModelPriceCatalogEntry(entry), entry);
assert.deepEqual(
await catalog.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-2026-07',
}),
entry,
);
assert.equal(
await catalog.resolve({
provider: 'remote',
model: 'model-a',
priceRevision: 'price-older',
}),
null,
);
assert.throws(
() => new StaticModelPriceCatalog([entry, entry]),
InvalidModelPricingError,
);
});
test('quote reserves the worst valid token allocation without overflow', () => {
const quote = createModelInvocationPriceQuote(price(), {
invocationId: 'request-a',
projectId: 'project-a',
modelPolicyRevision: 'policy-1',
maxTotalTokens: 256,
maxOutputTokens: 64,
});
assert.equal(quote.schema, MODEL_INVOCATION_PRICE_QUOTE_SCHEMA);
assert.equal(quote.reservedCostMicros, 68);
assert.deepEqual(normalizeModelInvocationPriceQuote(quote), quote);
assert.equal(Object.isFrozen(quote), true);
});
test('settlement deterministically prices exact usage and ignores provider cost', () => {
const quote = createModelInvocationPriceQuote(price(), {
invocationId: 'request-a',
projectId: 'project-a',
modelPolicyRevision: 'policy-1',
maxTotalTokens: 256,
maxOutputTokens: 64,
});
const providerUsage = {
inputTokens: 5,
outputTokens: 2,
totalTokens: 7,
costMicros: 99_999,
};
const canonicalUsage = priceModelUsage(quote, providerUsage);
const { completion } = commands(canonicalUsage);
const settlement = createModelInvocationPriceSettlement(
quote,
completion.completion,
);
assert.ok(settlement);
assert.equal(canonicalUsage.costMicros, 3);
assert.equal(settlement.schema, MODEL_INVOCATION_PRICE_SETTLEMENT_SCHEMA);
assert.equal(settlement.costMicros, 3);
assert.deepEqual(
normalizeModelInvocationPriceSettlement(
settlement,
quote,
completion.completion,
),
settlement,
);
});
test('unknown usage remains unpriced and quote tampering fails closed', () => {
const quote = createModelInvocationPriceQuote(price(), {
invocationId: 'request-a',
projectId: 'project-a',
modelPolicyRevision: 'policy-1',
maxTotalTokens: 256,
maxOutputTokens: 64,
});
const failed = commands(null);
assert.equal(
createModelInvocationPriceSettlement(quote, failed.completion.completion),
null,
);
assert.throws(
() =>
normalizeModelInvocationPriceQuote({
...quote,
reservedCostMicros: quote.reservedCostMicros + 1,
}),
InvalidModelPricingError,
);
});
@@ -0,0 +1,555 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
ModelGatewayProfileDrainingError,
ModelGatewayProfileUnavailableError,
ModelPriceCatalogManagementProfileUnavailableError,
bootstrapModelPriceCatalogManagementProfile,
bootstrapModelGatewayProfile,
} = require('@qinglong/ai/profile');
function repository(overrides = {}) {
return {
async findStart() {
return null;
},
async findCompletion() {
return null;
},
async findResolution() {
return null;
},
async findUsage() {
return null;
},
async findPriceQuote() {
return null;
},
async findPriceSettlement() {
return null;
},
async listProjectUsage() {
return { records: [], hasMore: false };
},
async summarizeProjectUsage() {
return {
invocationCount: 0,
inputTokens: 0,
outputTokens: 0,
totalTokens: 0,
knownCostMicros: 0,
unknownCostInvocations: 0,
};
},
async findQuotaReservation() {
return null;
},
async findQuotaSettlement() {
return null;
},
async readQuotaWindowUsage() {
return null;
},
async readAuthority() {
return null;
},
async listIncomplete() {
return {
observedAtMs: 1,
candidates: [],
hasMore: false,
};
},
async admit() {
throw new Error('not used');
},
async complete() {
throw new Error('not used');
},
async resolve() {
throw new Error('not used');
},
...overrides,
};
}
function providerAuthority(dispose) {
return {
providers: [
{
type: 'remote',
async listModels() {
return [{ id: 'model-a' }];
},
async generate() {
throw new Error('not used');
},
async *stream() {
throw new Error('not used');
},
},
],
policies: {
async resolve() {
throw new Error('not used');
},
},
dispose,
};
}
function pricingAuthority(overrides = {}) {
return {
async resolve() {
throw new Error('not used');
},
...overrides,
};
}
test('disabled AI Profile never reaches storage or provider credential loaders', async () => {
let storageLoads = 0;
let providerLoads = 0;
const audits = [];
const result = await bootstrapModelGatewayProfile({
enabled: false,
profile: 'edge',
async loadStorage() {
storageLoads += 1;
throw new Error('must remain unreachable');
},
async loadProviders() {
providerLoads += 1;
throw new Error('must remain unreachable');
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'disabled');
assert.equal(await result.stop(), 'stopped');
assert.equal(storageLoads, 0);
assert.equal(providerLoads, 0);
assert.deepEqual(audits, [{ profile: 'edge', state: 'disabled' }]);
});
test('enabled Edge AI Profile proves storage and recovery before providers', async () => {
const order = [];
const audits = [];
const result = await bootstrapModelGatewayProfile({
enabled: true,
profile: 'edge',
async loadStorage() {
order.push('storage');
return {
repository: repository({
async listIncomplete(limit) {
order.push(`recovery:${limit}`);
return {
observedAtMs: 2,
candidates: [],
hasMore: false,
};
},
}),
pricing: pricingAuthority(),
close() {
order.push('storage.close');
},
};
},
async loadProviders() {
order.push('providers');
return providerAuthority(() => {
order.push('providers.dispose');
});
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'active');
assert.equal(result.capability.maxConcurrent, 1);
assert.equal(result.capability.recoveryLimit, 4);
assert.equal(result.capability.accepting, true);
assert.deepEqual(order.slice(0, 3), ['storage', 'recovery:4', 'providers']);
assert.deepEqual(
audits.map(({ state }) => state),
['storage_ready', 'recovery_ready', 'active'],
);
assert.deepEqual(
await result.capability.listProjectUsage({
projectId: 'project-a',
fromMsInclusive: 0,
toMsExclusive: 1,
limit: 1,
}),
{ records: [], hasMore: false },
);
assert.equal(
(
await result.capability.summarizeProjectUsage({
projectId: 'project-a',
fromMsInclusive: 0,
toMsExclusive: 1,
})
).invocationCount,
0,
);
assert.equal(
await result.capability.readQuotaWindowUsage('project-a', 0),
null,
);
assert.equal(await result.capability.findPriceQuote('request-a'), null);
assert.equal(await result.capability.findPriceSettlement('request-a'), null);
assert.equal(await result.capability.stop(), 'stopped');
assert.equal(result.capability.accepting, false);
assert.deepEqual(order, [
'storage',
'recovery:4',
'providers',
'providers.dispose',
'storage.close',
]);
assert.equal(await result.capability.stop(), 'stopped');
assert.equal(order.filter((item) => item.endsWith('close')).length, 1);
assert.equal(order.filter((item) => item.endsWith('dispose')).length, 1);
assert.equal(audits.at(-1).state, 'stopped');
});
test('durable activation fence drains and releases authorities before a rejected operation', async () => {
const order = [];
const audits = [];
let active = true;
const result = await bootstrapModelGatewayProfile({
enabled: true,
profile: 'edge',
async loadStorage() {
return {
repository: repository(),
pricing: pricingAuthority(),
close() {
order.push('storage.close');
},
};
},
async loadProviders() {
return providerAuthority(() => {
order.push('providers.dispose');
});
},
confirmActive() {
if (!active) throw new Error('feature generation changed');
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'active');
active = false;
await assert.rejects(
result.capability.listProjectUsage({
projectId: 'project-a',
fromMsInclusive: 0,
toMsExclusive: 1,
limit: 1,
}),
ModelGatewayProfileDrainingError,
);
assert.equal(result.capability.accepting, false);
assert.equal(result.capability.activeOperations, 0);
assert.deepEqual(order, ['providers.dispose', 'storage.close']);
assert.deepEqual(
audits.map(({ state }) => state),
['storage_ready', 'recovery_ready', 'active', 'draining', 'stopped'],
);
assert.equal(await result.capability.stop(), 'stopped');
});
test('an explicit stop automatically releases authorities when the final operation drains', async () => {
const order = [];
let release;
let started;
const operationStarted = new Promise((resolve) => {
started = resolve;
});
const operationRelease = new Promise((resolve) => {
release = resolve;
});
const result = await bootstrapModelGatewayProfile({
enabled: true,
profile: 'standalone',
async loadStorage() {
return {
repository: repository({
async listProjectUsage() {
started();
await operationRelease;
return { records: [], hasMore: false };
},
}),
pricing: pricingAuthority(),
close() {
order.push('storage.close');
},
};
},
async loadProviders() {
return providerAuthority(() => {
order.push('providers.dispose');
});
},
audit() {},
});
assert.equal(result.status, 'active');
const operation = result.capability.listProjectUsage({
projectId: 'project-a',
fromMsInclusive: 0,
toMsExclusive: 1,
limit: 1,
});
await operationStarted;
assert.equal(await result.capability.stop(), 'draining');
assert.equal(result.capability.accepting, false);
release();
await operation;
assert.equal(await result.capability.stop(), 'stopped');
assert.deepEqual(order, ['providers.dispose', 'storage.close']);
});
test('AI Profile fails closed before provider credentials when recovery is truncated', async () => {
const order = [];
const audits = [];
await assert.rejects(
bootstrapModelGatewayProfile({
enabled: true,
profile: 'cluster',
async loadStorage() {
order.push('storage');
return {
repository: repository({
async listIncomplete(limit) {
order.push(`recovery:${limit}`);
return {
observedAtMs: 3,
candidates: [],
hasMore: true,
};
},
}),
pricing: pricingAuthority(),
close() {
order.push('storage.close');
},
};
},
async loadProviders() {
order.push('providers');
return providerAuthority();
},
audit(record) {
audits.push(record);
},
}),
ModelGatewayProfileUnavailableError,
);
assert.deepEqual(order, ['storage', 'recovery:128', 'storage.close']);
assert.deepEqual(
audits.map(({ state }) => state),
['storage_ready', 'failed'],
);
});
test('AI Profile closes incomplete storage authority before provider credentials', async () => {
const order = [];
const audits = [];
await assert.rejects(
bootstrapModelGatewayProfile({
enabled: true,
profile: 'edge',
async loadStorage() {
order.push('storage');
return {
repository: repository(),
close() {
order.push('storage.close');
},
};
},
async loadProviders() {
order.push('providers');
return providerAuthority();
},
audit(record) {
audits.push(record);
},
}),
ModelGatewayProfileUnavailableError,
);
assert.deepEqual(order, ['storage', 'storage.close']);
assert.deepEqual(
audits.map(({ state }) => state),
['failed'],
);
});
function modelPriceCatalogManagementAuthority(overrides = {}) {
return {
repository: {
async findPublication() {
return null;
},
async findCurrent() {
return null;
},
async findAuthorization() {
return null;
},
async publishAuthorized() {
throw new Error('not used');
},
async transitionAuthorized() {
throw new Error('not used');
},
},
authorizer: {
async authorize() {
throw new Error('not used');
},
},
...overrides,
};
}
test('disabled price catalog management is loader-free on constrained Edge', async () => {
let authorityLoads = 0;
const audits = [];
const result = await bootstrapModelPriceCatalogManagementProfile({
enabled: false,
profile: 'edge',
async loadAuthority() {
authorityLoads += 1;
throw new Error('must remain unreachable');
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'disabled');
assert.equal(result.decisionMode, 'human_confirmation');
assert.equal(await result.stop(), 'stopped');
assert.equal(authorityLoads, 0);
assert.deepEqual(audits, [
{
profile: 'edge',
state: 'disabled',
decisionMode: 'human_confirmation',
},
]);
});
test('standalone price catalog management lazily activates human confirmation authority', async () => {
const order = [];
const audits = [];
const result = await bootstrapModelPriceCatalogManagementProfile({
enabled: true,
profile: 'standalone',
async loadAuthority() {
order.push('authority');
return modelPriceCatalogManagementAuthority({
close() {
order.push('authority.close');
},
});
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'active');
assert.equal(result.decisionMode, 'human_confirmation');
assert.equal(result.capability.accepting, true);
assert.equal(result.capability.activeOperations, 0);
assert.equal(await result.capability.stop(), 'stopped');
assert.equal(result.capability.accepting, false);
assert.equal(await result.capability.stop(), 'stopped');
assert.deepEqual(order, ['authority', 'authority.close']);
assert.deepEqual(
audits.map(({ state }) => state),
['authority_ready', 'active', 'stopped'],
);
});
test('cluster price catalog management fails closed without quota authority', async () => {
const order = [];
const audits = [];
await assert.rejects(
bootstrapModelPriceCatalogManagementProfile({
enabled: true,
profile: 'cluster',
async loadAuthority() {
order.push('authority');
return modelPriceCatalogManagementAuthority({
close() {
order.push('authority.close');
},
});
},
audit(record) {
audits.push(record);
},
}),
ModelPriceCatalogManagementProfileUnavailableError,
);
assert.deepEqual(order, ['authority', 'authority.close']);
assert.deepEqual(audits, [
{
profile: 'cluster',
state: 'failed',
decisionMode: 'separation_of_duty',
},
]);
});
test('cluster price catalog management requires separation of duty and quota', async () => {
const order = [];
const audits = [];
const result = await bootstrapModelPriceCatalogManagementProfile({
enabled: true,
profile: 'cluster',
async loadAuthority() {
order.push('authority');
return modelPriceCatalogManagementAuthority({
quota: {
async consume() {
throw new Error('not used');
},
},
close() {
order.push('authority.close');
},
});
},
audit(record) {
audits.push(record);
},
});
assert.equal(result.status, 'active');
assert.equal(result.decisionMode, 'separation_of_duty');
assert.equal(result.capability.decisionMode, 'separation_of_duty');
assert.equal(await result.capability.stop(), 'stopped');
assert.deepEqual(order, ['authority', 'authority.close']);
assert.deepEqual(
audits.map(({ state }) => state),
['authority_ready', 'active', 'stopped'],
);
});
@@ -0,0 +1,125 @@
const assert = require('node:assert/strict');
const { chmod, mkdtemp, writeFile } = require('node:fs/promises');
const { tmpdir } = require('node:os');
const { join } = require('node:path');
const test = require('node:test');
const {
PROJECTED_MODEL_GATEWAY_AUTHORITY_SCHEMA,
ProjectedModelGatewayAuthorityUnavailableError,
canonicalProjectedModelGatewayAuthorityManifest,
loadProjectedModelGatewayProviderAuthority,
} = require('../dist/model-gateway/projectedModelGatewayAuthority.js');
function manifest(overrides = {}) {
return {
schema: PROJECTED_MODEL_GATEWAY_AUTHORITY_SCHEMA,
providers: [
{
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
allowPlaintextLoopback: false,
maxResponseBytes: 1048576,
},
],
projects: [
{
projectId: 'project-a',
policy: {
revision: 'policy-v1',
allowedProviders: ['openai-compatible'],
allowedModels: ['vendor/model-a'],
maxInputBytes: 4096,
maxOutputBytes: 4096,
maxOutputTokens: 256,
maxTotalTokens: 1024,
maxCostMicros: null,
priceRevision: null,
},
},
],
...overrides,
};
}
async function authorityFile(value, mode = 0o440) {
const root = await mkdtemp(join(tmpdir(), 'ql3-ai-authority-'));
const file = join(root, 'authority.json');
await writeFile(
file,
canonicalProjectedModelGatewayAuthorityManifest(value),
{ mode },
);
await chmod(file, mode);
return file;
}
const credentials = Object.freeze({
async authorizationHeader() {
throw new Error('not invoked while loading authority');
},
});
test('projected authority loads one canonical provider and Project policy', async () => {
const configFile = await authorityFile(manifest());
const authority = await loadProjectedModelGatewayProviderAuthority({
configFile,
credentials,
});
assert.deepEqual(
authority.providers.map(({ type }) => type),
['openai-compatible'],
);
assert.deepEqual(
await authority.policies.resolve({ projectId: 'project-a' }),
manifest().projects[0].policy,
);
await assert.rejects(
authority.policies.resolve({ projectId: 'project-b' }),
ProjectedModelGatewayAuthorityUnavailableError,
);
});
test('projected authority rejects provider/policy drift before network access', async () => {
assert.throws(
() =>
canonicalProjectedModelGatewayAuthorityManifest(
manifest({
projects: [
{
...manifest().projects[0],
policy: {
...manifest().projects[0].policy,
allowedProviders: ['missing-provider'],
},
},
],
}),
),
ProjectedModelGatewayAuthorityUnavailableError,
);
});
test('projected authority rejects writable or noncanonical JSON', async () => {
const writable = await authorityFile(manifest(), 0o640);
await assert.rejects(
loadProjectedModelGatewayProviderAuthority({
configFile: writable,
credentials,
}),
ProjectedModelGatewayAuthorityUnavailableError,
);
const root = await mkdtemp(join(tmpdir(), 'ql3-ai-authority-'));
const noncanonical = join(root, 'authority.json');
await writeFile(noncanonical, JSON.stringify(manifest(), null, 2), {
mode: 0o440,
});
await chmod(noncanonical, 0o440);
await assert.rejects(
loadProjectedModelGatewayProviderAuthority({
configFile: noncanonical,
credentials,
}),
ProjectedModelGatewayAuthorityUnavailableError,
);
});
@@ -0,0 +1,105 @@
const assert = require('node:assert/strict');
const {
mkdtemp,
mkdir,
chmod,
symlink,
unlink,
writeFile,
} = require('node:fs/promises');
const { tmpdir } = require('node:os');
const { join } = require('node:path');
const test = require('node:test');
const {
ProjectedModelProviderSecretMaterialUnavailableError,
createProjectedModelProviderSecretMaterialProvider,
projectedModelProviderSecretFileName,
} = require('../dist/model-provider-credential/projectedModelProviderSecretMaterial.js');
const { createSecretRef } = require('@qinglong/runtime-core/secret-reference');
const SECRET_REF = createSecretRef({
projectId: 'project-a',
name: 'openai-token',
});
async function generation(root, name, value, mode = 0o440) {
const directory = join(root, name);
await mkdir(directory);
const path = join(
directory,
projectedModelProviderSecretFileName(SECRET_REF),
);
await writeFile(path, value, { mode });
await chmod(path, mode);
}
async function atomicProjection(root, activeGeneration) {
const fileName = projectedModelProviderSecretFileName(SECRET_REF);
await symlink(activeGeneration, join(root, '..data'));
await symlink(join('..data', fileName), join(root, fileName));
}
test('projected credential material follows atomic rotation and wipes owned bytes', async () => {
const root = await mkdtemp(join(tmpdir(), 'ql3-ai-credential-'));
await generation(root, '..data-one', 'token-one');
await generation(root, '..data-two', 'token-two');
await atomicProjection(root, '..data-one');
const provider = await createProjectedModelProviderSecretMaterialProvider({
rootDirectory: root,
});
const first = await provider.resolveProjectSecretMaterial({
projectId: 'project-a',
secretRef: SECRET_REF,
});
assert.equal(Buffer.from(first.bytes).toString('utf8'), 'token-one');
const owned = first.bytes;
await first.dispose();
assert.deepEqual([...owned], Array(9).fill(0));
await unlink(join(root, '..data'));
await symlink('..data-two', join(root, '..data'));
const second = await provider.resolveProjectSecretMaterial({
projectId: 'project-a',
secretRef: SECRET_REF,
});
assert.equal(Buffer.from(second.bytes).toString('utf8'), 'token-two');
await second.dispose();
});
test('projected credential material rejects Project drift and writable material', async () => {
const root = await mkdtemp(join(tmpdir(), 'ql3-ai-credential-'));
await generation(root, '..data-one', 'unsafe-token', 0o640);
await atomicProjection(root, '..data-one');
const provider = await createProjectedModelProviderSecretMaterialProvider({
rootDirectory: root,
});
await assert.rejects(
provider.resolveProjectSecretMaterial({
projectId: 'project-b',
secretRef: SECRET_REF,
}),
ProjectedModelProviderSecretMaterialUnavailableError,
);
await assert.rejects(
provider.resolveProjectSecretMaterial({
projectId: 'project-a',
secretRef: SECRET_REF,
}),
ProjectedModelProviderSecretMaterialUnavailableError,
);
});
test('projected credential material rejects symlink root', async () => {
const direct = await mkdtemp(join(tmpdir(), 'ql3-ai-credential-'));
const parent = await mkdtemp(join(tmpdir(), 'ql3-ai-credential-link-'));
const linked = join(parent, 'root');
await symlink(direct, linked);
await assert.rejects(
createProjectedModelProviderSecretMaterialProvider({
rootDirectory: linked,
}),
ProjectedModelProviderSecretMaterialUnavailableError,
);
});
@@ -0,0 +1,365 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { createSecretRef } = require('@qinglong/runtime-core/secret-reference');
const {
BoundModelProviderCredentialProvider,
InvalidModelProviderCredentialBindingError,
MODEL_PROVIDER_CREDENTIAL_AUDIT_SCHEMA,
MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
ModelProviderCredentialUnavailableError,
digestModelProviderCredentialBinding,
normalizeModelProviderCredentialBinding,
} = require('../dist/model-provider-credential/providerCredential.js');
const {
OpenAiCompatibleProvider,
} = require('../dist/model-gateway/openAiCompatibleProvider.js');
const credentialSubpath = require('@qinglong/ai/provider-credential');
const SECRET_REF = createSecretRef({
projectId: 'project-a',
name: 'OPENAI_API_KEY',
});
function binding(overrides = {}) {
return {
schema: MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
projectId: 'project-a',
provider: 'openai-compatible',
revision: 'credential-binding-v1',
secretRef: SECRET_REF,
scheme: 'bearer',
...overrides,
};
}
function authorizationRequest(overrides = {}) {
return {
operation: 'generate',
projectId: 'project-a',
provider: 'openai-compatible',
requestId: 'request-a',
...overrides,
};
}
test('publishes credential binding through one explicit AI package subpath', () => {
assert.equal(
credentialSubpath.BoundModelProviderCredentialProvider,
BoundModelProviderCredentialProvider,
);
assert.equal(
credentialSubpath.MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
MODEL_PROVIDER_CREDENTIAL_BINDING_SCHEMA,
);
});
test('normalizes one canonical Project-bound binding and derives a stable content digest', () => {
const normalized = normalizeModelProviderCredentialBinding(binding());
assert.equal(Object.isFrozen(normalized), true);
assert.deepEqual(normalized, binding());
assert.match(
digestModelProviderCredentialBinding(normalized),
/^sha256:[a-f0-9]{64}$/,
);
assert.equal(
digestModelProviderCredentialBinding(normalized),
digestModelProviderCredentialBinding(binding()),
);
assert.throws(
() =>
normalizeModelProviderCredentialBinding(
binding({
secretRef: createSecretRef({
projectId: 'project-b',
name: 'OPENAI_API_KEY',
}),
}),
),
InvalidModelProviderCredentialBindingError,
);
assert.throws(
() =>
normalizeModelProviderCredentialBinding({ ...binding(), extra: true }),
InvalidModelProviderCredentialBindingError,
);
});
test('resolves, audits and disposes one short-lived bearer credential without content leakage', async () => {
const lookups = [];
const resolutions = [];
const audits = [];
let sourceDisposed = 0;
let sourceBytes;
const credentials = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding(lookup) {
lookups.push(lookup);
return binding();
},
},
secrets: {
async resolveProjectSecretMaterial(request) {
resolutions.push(request);
sourceBytes = Buffer.from('sk-ephemeral_123', 'ascii');
return {
secretRef: request.secretRef,
bytes: sourceBytes,
dispose() {
sourceDisposed += 1;
sourceBytes.fill(0);
},
};
},
},
audit: {
async record(record) {
audits.push(record);
},
},
now: () => 1234,
});
const lease = await credentials.authorizationHeader(authorizationRequest());
assert.equal(lease.value, 'Bearer sk-ephemeral_123');
assert.equal(sourceDisposed, 1);
assert.deepEqual([...sourceBytes], new Array(sourceBytes.length).fill(0));
assert.deepEqual(lookups, [
{ projectId: 'project-a', provider: 'openai-compatible' },
]);
assert.deepEqual(resolutions, [
{ projectId: 'project-a', secretRef: SECRET_REF },
]);
assert.equal(audits.length, 1);
assert.deepEqual(audits[0], {
schema: MODEL_PROVIDER_CREDENTIAL_AUDIT_SCHEMA,
operation: 'generate',
projectId: 'project-a',
provider: 'openai-compatible',
requestId: 'request-a',
bindingRevision: 'credential-binding-v1',
bindingDigest: digestModelProviderCredentialBinding(binding()),
occurredAtMs: 1234,
});
assert.equal(JSON.stringify(audits).includes('ephemeral'), false);
await lease.dispose();
assert.throws(() => lease.value, ModelProviderCredentialUnavailableError);
await lease.dispose();
});
test('re-resolves an unversioned SecretRef on every operation without a cache or watcher', async () => {
const values = ['token-a', 'token-b'];
let resolved = 0;
const credentials = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return binding();
},
},
secrets: {
async resolveProjectSecretMaterial(request) {
const bytes = Buffer.from(values[resolved++], 'ascii');
return {
secretRef: request.secretRef,
bytes,
dispose() {
bytes.fill(0);
},
};
},
},
audit: { async record() {} },
});
const first = await credentials.authorizationHeader(authorizationRequest());
const second = await credentials.authorizationHeader(
authorizationRequest({ operation: 'stream', requestId: 'request-b' }),
);
assert.equal(first.value, 'Bearer token-a');
assert.equal(second.value, 'Bearer token-b');
assert.equal(resolved, 2);
await first.dispose();
await second.dispose();
});
test('fails closed on missing or drifted bindings and disposes material when audit fails', async () => {
let secretCalls = 0;
const missing = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return null;
},
},
secrets: {
async resolveProjectSecretMaterial() {
secretCalls += 1;
throw new Error('must not run');
},
},
audit: { async record() {} },
});
await assert.rejects(
missing.authorizationHeader(authorizationRequest()),
ModelProviderCredentialUnavailableError,
);
assert.equal(secretCalls, 0);
const drifted = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return binding({ provider: 'another-provider' });
},
},
secrets: {
async resolveProjectSecretMaterial() {
secretCalls += 1;
throw new Error('must not run');
},
},
audit: { async record() {} },
});
await assert.rejects(
drifted.authorizationHeader(authorizationRequest()),
ModelProviderCredentialUnavailableError,
);
assert.equal(secretCalls, 0);
let disposed = 0;
const bytes = Buffer.from('token-a', 'ascii');
const unavailableAudit = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return binding();
},
},
secrets: {
async resolveProjectSecretMaterial(request) {
return {
secretRef: request.secretRef,
bytes,
dispose() {
disposed += 1;
bytes.fill(0);
},
};
},
},
audit: {
async record() {
throw new Error('audit unavailable');
},
},
});
await assert.rejects(
unavailableAudit.authorizationHeader(authorizationRequest()),
ModelProviderCredentialUnavailableError,
);
assert.equal(disposed, 1);
assert.deepEqual([...bytes], new Array(bytes.length).fill(0));
});
test('credential audit failure prevents OpenAI-compatible network access', async () => {
let fetchCalls = 0;
let disposed = 0;
const credentials = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return binding();
},
},
secrets: {
async resolveProjectSecretMaterial(request) {
const bytes = Buffer.from('token-a', 'ascii');
return {
secretRef: request.secretRef,
bytes,
dispose() {
disposed += 1;
bytes.fill(0);
},
};
},
},
audit: {
async record() {
throw new Error('audit unavailable');
},
},
});
const provider = new OpenAiCompatibleProvider({
type: 'openai-compatible',
baseUrl: 'https://models.example.test/v1/',
credentials,
async fetch() {
fetchCalls += 1;
throw new Error('must not run');
},
});
await assert.rejects(
provider.generate(
{
provider: 'openai-compatible',
model: 'model-a',
messages: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 16,
},
{
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
deadlineAtMs: Date.now() + 10_000,
},
),
ModelProviderCredentialUnavailableError,
);
assert.equal(fetchCalls, 0);
assert.equal(disposed, 1);
});
test('rejects unscoped model listing and malformed or oversized Secret material', async () => {
const materials = [
Buffer.from('token with spaces', 'ascii'),
Buffer.alloc(4096, 0x61),
Buffer.from([0xff, 0xfe]),
];
let disposed = 0;
const credentials = new BoundModelProviderCredentialProvider({
bindings: {
async resolveModelProviderCredentialBinding() {
return binding();
},
},
secrets: {
async resolveProjectSecretMaterial(request) {
const bytes = materials.shift();
return {
secretRef: request.secretRef,
bytes,
dispose() {
disposed += 1;
bytes.fill(0);
},
};
},
},
audit: { async record() {} },
});
await assert.rejects(
credentials.authorizationHeader({
operation: 'list_models',
provider: 'openai-compatible',
}),
InvalidModelProviderCredentialBindingError,
);
for (const requestId of ['malformed-a', 'malformed-b', 'malformed-c']) {
await assert.rejects(
credentials.authorizationHeader(authorizationRequest({ requestId })),
ModelProviderCredentialUnavailableError,
);
}
assert.equal(disposed, 3);
});
+257
View File
@@ -0,0 +1,257 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
createStepRunRecord,
transitionStepRunMutation,
} = require('@qinglong/runtime-core/step-run');
const {
createModelInvocationCompletionCommand,
createModelInvocationMutationIdentity,
createModelInvocationStartCommand,
} = require('../dist/model-invocation/modelInvocation.js');
const {
InvalidModelInvocationUsageLedgerError,
MAX_MODEL_INVOCATION_USAGE_QUERY_WINDOW_MS,
MODEL_INVOCATION_USAGE_LEDGER_SCHEMA,
createModelInvocationUsageLedgerRecord,
normalizeModelInvocationUsageLedgerQuery,
normalizeModelInvocationUsageLedgerRecord,
normalizeModelInvocationUsageLedgerSummaryQuery,
} = require('@qinglong/ai/usage-ledger');
const NOW = 1_000_000;
function audit(phase, overrides = {}) {
return {
phase,
projectId: 'project-a',
runId: 'run-a',
stepRunId: 'step-a',
traceId: 'trace-a',
requestId: 'request-a',
provider: 'remote',
model: 'model-a',
policyRevision: 'policy-1',
requestDigest: `sha256:${'b'.repeat(64)}`,
deadlineAtMs: NOW + 10_000,
inputBytes: 128,
maxOutputTokens: 64,
outputBytes: 0,
usage: null,
errorCode: null,
occurredAtMs: NOW,
...overrides,
};
}
function startFixture(projectId = 'project-a') {
const current = createStepRunRecord({
id: 'step-a',
runId: 'run-a',
stepKey: 'summarize',
kind: 'model',
definitionRef: 'prompt:summary@1',
definitionDigest: 'a'.repeat(64),
required: true,
initialStatus: 'ready',
inputRef: 'artifact:input-a',
mutationId: 'create-step-a',
createdAtMs: NOW - 1,
});
const identity = createModelInvocationMutationIdentity('request-a', 'start');
const mutation = transitionStepRunMutation(
current,
{
expectedVersion: current.version,
expectedDigest: current.stepRunDigest,
mutationId: identity.mutationId,
to: 'running',
atMs: NOW,
},
{
expectedRunVersion: 1,
expectedRunEventSequence: 1,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
);
return createModelInvocationStartCommand(
audit('admitted', { projectId }),
mutation,
);
}
function completionFixture({
errorCode = null,
usage = { inputTokens: 5, outputTokens: 2, totalTokens: 7, costMicros: 11 },
} = {}) {
const startCommand = startFixture();
const identity = createModelInvocationMutationIdentity(
'request-a',
'completion',
);
const failed = errorCode !== null;
const mutation = transitionStepRunMutation(
startCommand.stepRunMutation.stepRun,
{
expectedVersion: startCommand.start.startedStepRunVersion,
expectedDigest: startCommand.start.startedStepRunDigest,
mutationId: identity.mutationId,
to: failed ? 'failed' : 'succeeded',
atMs: NOW + 25,
...(failed
? {
resultCode: 'model_provider_failed',
errorSummary: 'Model invocation failed',
}
: { outputRef: 'model-invocation:request-a' }),
},
{
expectedRunVersion: 2,
expectedRunEventSequence: 2,
eventId: identity.eventId,
dedupeKey: identity.dedupeKey,
actor: { type: 'executor', id: 'model-gateway' },
},
);
return createModelInvocationCompletionCommand(
startCommand.start,
audit(failed ? 'failed' : 'completed', {
occurredAtMs: NOW + 25,
outputBytes: failed ? 0 : 12,
usage,
errorCode,
}),
mutation,
);
}
test('usage ledger derives one immutable content-free billing fact', () => {
const start = startFixture().start;
const completion = completionFixture().completion;
const ledger = createModelInvocationUsageLedgerRecord(start, completion);
assert.ok(ledger);
assert.equal(ledger.schema, MODEL_INVOCATION_USAGE_LEDGER_SCHEMA);
assert.equal(ledger.invocationId, completion.invocationId);
assert.equal(ledger.completionDigest, completion.completionDigest);
assert.equal(ledger.provider, start.provider);
assert.equal(ledger.model, start.model);
assert.equal(ledger.policyRevision, start.policyRevision);
assert.equal(ledger.outcome, 'succeeded');
assert.equal(ledger.inputTokens, 5);
assert.equal(ledger.outputTokens, 2);
assert.equal(ledger.totalTokens, 7);
assert.equal(ledger.costMicros, 11);
assert.deepEqual(
createModelInvocationUsageLedgerRecord(start, completion),
ledger,
);
assert.deepEqual(normalizeModelInvocationUsageLedgerRecord(ledger), ledger);
assert.equal(Object.isFrozen(ledger), true);
assert.equal(JSON.stringify(ledger).includes('top secret prompt'), false);
});
test('failed provider completion remains billable when usage is known', () => {
const start = startFixture().start;
const completion = completionFixture({
errorCode: 'MODEL_PROVIDER_FAILED',
usage: { inputTokens: 5, outputTokens: 0, totalTokens: 5 },
}).completion;
const ledger = createModelInvocationUsageLedgerRecord(start, completion);
assert.ok(ledger);
assert.equal(ledger.outcome, 'failed');
assert.equal(ledger.totalTokens, 5);
assert.equal(ledger.costMicros, null);
});
test('completion without usage creates no synthetic zero-cost fact', () => {
const start = startFixture().start;
const completion = completionFixture({
errorCode: 'MODEL_PROVIDER_FAILED',
usage: null,
}).completion;
assert.equal(createModelInvocationUsageLedgerRecord(start, completion), null);
});
test('detached completion and digest tampering fail closed', () => {
const start = startFixture().start;
const completion = completionFixture().completion;
const ledger = createModelInvocationUsageLedgerRecord(start, completion);
assert.throws(
() =>
createModelInvocationUsageLedgerRecord(
startFixture('project-b').start,
completion,
),
InvalidModelInvocationUsageLedgerError,
);
assert.throws(
() =>
normalizeModelInvocationUsageLedgerRecord({
...ledger,
totalTokens: ledger.totalTokens + 1,
}),
InvalidModelInvocationUsageLedgerError,
);
assert.throws(
() =>
normalizeModelInvocationUsageLedgerRecord({
...ledger,
ledgerDigest: '0'.repeat(64),
}),
InvalidModelInvocationUsageLedgerError,
);
});
test('Project usage query is bounded and cursor stays inside its window', () => {
const query = {
projectId: 'project-a',
fromMsInclusive: NOW,
toMsExclusive: NOW + 100,
limit: 128,
after: { settledAtMs: NOW + 25, invocationId: 'request-a' },
};
assert.deepEqual(normalizeModelInvocationUsageLedgerQuery(query), query);
assert.deepEqual(
normalizeModelInvocationUsageLedgerSummaryQuery({
projectId: 'project-a',
fromMsInclusive: NOW,
toMsExclusive: NOW + 100,
}),
{
projectId: 'project-a',
fromMsInclusive: NOW,
toMsExclusive: NOW + 100,
},
);
assert.throws(
() =>
normalizeModelInvocationUsageLedgerQuery({
...query,
toMsExclusive:
query.fromMsInclusive +
MAX_MODEL_INVOCATION_USAGE_QUERY_WINDOW_MS +
1,
}),
InvalidModelInvocationUsageLedgerError,
);
assert.throws(
() =>
normalizeModelInvocationUsageLedgerQuery({
...query,
after: { ...query.after, settledAtMs: NOW - 1 },
}),
InvalidModelInvocationUsageLedgerError,
);
assert.throws(
() => normalizeModelInvocationUsageLedgerQuery({ ...query, limit: 129 }),
InvalidModelInvocationUsageLedgerError,
);
});
+156
View File
@@ -0,0 +1,156 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const {
InvalidModelInvocationQuotaError,
ModelInvocationQuotaConfigurationError,
createModelInvocationQuotaAdmission,
createModelInvocationQuotaReservation,
createModelInvocationQuotaSettlement,
normalizeModelInvocationProjectQuotaPolicy,
normalizeModelInvocationQuotaAdmission,
normalizeModelInvocationQuotaReservation,
} = require('../dist/usage/usageQuota.js');
const quota = Object.freeze({
revision: 'quota-1',
windowMs: 3_600_000,
maxInvocations: 10,
maxTokens: 10_000,
maxCostMicros: 50_000,
});
function admission(overrides = {}) {
return createModelInvocationQuotaAdmission({
invocationId: 'invocation-a',
projectId: 'project-a',
modelPolicyRevision: 'model-policy-1',
reservedTokens: 1_000,
reservedCostMicros: 5_000,
quota,
...overrides,
});
}
function completion(overrides = {}) {
return {
invocationId: 'invocation-a',
projectId: 'project-a',
completionDigest: 'c'.repeat(64),
completedAtMs: 3_600_200,
usage: {
inputTokens: 120,
outputTokens: 30,
totalTokens: 150,
costMicros: 700,
},
...overrides,
};
}
test('quota admission reserves one bounded call in a database-aligned window', () => {
const value = admission();
const reservation = createModelInvocationQuotaReservation(value, 3_600_123);
assert.deepEqual(normalizeModelInvocationProjectQuotaPolicy(quota), quota);
assert.deepEqual(normalizeModelInvocationQuotaAdmission(value), value);
assert.deepEqual(
normalizeModelInvocationQuotaReservation(reservation),
reservation,
);
assert.equal(reservation.windowStartMs, 3_600_000);
assert.equal(reservation.windowEndMs, 7_200_000);
assert.match(reservation.admissionDigest, /^[0-9a-f]{64}$/);
assert.match(reservation.reservationDigest, /^[0-9a-f]{64}$/);
});
test('known usage settles actual consumption and releases unused capacity', () => {
const reservation = createModelInvocationQuotaReservation(
admission(),
3_600_123,
);
const settlement = createModelInvocationQuotaSettlement(
reservation,
completion(),
);
assert.equal(settlement.effectiveTokens, 150);
assert.equal(settlement.effectiveCostMicros, 700);
assert.equal(settlement.retainedTokenReservation, false);
assert.equal(settlement.retainedCostReservation, false);
});
test('unknown usage retains the full reservation', () => {
const reservation = createModelInvocationQuotaReservation(
admission(),
3_600_123,
);
const settlement = createModelInvocationQuotaSettlement(
reservation,
completion({ usage: null }),
);
assert.equal(settlement.effectiveTokens, 1_000);
assert.equal(settlement.effectiveCostMicros, 5_000);
assert.equal(settlement.retainedTokenReservation, true);
assert.equal(settlement.retainedCostReservation, true);
});
test('known tokens with unknown cost retain only the cost reservation', () => {
const reservation = createModelInvocationQuotaReservation(
admission(),
3_600_123,
);
const settlement = createModelInvocationQuotaSettlement(
reservation,
completion({
usage: { inputTokens: 120, outputTokens: 30, totalTokens: 150 },
}),
);
assert.equal(settlement.effectiveTokens, 150);
assert.equal(settlement.effectiveCostMicros, 5_000);
assert.equal(settlement.retainedTokenReservation, false);
assert.equal(settlement.retainedCostReservation, true);
});
test('cost-disabled quota leaves billing cost to the usage ledger', () => {
const reservation = createModelInvocationQuotaReservation(
admission({
reservedCostMicros: null,
quota: { ...quota, maxCostMicros: null },
}),
3_600_123,
);
const settlement = createModelInvocationQuotaSettlement(
reservation,
completion(),
);
assert.equal(settlement.effectiveTokens, 150);
assert.equal(settlement.effectiveCostMicros, null);
assert.equal(settlement.retainedCostReservation, false);
});
test('cost quota without a per-call cost ceiling fails closed', () => {
assert.throws(
() => admission({ reservedCostMicros: null }),
ModelInvocationQuotaConfigurationError,
);
});
test('tampering and unsupported windows fail closed', () => {
const value = admission();
assert.throws(
() =>
normalizeModelInvocationQuotaAdmission({
...value,
reservedTokens: value.reservedTokens + 1,
}),
InvalidModelInvocationQuotaError,
);
assert.throws(
() => normalizeModelInvocationProjectQuotaPolicy({ ...quota, windowMs: 7 }),
InvalidModelInvocationQuotaError,
);
});