feat(ql3): materialize package secret bindings

This commit is contained in:
whyour
2026-08-13 10:31:06 +08:00
parent 55ef085a6e
commit d72631a2b0
34 changed files with 839 additions and 115 deletions
@@ -142,9 +142,11 @@ test('creates a reviewed edge database and opens runtime only after readiness',
'0090-capability-v45',
'0091-plugin-package-secret-bindings',
'0092-capability-v46',
'0093-plugin-package-secret-materialization-guard',
'0094-capability-v47',
]);
assert.equal(migrated.readiness.contractName, 'local-control-core');
assert.equal(migrated.readiness.contractVersion, 46);
assert.equal(migrated.readiness.contractVersion, 47);
assert.equal(migrated.readiness.journalMode, 'delete');
assert.equal(fs.statSync(databasePath).mode & 0o777, 0o600);
@@ -228,6 +230,89 @@ test('creates a reviewed edge database and opens runtime only after readiness',
}
});
test('rejects malformed and unbound Package Secret materialized revisions at the database boundary', async () => {
const client = new DatabaseSync(':memory:');
try {
client.exec('PRAGMA foreign_keys = ON');
await runMigrationStream({
stream: localSqliteMigrationDefinition,
store: new LocalSqliteMigrationStreamStore(client),
});
const insert = client.prepare(
`INSERT INTO "QingLong3PluginPackageMaterializedRevisions" (
generation_digest, project_id, package_name, generation,
lock_digest, manifest_digest, revision_digest, revision_json,
created_at_ms
) VALUES (?, 'default', 'secret-guard', 1, ?, ?, ?, ?, 1)`,
);
const digest = 'a'.repeat(64);
const revision = ({ manifest, resources = [] }) => ({
schema: 'qinglong/plugin-package-materialized-revision@v1',
generation: {
installationId: 'install-secret-guard',
projectId: 'default',
packageName: 'secret-guard',
lockDigest: digest,
generation: 1,
generationDigest: digest,
},
manifestDigest: digest,
manifest,
resources,
revisionDigest: digest,
createdAtMs: 1,
});
assert.throws(
() =>
insert.run(
digest,
digest,
digest,
digest,
JSON.stringify(revision({ manifest: {} })),
),
/permission declarations are malformed/,
);
assert.throws(
() =>
insert.run(
digest,
digest,
digest,
digest,
JSON.stringify(
revision({
manifest: { spec: { permissions: { secrets: [] } } },
resources: [
{
kind: 'task',
value: {
spec: {
config: {
environment: [
{
name: 'TOKEN',
kind: 'secret',
secretRef:
'qlsecret://default/runtime-token?version=1',
},
],
},
},
},
},
],
}),
),
),
/outside Package binding/,
);
} finally {
client.close();
}
});
test('standalone opts into bounded WAL while edge keeps rollback journal', async (t) => {
const { databasePath } = fixture(t);
const options = { databasePath, profile: 'standalone' };
@@ -507,8 +592,8 @@ test('backfills v14 execution revisions with a verified independent digest', asy
.get(),
},
{
contract_version: 46,
migration_id: '0091-plugin-package-secret-bindings',
contract_version: 47,
migration_id: '0093-plugin-package-secret-materialization-guard',
},
);
} finally {
@@ -156,7 +156,7 @@ test('atomically admits one generation-bound Workflow Run and exactly replays it
},
{ runs: 1, steps: 2, events: 3, mutations: 2, admissions: 1 },
);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 46);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 47);
});
test('runs an optional authorization guard inside new and replay transactions', async (t) => {
@@ -288,7 +288,7 @@ test('exactly replays immutable admission after the Workflow StepRun advances',
},
{ status: 'running', version: 5, eventSequence: 5 },
);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 46);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 47);
});
test('fails closed before writing when the exact installation is not active', async (t) => {
@@ -231,7 +231,7 @@ test('atomically admits the exact reconciled local Task revision and replays it'
stepAttemptCount: 0,
},
);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 46);
assert.equal((await auditLocalSqliteReadiness(client)).contractVersion, 47);
});
test('bounds candidate paging before SQL and fences cancellation', async (t) => {
@@ -40,9 +40,9 @@ test('creates and exactly replays a reviewed rollout backup', async (t) => {
await migrateLocalSqlitePath(state);
const prepared = await createLocalSqliteRolloutBackup(state);
assert.equal(prepared.status, 'prepared');
assert.equal(prepared.contractVersion, 46);
assert.equal(prepared.writeContractVersion, 46);
assert.equal(LOCAL_SQLITE_WRITE_CONTRACT_VERSION, 46);
assert.equal(prepared.contractVersion, 47);
assert.equal(prepared.writeContractVersion, 47);
assert.equal(LOCAL_SQLITE_WRITE_CONTRACT_VERSION, 47);
assert.match(prepared.sha256, /^[0-9a-f]{64}$/);
assert.equal(prepared.bytes > 0, true);
assert.equal(prepared.pageCount > 0, true);