feat(ql3): enforce staged secret binding persistence

This commit is contained in:
whyour
2026-08-13 19:20:39 +08:00
parent f111d8b10c
commit 326783ff14
32 changed files with 1071 additions and 71 deletions
@@ -3,13 +3,22 @@ import type { DatabaseSync } from 'node:sqlite';
import { localSqliteMigrationManifest } from '../migration/migrationManifest';
import { LocalSqliteMigrationStreamStore } from '../migration/migrationStreamStore';
import { LOCAL_PLUGIN_PACKAGE_SECRET_MATERIALIZATION_TRIGGER_SQL } from '../plugin-package/pluginPackageSecretMaterializationSchemaContract';
import { LOCAL_PLUGIN_PACKAGE_SECRET_BINDING_TARGET_TRIGGER_SQL } from '../plugin-package/secret-binding/pluginPackageSecretBindingTargetSchemaContract';
import {
LOCAL_STEP_RUN_REFERENCE_TRIGGERS,
normalizeLocalSqliteSchemaSql,
} from '../run/stepRunSchemaContract';
export const LOCAL_SQLITE_CONTRACT_NAME = 'local-control-core';
export const LOCAL_SQLITE_CONTRACT_VERSION = 47;
export const LOCAL_SQLITE_CONTRACT_VERSION = 48;
const PLUGIN_PACKAGE_SECRET_BINDING_TARGET_TRIGGERS = Object.freeze([
Object.freeze({
name: 'ql3_plugin_package_secret_binding_target_guard',
tableName: 'QingLong3PluginPackageSecretBindings',
sql: LOCAL_PLUGIN_PACKAGE_SECRET_BINDING_TARGET_TRIGGER_SQL,
}),
]);
const PLUGIN_PACKAGE_SECRET_MATERIALIZATION_TRIGGERS = Object.freeze([
Object.freeze({
@@ -1752,6 +1761,7 @@ function assertRequiredSchema(client: DatabaseSync): number {
const expectedTriggers = [
...LOCAL_STEP_RUN_REFERENCE_TRIGGERS,
...PLUGIN_PACKAGE_AUTOMATION_DISPOSITION_TRIGGERS,
...PLUGIN_PACKAGE_SECRET_BINDING_TARGET_TRIGGERS,
...PLUGIN_PACKAGE_SECRET_MATERIALIZATION_TRIGGERS,
].sort((left, right) => left.name.localeCompare(right.name));
if (
@@ -2564,10 +2574,10 @@ export async function auditLocalSqliteReadiness(
capability.contract_name !== LOCAL_SQLITE_CONTRACT_NAME ||
capability.contract_version !== LOCAL_SQLITE_CONTRACT_VERSION ||
capability.migration_id !==
'0093-plugin-package-secret-materialization-guard' ||
'0095-plugin-package-secret-binding-target-guard' ||
typeof capability.capabilities !== 'string' ||
capability.capabilities !==
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_project_administration":1,"local_security_audit":1,"local_security_audit_compaction":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_identity_credential_administration":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1,"local_owner_pepper_catalog":1,"local_owner_credential_recovery":1,"local_owner_pepper_reference_inspection":1,"local_owner_pepper_material_gc":1,"local_owner_delivery_acknowledgement_gc":1,"task_definition":1,"local_execution_revision_digest":1,"trigger_definition":1,"legacy_adoption_ledger":1,"local_scheduler_admission":1,"plugin_package_install":1,"approved_action":1,"plugin_package_admission":1,"approved_action_execution":1,"plugin_package_proposal":1,"plugin_package_materialized_revision":1,"plugin_package_secret_binding":1,"plugin_package_secret_materialization":1,"plugin_package_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_failure_completion":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"plugin_package_quarantine":1,"plugin_package_lifecycle":1,"plugin_package_automation_publication":1,"plugin_package_automation_security_withdrawal":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_run_list":1,"run_attempt_log_retention":1,"plugin_package_workflow_task_attempt_admission":1}' ||
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_project_administration":1,"local_security_audit":1,"local_security_audit_compaction":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_identity_credential_administration":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1,"local_owner_pepper_catalog":1,"local_owner_credential_recovery":1,"local_owner_pepper_reference_inspection":1,"local_owner_pepper_material_gc":1,"local_owner_delivery_acknowledgement_gc":1,"task_definition":1,"local_execution_revision_digest":1,"trigger_definition":1,"legacy_adoption_ledger":1,"local_scheduler_admission":1,"plugin_package_install":1,"approved_action":1,"plugin_package_admission":1,"approved_action_execution":1,"plugin_package_proposal":1,"plugin_package_materialized_revision":1,"plugin_package_secret_binding":1,"plugin_package_secret_binding_transition":1,"plugin_package_secret_materialization":1,"plugin_package_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_failure_completion":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"plugin_package_quarantine":1,"plugin_package_lifecycle":1,"plugin_package_automation_publication":1,"plugin_package_automation_security_withdrawal":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_run_list":1,"run_attempt_log_retention":1,"plugin_package_workflow_task_attempt_admission":1}' ||
typeof capability.updated_at_ms !== 'number' ||
!Number.isSafeInteger(capability.updated_at_ms) ||
capability.updated_at_ms < 0