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,184 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0001RunCoreMigration = defineLocalSqliteMigration({
id: '0001-run-core',
statements: [
`
CREATE TABLE "QingLong3SchemaCapabilities" (
contract_name TEXT PRIMARY KEY,
contract_version INTEGER NOT NULL
CONSTRAINT ql3_local_capabilities_version_check CHECK (contract_version >= 1),
migration_id TEXT NOT NULL,
capabilities TEXT NOT NULL
CONSTRAINT ql3_local_capabilities_json_check
CHECK (json_valid(capabilities) AND json_type(capabilities) = 'object'),
updated_at_ms INTEGER NOT NULL
CONSTRAINT ql3_local_capabilities_updated_at_check CHECK (updated_at_ms >= 0),
CONSTRAINT ql3_local_capabilities_migration_fk
FOREIGN KEY (migration_id)
REFERENCES "QingLong3SchemaMigrations" (migration_id)
)
`,
`
CREATE TABLE "Runs" (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
task_id TEXT NOT NULL,
task_revision TEXT NOT NULL,
task_name TEXT,
task_snapshot_ref TEXT,
legacy_cron_id INTEGER,
parent_run_id TEXT,
retry_of_run_id TEXT,
trigger_id TEXT,
trigger_type TEXT NOT NULL,
execution_origin TEXT NOT NULL
CONSTRAINT ql3_local_runs_execution_origin_check
CHECK (execution_origin IN ('manual','scheduled_system','scheduled_node','once','boot','grpc','subscription','system','script','legacy_import')),
execution_owner TEXT NOT NULL
CONSTRAINT ql3_local_runs_execution_owner_check
CHECK (execution_owner IN ('legacy','runtime')),
triggered_by TEXT,
request_id TEXT,
scheduled_for_ms INTEGER,
status TEXT NOT NULL
CONSTRAINT ql3_local_runs_status_check
CHECK (status IN ('created','queued','dispatching','running','waiting_approval','retry_wait','lost','succeeded','failed','cancelled','timed_out')),
version INTEGER NOT NULL DEFAULT 0
CONSTRAINT ql3_local_runs_version_check CHECK (version >= 0),
event_sequence INTEGER NOT NULL DEFAULT 0
CONSTRAINT ql3_local_runs_event_sequence_check CHECK (event_sequence >= 0),
priority INTEGER NOT NULL DEFAULT 0,
idempotency_key TEXT,
input_ref TEXT,
output_ref TEXT,
created_at_ms INTEGER NOT NULL,
queued_at_ms INTEGER,
started_at_ms INTEGER,
finished_at_ms INTEGER,
cancel_requested_at_ms INTEGER,
cancel_reason TEXT
CONSTRAINT ql3_local_runs_cancel_reason_check
CHECK (cancel_reason IS NULL OR cancel_reason IN ('user','policy','shutdown','reconcile','timeout')),
error_code TEXT,
error_summary TEXT,
CONSTRAINT ql3_local_runs_time_check CHECK (
created_at_ms >= 0 AND
(scheduled_for_ms IS NULL OR scheduled_for_ms >= 0) AND
(queued_at_ms IS NULL OR queued_at_ms >= 0) AND
(started_at_ms IS NULL OR started_at_ms >= 0) AND
(finished_at_ms IS NULL OR finished_at_ms >= 0) AND
(cancel_requested_at_ms IS NULL OR cancel_requested_at_ms >= 0)
),
CONSTRAINT ql3_local_runs_parent_fk FOREIGN KEY (parent_run_id) REFERENCES "Runs" (id),
CONSTRAINT ql3_local_runs_retry_fk FOREIGN KEY (retry_of_run_id) REFERENCES "Runs" (id)
)
`,
`CREATE UNIQUE INDEX ql3_local_runs_project_idempotency_uidx ON "Runs" (project_id, idempotency_key) WHERE idempotency_key IS NOT NULL`,
`CREATE INDEX ql3_local_runs_project_created_idx ON "Runs" (project_id, created_at_ms, id)`,
`CREATE INDEX ql3_local_runs_task_created_idx ON "Runs" (task_id, created_at_ms, id)`,
`CREATE INDEX ql3_local_runs_cancel_requested_idx ON "Runs" (status, cancel_requested_at_ms, id)`,
`CREATE INDEX ql3_local_runs_lost_retry_idx ON "Runs" (execution_owner, status, id)`,
`
CREATE TABLE "RunAttempts" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
step_run_id TEXT,
attempt INTEGER NOT NULL
CONSTRAINT ql3_local_attempts_attempt_check CHECK (attempt >= 1),
status TEXT NOT NULL
CONSTRAINT ql3_local_attempts_status_check
CHECK (status IN ('claimed','starting','running','succeeded','failed','cancelled','timed_out','lost')),
executor_type TEXT NOT NULL,
worker_id TEXT,
worker_session_id TEXT,
worker_generation INTEGER,
executor_handle TEXT,
pid INTEGER,
log_artifact_id TEXT,
lease_token TEXT,
lease_token_digest TEXT,
lease_generation INTEGER,
lease_version INTEGER,
lease_expires_at_ms INTEGER,
offer_id TEXT,
deadline_at_ms INTEGER,
callback_token_hash TEXT,
callback_sequence INTEGER NOT NULL DEFAULT 0
CONSTRAINT ql3_local_attempts_callback_sequence_check CHECK (callback_sequence >= 0),
created_at_ms INTEGER NOT NULL,
started_at_ms INTEGER,
finished_at_ms INTEGER,
exit_code INTEGER,
error_code TEXT,
error_summary TEXT,
CONSTRAINT ql3_local_attempts_time_check CHECK (
created_at_ms >= 0 AND
(started_at_ms IS NULL OR started_at_ms >= 0) AND
(finished_at_ms IS NULL OR finished_at_ms >= 0) AND
(lease_expires_at_ms IS NULL OR lease_expires_at_ms >= 0) AND
(deadline_at_ms IS NULL OR deadline_at_ms >= 0)
),
CONSTRAINT ql3_local_attempts_run_fk FOREIGN KEY (run_id) REFERENCES "Runs" (id) ON DELETE CASCADE
)
`,
`CREATE UNIQUE INDEX ql3_local_attempts_run_attempt_uidx ON "RunAttempts" (run_id, attempt)`,
`CREATE INDEX ql3_local_attempts_run_status_idx ON "RunAttempts" (run_id, status, id)`,
`CREATE INDEX ql3_local_attempts_lease_idx ON "RunAttempts" (lease_expires_at_ms, id)`,
`CREATE INDEX ql3_local_attempts_deadline_idx ON "RunAttempts" (status, deadline_at_ms, id)`,
`
CREATE TABLE "RunEvents" (
id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
sequence INTEGER NOT NULL
CONSTRAINT ql3_local_events_sequence_check CHECK (sequence >= 1),
type TEXT NOT NULL,
dedupe_key TEXT,
actor_type TEXT NOT NULL
CONSTRAINT ql3_local_events_actor_type_check
CHECK (actor_type IN ('user','api_app','trigger','agent','mcp_client','worker','executor','system','legacy_shell','scheduler','reconciler','compatibility')),
actor_id TEXT,
attempt_id TEXT,
step_run_id TEXT,
payload TEXT NOT NULL
CONSTRAINT ql3_local_events_payload_check
CHECK (json_valid(payload) AND json_type(payload) = 'object'),
created_at_ms INTEGER NOT NULL
CONSTRAINT ql3_local_events_created_at_check CHECK (created_at_ms >= 0),
CONSTRAINT ql3_local_events_run_fk FOREIGN KEY (run_id) REFERENCES "Runs" (id) ON DELETE CASCADE,
CONSTRAINT ql3_local_events_attempt_fk FOREIGN KEY (attempt_id) REFERENCES "RunAttempts" (id) ON DELETE SET NULL
)
`,
`CREATE UNIQUE INDEX ql3_local_events_run_sequence_uidx ON "RunEvents" (run_id, sequence)`,
`CREATE UNIQUE INDEX ql3_local_events_run_dedupe_uidx ON "RunEvents" (run_id, dedupe_key) WHERE dedupe_key IS NOT NULL`,
`CREATE INDEX ql3_local_events_run_created_idx ON "RunEvents" (run_id, created_at_ms, id)`,
`
CREATE TABLE "RunRetryPolicies" (
run_id TEXT PRIMARY KEY,
max_attempts INTEGER NOT NULL
CONSTRAINT ql3_local_retry_max_attempts_check CHECK (max_attempts BETWEEN 1 AND 16),
retry_on_lost INTEGER NOT NULL
CONSTRAINT ql3_local_retry_on_lost_check CHECK (retry_on_lost IN (0, 1)),
safety TEXT NOT NULL
CONSTRAINT ql3_local_retry_safety_check CHECK (safety IN ('unknown','idempotent','deduplicated')),
backoff_base_ms INTEGER NOT NULL,
backoff_max_ms INTEGER NOT NULL,
next_attempt_at_ms INTEGER,
version INTEGER NOT NULL DEFAULT 0
CONSTRAINT ql3_local_retry_version_check CHECK (version >= 0),
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_local_retry_backoff_check CHECK (
backoff_base_ms BETWEEN 0 AND 86400000 AND
backoff_max_ms BETWEEN backoff_base_ms AND 86400000
),
CONSTRAINT ql3_local_retry_time_check CHECK (
created_at_ms >= 0 AND updated_at_ms >= created_at_ms AND
(next_attempt_at_ms IS NULL OR next_attempt_at_ms >= 0)
),
CONSTRAINT ql3_local_retry_run_fk FOREIGN KEY (run_id) REFERENCES "Runs" (id) ON DELETE CASCADE
)
`,
`CREATE INDEX ql3_local_retry_due_idx ON "RunRetryPolicies" (next_attempt_at_ms, run_id) WHERE next_attempt_at_ms IS NOT NULL`,
],
});
@@ -0,0 +1,15 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0002CapabilityMigration = defineLocalSqliteMigration({
id: '0002-capability',
statements: [
`
INSERT INTO "QingLong3SchemaCapabilities" (
contract_name, contract_version, migration_id, capabilities, updated_at_ms
) VALUES (
'local-control-core', 1, '0001-run-core', '{"run_core":1,"run_retry_policy":1}',
CAST(unixepoch('subsec') * 1000 AS INTEGER)
)
`,
],
});
@@ -0,0 +1,35 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0003CompletionReceiptJournalMigration =
defineLocalSqliteMigration({
id: '0003-completion-receipt-journal',
statements: [
`
CREATE TABLE "LocalCompletionReceiptJournal" (
attempt_id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
state TEXT NOT NULL
CONSTRAINT ql3_local_receipt_journal_state_check
CHECK (state IN ('pending','quarantined')),
quarantine_ref TEXT,
purge_after_ms INTEGER,
registered_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_local_receipt_journal_time_check CHECK (
registered_at_ms >= 0 AND updated_at_ms >= registered_at_ms AND
(purge_after_ms IS NULL OR purge_after_ms >= updated_at_ms)
),
CONSTRAINT ql3_local_receipt_journal_shape_check CHECK (
(state = 'pending' AND quarantine_ref IS NULL AND purge_after_ms IS NULL) OR
(state = 'quarantined' AND quarantine_ref IS NOT NULL AND purge_after_ms IS NOT NULL)
),
CONSTRAINT ql3_local_receipt_journal_attempt_fk
FOREIGN KEY (attempt_id) REFERENCES "RunAttempts" (id) ON DELETE CASCADE,
CONSTRAINT ql3_local_receipt_journal_run_fk
FOREIGN KEY (run_id) REFERENCES "Runs" (id) ON DELETE CASCADE
)
`,
`CREATE INDEX ql3_local_receipt_journal_scan_idx ON "LocalCompletionReceiptJournal" (state, updated_at_ms, attempt_id)`,
`CREATE INDEX ql3_local_receipt_journal_purge_idx ON "LocalCompletionReceiptJournal" (purge_after_ms, attempt_id) WHERE state = 'quarantined'`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0004CapabilityV2Migration = defineLocalSqliteMigration({
id: '0004-capability-v2',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 2,
migration_id = '0003-completion-receipt-journal',
capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 1
AND migration_id = '0001-run-core'
AND capabilities = '{"run_core":1,"run_retry_policy":1}'
`,
],
});
@@ -0,0 +1,75 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0005LocalDispatchPlanMigration = defineLocalSqliteMigration({
id: '0005-local-dispatch-plan',
statements: [
`
CREATE TABLE "QingLong3LocalExecutionContextRecipes" (
"context_ref" TEXT PRIMARY KEY NOT NULL,
"environment_json" TEXT NOT NULL,
"content_digest" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
CONSTRAINT ql3_local_context_ref_check CHECK (
length("context_ref") = 80
AND "context_ref" GLOB 'localctx:sha256:[0-9a-f]*'
AND length(replace("context_ref", 'localctx:sha256:', '')) = 64
),
CONSTRAINT ql3_local_context_environment_check CHECK (
json_valid("environment_json")
AND json_type("environment_json") = 'array'
AND length("environment_json") <= 262144
),
CONSTRAINT ql3_local_context_digest_check CHECK (
length("content_digest") = 64
AND "content_digest" NOT GLOB '*[^0-9a-f]*'
AND "context_ref" = 'localctx:sha256:' || "content_digest"
),
CONSTRAINT ql3_local_context_created_check CHECK ("created_at_ms" >= 0)
)
`,
`
CREATE TABLE "QingLong3LocalTaskExecutionRevisions" (
"project_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"task_revision" TEXT NOT NULL,
"executor_type" TEXT NOT NULL,
"command_json" TEXT NOT NULL,
"working_directory" TEXT,
"timeout_ms" INTEGER,
"context_ref" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "task_id", "task_revision"),
CONSTRAINT ql3_local_revision_executor_check CHECK (
"executor_type" = 'local_process'
),
CONSTRAINT ql3_local_revision_command_check CHECK (
json_valid("command_json")
AND json_type("command_json") = 'object'
AND length("command_json") BETWEEN 1 AND 131072
),
CONSTRAINT ql3_local_revision_working_directory_check CHECK (
"working_directory" IS NULL
OR (length("working_directory") BETWEEN 1 AND 4096
AND substr("working_directory", 1, 1) = '/')
),
CONSTRAINT ql3_local_revision_timeout_check CHECK (
"timeout_ms" IS NULL OR "timeout_ms" BETWEEN 1 AND 31536000000
),
CONSTRAINT ql3_local_revision_created_check CHECK ("created_at_ms" >= 0),
FOREIGN KEY ("context_ref")
REFERENCES "QingLong3LocalExecutionContextRecipes" ("context_ref")
ON DELETE RESTRICT
)
`,
`
CREATE INDEX "ql3_local_runs_dispatch_idx"
ON "Runs" (
"execution_owner", "status", "priority" DESC,
"queued_at_ms", "id"
)
WHERE "execution_owner" = 'runtime'
AND "status" = 'queued'
AND "cancel_requested_at_ms" IS NULL
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0006CapabilityV3Migration = defineLocalSqliteMigration({
id: '0006-capability-v3',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 3,
migration_id = '0005-local-dispatch-plan',
capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 2
AND migration_id = '0003-completion-receipt-journal'
AND capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1}'
`,
],
});
@@ -0,0 +1,68 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0007LocalSecretEnvelopesMigration =
defineLocalSqliteMigration({
id: '0007-local-secret-envelopes',
statements: [
`
CREATE TABLE "QingLong3LocalSecretEnvelopes" (
"project_id" TEXT NOT NULL,
"secret_name" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"mutation_id" TEXT NOT NULL,
"key_id" TEXT NOT NULL,
"algorithm" TEXT NOT NULL,
"nonce" BLOB NOT NULL,
"ciphertext" BLOB NOT NULL,
"auth_tag" BLOB NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "secret_name", "version"),
CONSTRAINT ql3_local_secret_project_check CHECK (
length("project_id") BETWEEN 1 AND 128
AND "project_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
),
CONSTRAINT ql3_local_secret_name_check CHECK (
length("secret_name") BETWEEN 1 AND 128
AND "secret_name" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
),
CONSTRAINT ql3_local_secret_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_secret_mutation_check CHECK (
length("mutation_id") BETWEEN 1 AND 64
),
CONSTRAINT ql3_local_secret_key_check CHECK (
length("key_id") BETWEEN 1 AND 128
AND "key_id" NOT GLOB '*[^A-Za-z0-9._-]*'
),
CONSTRAINT ql3_local_secret_algorithm_check CHECK (
"algorithm" = 'aes-256-gcm'
),
CONSTRAINT ql3_local_secret_crypto_shape_check CHECK (
length("nonce") = 12
AND length("ciphertext") <= 16384
AND length("auth_tag") = 16
),
CONSTRAINT ql3_local_secret_created_check CHECK ("created_at_ms" >= 0)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_secret_mutation_uidx"
ON "QingLong3LocalSecretEnvelopes" (
"project_id", "secret_name", "mutation_id"
)
`,
`
CREATE INDEX "ql3_local_secret_current_idx"
ON "QingLong3LocalSecretEnvelopes" (
"project_id", "secret_name", "version" DESC
)
`,
`
CREATE INDEX "ql3_local_secret_key_usage_idx"
ON "QingLong3LocalSecretEnvelopes" (
"key_id", "project_id", "secret_name", "version"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0008CapabilityV4Migration = defineLocalSqliteMigration({
id: '0008-capability-v4',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 4,
migration_id = '0007-local-secret-envelopes',
capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 3
AND migration_id = '0005-local-dispatch-plan'
AND capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1}'
`,
],
});
@@ -0,0 +1,166 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0009LocalProjectPolicyAuditMigration =
defineLocalSqliteMigration({
id: '0009-local-project-policy-audit',
statements: [
`
CREATE TABLE "QingLong3Projects" (
"id" TEXT PRIMARY KEY NOT NULL,
"name" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"status" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
"updated_at_ms" INTEGER NOT NULL,
CONSTRAINT ql3_local_projects_id_check CHECK (
length("id") BETWEEN 1 AND 128
AND "id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
),
CONSTRAINT ql3_local_projects_name_check CHECK (
length("name") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_projects_slug_check CHECK (
length("slug") BETWEEN 1 AND 128
AND "slug" = lower("slug")
AND "slug" NOT GLOB '*[^a-z0-9-]*'
AND substr("slug", 1, 1) NOT GLOB '[^a-z0-9]'
AND substr("slug", -1, 1) NOT GLOB '[^a-z0-9]'
),
CONSTRAINT ql3_local_projects_status_check CHECK (
"status" IN ('active', 'archived')
),
CONSTRAINT ql3_local_projects_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_projects_time_check CHECK (
"created_at_ms" >= 0 AND "updated_at_ms" >= "created_at_ms"
)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_projects_slug_uidx"
ON "QingLong3Projects" ("slug")
`,
`
INSERT INTO "QingLong3Projects" (
"id", "name", "slug", "status", "version", "created_at_ms", "updated_at_ms"
) VALUES ('default', 'Default', 'default', 'active', 1, 0, 0)
`,
`
CREATE TABLE "QingLong3ProjectRoleBindings" (
"project_id" TEXT NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"state" TEXT NOT NULL,
"role" TEXT,
"mutation_id" TEXT NOT NULL,
"changed_by_type" TEXT NOT NULL,
"changed_by_id" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "subject_type", "subject_id", "version"),
FOREIGN KEY ("project_id") REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
CONSTRAINT ql3_local_bindings_subject_type_check CHECK (
"subject_type" IN ('user','api_app','mcp_client','agent','system','worker')
),
CONSTRAINT ql3_local_bindings_subject_id_check CHECK (
length("subject_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_bindings_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_bindings_state_role_check CHECK (
("state" = 'active' AND "role" IN ('owner','admin','operator','viewer'))
OR ("state" = 'revoked' AND "role" IS NULL)
),
CONSTRAINT ql3_local_bindings_mutation_check CHECK (
length("mutation_id") BETWEEN 1 AND 64
),
CONSTRAINT ql3_local_bindings_changed_by_type_check CHECK (
"changed_by_type" IN ('user','api_app','mcp_client','agent','system','worker')
),
CONSTRAINT ql3_local_bindings_changed_by_id_check CHECK (
length("changed_by_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_bindings_created_check CHECK ("created_at_ms" >= 0)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_bindings_mutation_uidx"
ON "QingLong3ProjectRoleBindings" (
"project_id", "subject_type", "subject_id", "mutation_id"
)
`,
`
CREATE INDEX "ql3_local_bindings_current_idx"
ON "QingLong3ProjectRoleBindings" (
"project_id", "subject_type", "subject_id", "version" DESC
)
`,
`
CREATE INDEX "ql3_local_bindings_project_idx"
ON "QingLong3ProjectRoleBindings" ("project_id", "version" DESC)
`,
`
CREATE TABLE "QingLong3SecurityAuditEvents" (
"event_id" TEXT PRIMARY KEY NOT NULL,
"request_id" TEXT NOT NULL,
"operation_id" TEXT NOT NULL,
"project_id" TEXT,
"subject_type" TEXT,
"subject_id" TEXT,
"authentication_id" TEXT,
"outcome" TEXT NOT NULL,
"reasons_json" TEXT NOT NULL,
"fence_project_version" INTEGER,
"fence_binding_version" INTEGER,
"occurred_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("project_id") REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
CONSTRAINT ql3_local_audit_event_check CHECK (length("event_id") = 36),
CONSTRAINT ql3_local_audit_request_check CHECK (length("request_id") BETWEEN 1 AND 128),
CONSTRAINT ql3_local_audit_operation_check CHECK (length("operation_id") BETWEEN 1 AND 128),
CONSTRAINT ql3_local_audit_subject_check CHECK (
("subject_type" IS NULL AND "subject_id" IS NULL AND "authentication_id" IS NULL)
OR (
"subject_type" IN ('user','api_app','mcp_client','agent','system','worker')
AND length("subject_id") BETWEEN 1 AND 255
AND length("authentication_id") BETWEEN 1 AND 128
)
),
CONSTRAINT ql3_local_audit_outcome_check CHECK (
"outcome" IN (
'authentication_rejected','authentication_unavailable',
'authorization_unavailable','denied','approval_required','allowed'
)
),
CONSTRAINT ql3_local_audit_reasons_check CHECK (
json_valid("reasons_json")
AND json_type("reasons_json") = 'array'
AND json_array_length("reasons_json") BETWEEN 1 AND 8
AND length("reasons_json") <= 2048
),
CONSTRAINT ql3_local_audit_fence_check CHECK (
("fence_project_version" IS NULL AND "fence_binding_version" IS NULL)
OR (
"fence_project_version" BETWEEN 1 AND 2147483647
AND ("fence_binding_version" IS NULL OR "fence_binding_version" BETWEEN 1 AND 2147483647)
)
),
CONSTRAINT ql3_local_audit_time_check CHECK ("occurred_at_ms" >= 0)
)
`,
`
CREATE INDEX "ql3_local_audit_project_time_idx"
ON "QingLong3SecurityAuditEvents" (
"project_id", "occurred_at_ms" DESC, "event_id" DESC
)
`,
`
CREATE INDEX "ql3_local_audit_subject_time_idx"
ON "QingLong3SecurityAuditEvents" (
"subject_type", "subject_id", "occurred_at_ms" DESC, "event_id" DESC
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0010CapabilityV5Migration = defineLocalSqliteMigration({
id: '0010-capability-v5',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 5,
migration_id = '0009-local-project-policy-audit',
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_security_audit":1,"local_secret_authorized_mutation":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 4
AND migration_id = '0007-local-secret-envelopes'
AND capabilities = '{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1}'
`,
],
});
@@ -0,0 +1,92 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0011LocalIdentityCredentialMigration =
defineLocalSqliteMigration({
id: '0011-local-identity-credential',
statements: [
`
CREATE TABLE "QingLong3IdentitySubjects" (
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"status" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
"updated_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("subject_type", "subject_id"),
CONSTRAINT ql3_local_identity_type_check CHECK (
"subject_type" IN ('user','api_app','mcp_client','agent','system','worker')
),
CONSTRAINT ql3_local_identity_id_check CHECK (
length("subject_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_identity_status_check CHECK (
"status" IN ('active','disabled')
),
CONSTRAINT ql3_local_identity_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_identity_time_check CHECK (
"created_at_ms" >= 0 AND "updated_at_ms" >= "created_at_ms"
)
)
`,
`
CREATE INDEX "ql3_local_identity_status_idx"
ON "QingLong3IdentitySubjects" (
"status", "subject_type", "subject_id"
)
`,
`
CREATE TABLE "QingLong3ApiCredentials" (
"credential_id" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"state" TEXT NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"secret_digest" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
"not_before_at_ms" INTEGER NOT NULL,
"expires_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("credential_id", "version"),
FOREIGN KEY ("subject_type", "subject_id")
REFERENCES "QingLong3IdentitySubjects" ("subject_type", "subject_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_credentials_id_check CHECK (
length("credential_id") BETWEEN 1 AND 64
AND "credential_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
),
CONSTRAINT ql3_local_credentials_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_credentials_state_check CHECK (
"state" IN ('active','revoked')
),
CONSTRAINT ql3_local_credentials_subject_type_check CHECK (
"subject_type" IN ('user','api_app','mcp_client','agent')
),
CONSTRAINT ql3_local_credentials_subject_id_check CHECK (
length("subject_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_credentials_digest_check CHECK (
length("secret_digest") = 64
AND "secret_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_credentials_lifetime_check CHECK (
"created_at_ms" >= 0
AND "not_before_at_ms" >= "created_at_ms"
AND "expires_at_ms" > "not_before_at_ms"
)
)
`,
`
CREATE INDEX "ql3_local_credentials_current_idx"
ON "QingLong3ApiCredentials" ("credential_id", "version" DESC)
`,
`
CREATE INDEX "ql3_local_credentials_subject_idx"
ON "QingLong3ApiCredentials" (
"subject_type", "subject_id", "credential_id", "version" DESC
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0012CapabilityV6Migration = defineLocalSqliteMigration({
id: '0012-capability-v6',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 6,
migration_id = '0011-local-identity-credential',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 5
AND migration_id = '0009-local-project-policy-audit'
AND 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_security_audit":1,"local_secret_authorized_mutation":1}'
`,
],
});
@@ -0,0 +1,193 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0013LocalOwnerBootstrapMigration =
defineLocalSqliteMigration({
id: '0013-local-owner-bootstrap',
statements: [
`
CREATE TABLE "QingLong3LocalIdentityProvisionings" (
"slot" INTEGER PRIMARY KEY NOT NULL,
"mutation_id" TEXT NOT NULL,
"request_id" TEXT NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"credential_id" TEXT NOT NULL,
"credential_version" INTEGER NOT NULL,
"issuer_authentication_id" TEXT NOT NULL,
"issuer_authenticated_at_ms" INTEGER NOT NULL,
"issuer_expires_at_ms" INTEGER NOT NULL,
"audit_event_id" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("subject_type", "subject_id")
REFERENCES "QingLong3IdentitySubjects" ("subject_type", "subject_id")
ON DELETE RESTRICT,
FOREIGN KEY ("credential_id", "credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_provisioning_singleton_check CHECK ("slot" = 1),
CONSTRAINT ql3_local_provisioning_mutation_check CHECK (
length("mutation_id") = 36
),
CONSTRAINT ql3_local_provisioning_request_check CHECK (
length("request_id") BETWEEN 1 AND 128
),
CONSTRAINT ql3_local_provisioning_subject_check CHECK (
"subject_type" = 'user' AND length("subject_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_local_provisioning_credential_check CHECK (
length("credential_id") BETWEEN 1 AND 64 AND "credential_version" = 1
),
CONSTRAINT ql3_local_provisioning_issuer_check CHECK (
length("issuer_authentication_id") BETWEEN 1 AND 128
AND "issuer_authenticated_at_ms" <= "created_at_ms"
AND "issuer_expires_at_ms" > "created_at_ms"
),
CONSTRAINT ql3_local_provisioning_audit_check CHECK (
"audit_event_id" = "mutation_id"
),
CONSTRAINT ql3_local_provisioning_time_check CHECK ("created_at_ms" >= 0)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_provisioning_mutation_uidx"
ON "QingLong3LocalIdentityProvisionings" ("mutation_id")
`,
`
CREATE UNIQUE INDEX "ql3_local_provisioning_subject_uidx"
ON "QingLong3LocalIdentityProvisionings" ("subject_type", "subject_id")
`,
`
CREATE UNIQUE INDEX "ql3_local_provisioning_credential_uidx"
ON "QingLong3LocalIdentityProvisionings" (
"credential_id", "credential_version"
)
`,
`
CREATE TABLE "QingLong3LocalOwnerBootstrapChallenges" (
"project_id" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"issue_mutation_id" TEXT NOT NULL,
"issue_request_id" TEXT NOT NULL,
"challenge_id" TEXT NOT NULL,
"token_digest" TEXT NOT NULL,
"issuer_authentication_id" TEXT NOT NULL,
"issuer_authenticated_at_ms" INTEGER NOT NULL,
"issuer_expires_at_ms" INTEGER NOT NULL,
"issued_at_ms" INTEGER NOT NULL,
"expires_at_ms" INTEGER NOT NULL,
"issue_audit_event_id" TEXT NOT NULL,
"consumed_at_ms" INTEGER,
"claim_mutation_id" TEXT,
"claim_request_id" TEXT,
"claimed_subject_type" TEXT,
"claimed_subject_id" TEXT,
"credential_id" TEXT,
"credential_version" INTEGER,
"claim_authentication_id" TEXT,
"claim_authenticated_at_ms" INTEGER,
"claim_expires_at_ms" INTEGER,
"claim_assurance" TEXT,
"claim_audit_event_id" TEXT,
PRIMARY KEY ("project_id", "version"),
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("issue_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id") ON DELETE RESTRICT,
FOREIGN KEY ("claimed_subject_type", "claimed_subject_id")
REFERENCES "QingLong3IdentitySubjects" ("subject_type", "subject_id")
ON DELETE RESTRICT,
FOREIGN KEY ("credential_id", "credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("claim_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id") ON DELETE RESTRICT,
CONSTRAINT ql3_local_owner_challenge_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_owner_challenge_issue_identity_check CHECK (
length("issue_mutation_id") = 36
AND length("issue_request_id") BETWEEN 1 AND 128
AND "issue_audit_event_id" = "issue_mutation_id"
),
CONSTRAINT ql3_local_owner_challenge_id_check CHECK (
length("challenge_id") = 22
AND "challenge_id" NOT GLOB '*[^A-Za-z0-9_-]*'
),
CONSTRAINT ql3_local_owner_challenge_digest_check CHECK (
length("token_digest") = 64
AND "token_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_owner_challenge_issuer_check CHECK (
length("issuer_authentication_id") BETWEEN 1 AND 128
AND "issuer_authenticated_at_ms" <= "issued_at_ms"
AND "issuer_expires_at_ms" > "issued_at_ms"
),
CONSTRAINT ql3_local_owner_challenge_lifetime_check CHECK (
"issued_at_ms" >= 0
AND "expires_at_ms" > "issued_at_ms"
AND "expires_at_ms" - "issued_at_ms" BETWEEN 60000 AND 1800000
),
CONSTRAINT ql3_local_owner_challenge_claim_shape_check CHECK (
(
"consumed_at_ms" IS NULL
AND "claim_mutation_id" IS NULL
AND "claim_request_id" IS NULL
AND "claimed_subject_type" IS NULL
AND "claimed_subject_id" IS NULL
AND "credential_id" IS NULL
AND "credential_version" IS NULL
AND "claim_authentication_id" IS NULL
AND "claim_authenticated_at_ms" IS NULL
AND "claim_expires_at_ms" IS NULL
AND "claim_assurance" IS NULL
AND "claim_audit_event_id" IS NULL
)
OR (
"consumed_at_ms" >= "issued_at_ms"
AND "consumed_at_ms" < "expires_at_ms"
AND length("claim_mutation_id") = 36
AND length("claim_request_id") BETWEEN 1 AND 128
AND "claimed_subject_type" = 'user'
AND length("claimed_subject_id") BETWEEN 1 AND 255
AND length("credential_id") BETWEEN 1 AND 64
AND "credential_version" BETWEEN 1 AND 2147483647
AND length("claim_authentication_id") BETWEEN 1 AND 128
AND "claim_authenticated_at_ms" <= "consumed_at_ms"
AND "claim_expires_at_ms" > "consumed_at_ms"
AND "claim_assurance" = 'single_factor'
AND "claim_audit_event_id" = "claim_mutation_id"
)
)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_challenge_issue_mutation_uidx"
ON "QingLong3LocalOwnerBootstrapChallenges" ("issue_mutation_id")
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_challenge_id_uidx"
ON "QingLong3LocalOwnerBootstrapChallenges" ("challenge_id")
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_challenge_claim_mutation_uidx"
ON "QingLong3LocalOwnerBootstrapChallenges" ("claim_mutation_id")
WHERE "claim_mutation_id" IS NOT NULL
`,
`
CREATE INDEX "ql3_local_owner_challenge_current_idx"
ON "QingLong3LocalOwnerBootstrapChallenges" (
"project_id", "version" DESC
)
`,
`
CREATE INDEX "ql3_local_owner_challenge_expiry_idx"
ON "QingLong3LocalOwnerBootstrapChallenges" (
"project_id", "expires_at_ms", "version" DESC
)
WHERE "consumed_at_ms" IS NULL
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0014CapabilityV7Migration = defineLocalSqliteMigration({
id: '0014-capability-v7',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 7,
migration_id = '0013-local-owner-bootstrap',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 6
AND migration_id = '0011-local-identity-credential'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1}'
`,
],
});
@@ -0,0 +1,73 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0015LocalOwnerDeliveryAcknowledgementsMigration =
defineLocalSqliteMigration({
id: '0015-local-owner-delivery-acknowledgements',
statements: [
`
CREATE TABLE "QingLong3LocalOwnerDeliveryAcknowledgements" (
"mutation_id" TEXT PRIMARY KEY NOT NULL,
"kind" TEXT NOT NULL,
"request_id" TEXT NOT NULL,
"project_id" TEXT,
"subject_id" TEXT,
"credential_id" TEXT,
"challenge_id" TEXT,
"fact_digest" TEXT NOT NULL,
"delivery_digest" TEXT NOT NULL,
"ttl_ms" INTEGER NOT NULL,
"acknowledged_at_ms" INTEGER NOT NULL,
"provisioning_mutation_id" TEXT,
"challenge_mutation_id" TEXT,
FOREIGN KEY ("provisioning_mutation_id")
REFERENCES "QingLong3LocalIdentityProvisionings" ("mutation_id")
ON DELETE RESTRICT,
FOREIGN KEY ("challenge_mutation_id")
REFERENCES "QingLong3LocalOwnerBootstrapChallenges" ("issue_mutation_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_owner_delivery_ack_mutation_check CHECK (
length("mutation_id") = 36
),
CONSTRAINT ql3_local_owner_delivery_ack_request_check CHECK (
length("request_id") BETWEEN 1 AND 128
),
CONSTRAINT ql3_local_owner_delivery_ack_digest_check CHECK (
length("fact_digest") = 64
AND "fact_digest" NOT GLOB '*[^0-9a-f]*'
AND length("delivery_digest") = 64
AND "delivery_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_owner_delivery_ack_time_check CHECK (
"ttl_ms" > 0 AND "acknowledged_at_ms" >= 0
),
CONSTRAINT ql3_local_owner_delivery_ack_shape_check CHECK (
(
"kind" = 'credential'
AND "project_id" IS NULL
AND length("subject_id") = 26
AND "subject_id" GLOB 'usr_*'
AND "subject_id" NOT GLOB '*[^A-Za-z0-9_-]*'
AND length("credential_id") = 26
AND "credential_id" GLOB 'own_*'
AND "credential_id" NOT GLOB '*[^A-Za-z0-9_-]*'
AND "challenge_id" IS NULL
AND "provisioning_mutation_id" = "mutation_id"
AND "challenge_mutation_id" IS NULL
AND "ttl_ms" BETWEEN 600000 AND 604800000
)
OR (
"kind" = 'challenge'
AND length("project_id") BETWEEN 1 AND 128
AND "subject_id" IS NULL
AND "credential_id" IS NULL
AND length("challenge_id") = 22
AND "challenge_id" NOT GLOB '*[^A-Za-z0-9_-]*'
AND "provisioning_mutation_id" IS NULL
AND "challenge_mutation_id" = "mutation_id"
AND "ttl_ms" BETWEEN 60000 AND 1800000
)
)
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0016CapabilityV8Migration = defineLocalSqliteMigration({
id: '0016-capability-v8',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 8,
migration_id = '0015-local-owner-delivery-acknowledgements',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 7
AND migration_id = '0013-local-owner-bootstrap'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1}'
`,
],
});
@@ -0,0 +1,36 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0017ApiCredentialPepperBindingsMigration =
defineLocalSqliteMigration({
id: '0017-api-credential-pepper-bindings',
statements: [
`
CREATE TABLE "QingLong3ApiCredentialPepperBindings" (
"credential_id" TEXT NOT NULL,
"credential_version" INTEGER NOT NULL,
"pepper_key_id" TEXT NOT NULL,
PRIMARY KEY ("credential_id", "credential_version"),
FOREIGN KEY ("credential_id", "credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_credential_pepper_key_id_check CHECK (
length("pepper_key_id") BETWEEN 1 AND 64
AND "pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
)
)
`,
`
INSERT INTO "QingLong3ApiCredentialPepperBindings" (
"credential_id", "credential_version", "pepper_key_id"
)
SELECT "credential_id", "version", 'legacy-v1'
FROM "QingLong3ApiCredentials"
`,
`
CREATE INDEX "ql3_local_credential_pepper_key_idx"
ON "QingLong3ApiCredentialPepperBindings" (
"pepper_key_id", "credential_id", "credential_version"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0018CapabilityV9Migration = defineLocalSqliteMigration({
id: '0018-capability-v9',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 9,
migration_id = '0017-api-credential-pepper-bindings',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 8
AND migration_id = '0015-local-owner-delivery-acknowledgements'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1}'
`,
],
});
@@ -0,0 +1,182 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0019LocalOwnerPepperCatalogMigration =
defineLocalSqliteMigration({
id: '0019-local-owner-pepper-catalog',
statements: [
`
CREATE TABLE "QingLong3LocalOwnerPepperKeys" (
"pepper_key_id" TEXT PRIMARY KEY,
"material_digest" TEXT,
"backup_digest" TEXT,
"state" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"register_mutation_id" TEXT,
"activate_mutation_id" TEXT,
"retire_mutation_id" TEXT,
"registered_at_ms" INTEGER NOT NULL,
"activated_at_ms" INTEGER,
"retired_at_ms" INTEGER,
CONSTRAINT ql3_local_owner_pepper_key_id_check CHECK (
length("pepper_key_id") BETWEEN 1 AND 64
AND "pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
),
CONSTRAINT ql3_local_owner_pepper_digest_check CHECK (
("material_digest" IS NULL AND "backup_digest" IS NULL)
OR (
length("material_digest") = 64
AND "material_digest" NOT GLOB '*[^0-9a-f]*'
AND length("backup_digest") = 64
AND "backup_digest" NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_local_owner_pepper_state_check CHECK (
"state" IN ('recovery_required', 'staged', 'active', 'retired')
),
CONSTRAINT ql3_local_owner_pepper_version_check CHECK (
"version" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_owner_pepper_mutation_check CHECK (
("register_mutation_id" IS NULL OR length("register_mutation_id") = 36)
AND ("activate_mutation_id" IS NULL OR length("activate_mutation_id") = 36)
AND ("retire_mutation_id" IS NULL OR length("retire_mutation_id") = 36)
),
CONSTRAINT ql3_local_owner_pepper_time_check CHECK (
"registered_at_ms" >= 0
AND ("activated_at_ms" IS NULL OR "activated_at_ms" >= "registered_at_ms")
AND ("retired_at_ms" IS NULL OR "retired_at_ms" >= "activated_at_ms")
),
CONSTRAINT ql3_local_owner_pepper_shape_check CHECK (
("state" = 'recovery_required' AND "material_digest" IS NULL
AND "backup_digest" IS NULL AND "register_mutation_id" IS NULL
AND "activate_mutation_id" IS NULL AND "retire_mutation_id" IS NULL
AND "activated_at_ms" IS NULL AND "retired_at_ms" IS NULL)
OR ("state" = 'staged' AND "material_digest" IS NOT NULL
AND "backup_digest" IS NOT NULL AND "register_mutation_id" IS NOT NULL
AND "activate_mutation_id" IS NULL AND "retire_mutation_id" IS NULL
AND "activated_at_ms" IS NULL AND "retired_at_ms" IS NULL)
OR ("state" = 'active' AND "material_digest" IS NOT NULL
AND "backup_digest" IS NOT NULL AND "register_mutation_id" IS NOT NULL
AND "activate_mutation_id" IS NOT NULL AND "retire_mutation_id" IS NULL
AND "activated_at_ms" IS NOT NULL AND "retired_at_ms" IS NULL)
OR ("state" = 'retired' AND "material_digest" IS NOT NULL
AND "backup_digest" IS NOT NULL AND "register_mutation_id" IS NOT NULL
AND "activate_mutation_id" IS NOT NULL AND "retire_mutation_id" IS NOT NULL
AND "activated_at_ms" IS NOT NULL AND "retired_at_ms" IS NOT NULL)
)
)
`,
`
INSERT INTO "QingLong3LocalOwnerPepperKeys" (
"pepper_key_id", "state", "version", "registered_at_ms"
)
SELECT 'legacy-v1', 'recovery_required', 1, 0
WHERE EXISTS (SELECT 1 FROM "QingLong3ApiCredentialPepperBindings" LIMIT 1)
`,
`
ALTER TABLE "QingLong3ApiCredentialPepperBindings"
RENAME TO "QingLong3ApiCredentialPepperBindingsBeforeCatalog"
`,
`
CREATE TABLE "QingLong3ApiCredentialPepperBindings" (
"credential_id" TEXT NOT NULL,
"credential_version" INTEGER NOT NULL,
"pepper_key_id" TEXT NOT NULL,
PRIMARY KEY ("credential_id", "credential_version"),
FOREIGN KEY ("credential_id", "credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("pepper_key_id")
REFERENCES "QingLong3LocalOwnerPepperKeys" ("pepper_key_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_credential_pepper_key_id_check CHECK (
length("pepper_key_id") BETWEEN 1 AND 64
AND "pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
)
)
`,
`
INSERT INTO "QingLong3ApiCredentialPepperBindings" (
"credential_id", "credential_version", "pepper_key_id"
)
SELECT "credential_id", "credential_version", "pepper_key_id"
FROM "QingLong3ApiCredentialPepperBindingsBeforeCatalog"
`,
`
DROP TABLE "QingLong3ApiCredentialPepperBindingsBeforeCatalog"
`,
`
CREATE INDEX "ql3_local_credential_pepper_key_idx"
ON "QingLong3ApiCredentialPepperBindings" (
"pepper_key_id", "credential_id", "credential_version"
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_register_mutation_uidx"
ON "QingLong3LocalOwnerPepperKeys" ("register_mutation_id")
WHERE "register_mutation_id" IS NOT NULL
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_single_active_uidx"
ON "QingLong3LocalOwnerPepperKeys" ("state")
WHERE "state" = 'active'
`,
`
CREATE INDEX "ql3_local_owner_pepper_state_idx"
ON "QingLong3LocalOwnerPepperKeys" ("state", "pepper_key_id")
`,
`
CREATE TABLE "QingLong3LocalOwnerPepperActivations" (
"generation" INTEGER PRIMARY KEY,
"mutation_id" TEXT NOT NULL,
"expected_generation" INTEGER NOT NULL,
"previous_pepper_key_id" TEXT,
"active_pepper_key_id" TEXT NOT NULL,
"material_digest" TEXT NOT NULL,
"backup_digest" TEXT NOT NULL,
"activated_at_ms" INTEGER NOT NULL,
CONSTRAINT ql3_local_owner_pepper_activation_generation_check CHECK (
"generation" BETWEEN 1 AND 2147483647
AND "expected_generation" = "generation" - 1
),
CONSTRAINT ql3_local_owner_pepper_activation_mutation_check CHECK (
length("mutation_id") = 36
),
CONSTRAINT ql3_local_owner_pepper_activation_key_check CHECK (
length("active_pepper_key_id") BETWEEN 1 AND 64
AND "active_pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND ("previous_pepper_key_id" IS NULL OR (
length("previous_pepper_key_id") BETWEEN 1 AND 64
AND "previous_pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND "previous_pepper_key_id" <> "active_pepper_key_id"
))
),
CONSTRAINT ql3_local_owner_pepper_activation_digest_check CHECK (
length("material_digest") = 64
AND "material_digest" NOT GLOB '*[^0-9a-f]*'
AND length("backup_digest") = 64
AND "backup_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_owner_pepper_activation_time_check CHECK (
"activated_at_ms" >= 0
),
FOREIGN KEY ("previous_pepper_key_id")
REFERENCES "QingLong3LocalOwnerPepperKeys" ("pepper_key_id")
ON DELETE RESTRICT,
FOREIGN KEY ("active_pepper_key_id")
REFERENCES "QingLong3LocalOwnerPepperKeys" ("pepper_key_id")
ON DELETE RESTRICT
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_activation_mutation_uidx"
ON "QingLong3LocalOwnerPepperActivations" ("mutation_id")
`,
`
CREATE INDEX "ql3_local_owner_pepper_activation_key_idx"
ON "QingLong3LocalOwnerPepperActivations" (
"active_pepper_key_id", "generation" DESC
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0020CapabilityV10Migration = defineLocalSqliteMigration({
id: '0020-capability-v10',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 10,
migration_id = '0019-local-owner-pepper-catalog',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1,"local_owner_pepper_catalog":1}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 9
AND migration_id = '0017-api-credential-pepper-bindings'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1}'
`,
],
});
@@ -0,0 +1,140 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0021LocalOwnerCredentialRecoveryMigration =
defineLocalSqliteMigration({
id: '0021-local-owner-credential-recovery',
statements: [
`
CREATE TABLE "QingLong3LocalOwnerCredentialRecoveries" (
"issue_mutation_id" TEXT PRIMARY KEY NOT NULL,
"issue_request_id" TEXT NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"previous_credential_id" TEXT NOT NULL,
"previous_credential_version" INTEGER NOT NULL,
"replacement_credential_id" TEXT NOT NULL,
"replacement_credential_version" INTEGER NOT NULL,
"state" TEXT NOT NULL,
"issued_at_ms" INTEGER NOT NULL,
"issue_audit_event_id" TEXT NOT NULL,
"delivery_digest" TEXT,
"acknowledged_at_ms" INTEGER,
"complete_mutation_id" TEXT,
"complete_request_id" TEXT,
"revoked_credential_version" INTEGER,
"completed_at_ms" INTEGER,
"complete_audit_event_id" TEXT,
FOREIGN KEY ("subject_type", "subject_id")
REFERENCES "QingLong3IdentitySubjects" ("subject_type", "subject_id")
ON DELETE RESTRICT,
FOREIGN KEY ("previous_credential_id", "previous_credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("replacement_credential_id", "replacement_credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("previous_credential_id", "revoked_credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("issue_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
FOREIGN KEY ("complete_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_owner_recovery_mutation_check CHECK (
length("issue_mutation_id") = 36
AND "issue_audit_event_id" = "issue_mutation_id"
AND ("complete_mutation_id" IS NULL OR (
length("complete_mutation_id") = 36
AND "complete_audit_event_id" = "complete_mutation_id"
AND "complete_mutation_id" <> "issue_mutation_id"
))
),
CONSTRAINT ql3_local_owner_recovery_request_check CHECK (
length("issue_request_id") BETWEEN 1 AND 128
AND ("complete_request_id" IS NULL
OR length("complete_request_id") BETWEEN 1 AND 128)
),
CONSTRAINT ql3_local_owner_recovery_identity_check CHECK (
"subject_type" = 'user'
AND length("subject_id") = 26
AND "subject_id" GLOB 'usr_*'
AND "subject_id" NOT GLOB '*[^A-Za-z0-9_-]*'
),
CONSTRAINT ql3_local_owner_recovery_credential_check CHECK (
length("previous_credential_id") BETWEEN 1 AND 64
AND "previous_credential_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND "previous_credential_version" BETWEEN 1 AND 2147483646
AND length("replacement_credential_id") BETWEEN 1 AND 64
AND "replacement_credential_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND "replacement_credential_id" <> "previous_credential_id"
AND "replacement_credential_version" = 1
AND ("revoked_credential_version" IS NULL
OR "revoked_credential_version" = "previous_credential_version" + 1)
),
CONSTRAINT ql3_local_owner_recovery_digest_check CHECK (
"delivery_digest" IS NULL OR (
length("delivery_digest") = 64
AND "delivery_digest" NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_local_owner_recovery_time_check CHECK (
"issued_at_ms" >= 0
AND ("acknowledged_at_ms" IS NULL
OR "acknowledged_at_ms" >= "issued_at_ms")
AND ("completed_at_ms" IS NULL
OR "completed_at_ms" >= "acknowledged_at_ms")
),
CONSTRAINT ql3_local_owner_recovery_shape_check CHECK (
("state" = 'issued'
AND "delivery_digest" IS NULL
AND "acknowledged_at_ms" IS NULL
AND "complete_mutation_id" IS NULL
AND "complete_request_id" IS NULL
AND "revoked_credential_version" IS NULL
AND "completed_at_ms" IS NULL
AND "complete_audit_event_id" IS NULL)
OR ("state" = 'acknowledged'
AND "delivery_digest" IS NOT NULL
AND "acknowledged_at_ms" IS NOT NULL
AND "complete_mutation_id" IS NULL
AND "complete_request_id" IS NULL
AND "revoked_credential_version" IS NULL
AND "completed_at_ms" IS NULL
AND "complete_audit_event_id" IS NULL)
OR ("state" = 'completed'
AND "delivery_digest" IS NOT NULL
AND "acknowledged_at_ms" IS NOT NULL
AND "complete_mutation_id" IS NOT NULL
AND "complete_request_id" IS NOT NULL
AND "revoked_credential_version" IS NOT NULL
AND "completed_at_ms" IS NOT NULL
AND "complete_audit_event_id" IS NOT NULL)
)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_recovery_open_subject_uidx"
ON "QingLong3LocalOwnerCredentialRecoveries" ("subject_id")
WHERE "state" <> 'completed'
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_recovery_replacement_uidx"
ON "QingLong3LocalOwnerCredentialRecoveries" (
"replacement_credential_id", "replacement_credential_version"
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_recovery_complete_mutation_uidx"
ON "QingLong3LocalOwnerCredentialRecoveries" ("complete_mutation_id")
WHERE "complete_mutation_id" IS NOT NULL
`,
`
CREATE INDEX "ql3_local_owner_recovery_previous_idx"
ON "QingLong3LocalOwnerCredentialRecoveries" (
"previous_credential_id", "previous_credential_version", "state"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0022CapabilityV11Migration = defineLocalSqliteMigration({
id: '0022-capability-v11',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 11,
migration_id = '0021-local-owner-credential-recovery',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 10
AND migration_id = '0019-local-owner-pepper-catalog'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":1,"local_owner_bootstrap":1,"local_owner_delivery_acknowledgement":1,"api_credential_pepper_binding":1,"local_owner_pepper_catalog":1}'
`,
],
});
@@ -0,0 +1,133 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0023LocalOwnerPepperMaterialGcMigration =
defineLocalSqliteMigration({
id: '0023-local-owner-pepper-material-gc',
statements: [
`
CREATE TABLE "QingLong3LocalOwnerPepperMaterialGc" (
"prepare_mutation_id" TEXT PRIMARY KEY NOT NULL,
"prepare_request_id" TEXT NOT NULL,
"pepper_key_id" TEXT NOT NULL,
"material_digest" TEXT NOT NULL,
"backup_material_digest" TEXT NOT NULL,
"active_pepper_key_id" TEXT NOT NULL,
"active_generation" INTEGER NOT NULL,
"active_material_digest" TEXT NOT NULL,
"retention_policy_version" INTEGER NOT NULL,
"acknowledgement_retention_ms" INTEGER NOT NULL,
"audit_retention_ms" INTEGER NOT NULL,
"backup_retention_ms" INTEGER NOT NULL,
"retention_policy_digest" TEXT NOT NULL,
"references_inspected_at_ms" INTEGER NOT NULL,
"retention_eligible_at_ms" INTEGER NOT NULL,
"prepared_at_ms" INTEGER NOT NULL,
"prepare_audit_event_id" TEXT NOT NULL,
"state" TEXT NOT NULL,
"complete_mutation_id" TEXT,
"complete_request_id" TEXT,
"destruction_proof_digest" TEXT,
"completed_at_ms" INTEGER,
"complete_audit_event_id" TEXT,
FOREIGN KEY ("pepper_key_id")
REFERENCES "QingLong3LocalOwnerPepperKeys" ("pepper_key_id")
ON DELETE RESTRICT,
FOREIGN KEY ("active_pepper_key_id")
REFERENCES "QingLong3LocalOwnerPepperKeys" ("pepper_key_id")
ON DELETE RESTRICT,
FOREIGN KEY ("active_generation")
REFERENCES "QingLong3LocalOwnerPepperActivations" ("generation")
ON DELETE RESTRICT,
FOREIGN KEY ("prepare_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
FOREIGN KEY ("complete_audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_owner_pepper_gc_mutation_check CHECK (
length("prepare_mutation_id") = 36
AND "prepare_audit_event_id" = "prepare_mutation_id"
AND ("complete_mutation_id" IS NULL OR (
length("complete_mutation_id") = 36
AND "complete_mutation_id" <> "prepare_mutation_id"
AND "complete_audit_event_id" = "complete_mutation_id"
))
),
CONSTRAINT ql3_local_owner_pepper_gc_request_check CHECK (
length("prepare_request_id") BETWEEN 1 AND 128
AND ("complete_request_id" IS NULL
OR length("complete_request_id") BETWEEN 1 AND 128)
),
CONSTRAINT ql3_local_owner_pepper_gc_key_check CHECK (
length("pepper_key_id") BETWEEN 1 AND 64
AND "pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND length("active_pepper_key_id") BETWEEN 1 AND 64
AND "active_pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND "pepper_key_id" <> "active_pepper_key_id"
AND "active_generation" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_local_owner_pepper_gc_digest_check CHECK (
length("material_digest") = 64
AND "material_digest" NOT GLOB '*[^0-9a-f]*'
AND length("backup_material_digest") = 64
AND "backup_material_digest" NOT GLOB '*[^0-9a-f]*'
AND length("active_material_digest") = 64
AND "active_material_digest" NOT GLOB '*[^0-9a-f]*'
AND length("retention_policy_digest") = 64
AND "retention_policy_digest" NOT GLOB '*[^0-9a-f]*'
AND ("destruction_proof_digest" IS NULL OR (
length("destruction_proof_digest") = 64
AND "destruction_proof_digest" NOT GLOB '*[^0-9a-f]*'
))
),
CONSTRAINT ql3_local_owner_pepper_gc_retention_check CHECK (
"retention_policy_version" = 1
AND "acknowledgement_retention_ms" BETWEEN 604800000 AND 315360000000
AND "audit_retention_ms" BETWEEN 2592000000 AND 315360000000
AND "backup_retention_ms" BETWEEN 2592000000 AND 315360000000
),
CONSTRAINT ql3_local_owner_pepper_gc_time_check CHECK (
"references_inspected_at_ms" = "prepared_at_ms"
AND "retention_eligible_at_ms" <= "prepared_at_ms"
AND "prepared_at_ms" >= 0
AND ("completed_at_ms" IS NULL
OR "completed_at_ms" >= "prepared_at_ms")
),
CONSTRAINT ql3_local_owner_pepper_gc_shape_check CHECK (
("state" = 'prepared'
AND "complete_mutation_id" IS NULL
AND "complete_request_id" IS NULL
AND "destruction_proof_digest" IS NULL
AND "completed_at_ms" IS NULL
AND "complete_audit_event_id" IS NULL)
OR ("state" = 'completed'
AND "complete_mutation_id" IS NOT NULL
AND "complete_request_id" IS NOT NULL
AND "destruction_proof_digest" IS NOT NULL
AND "completed_at_ms" IS NOT NULL
AND "complete_audit_event_id" IS NOT NULL)
)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_gc_key_uidx"
ON "QingLong3LocalOwnerPepperMaterialGc" ("pepper_key_id")
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_gc_open_uidx"
ON "QingLong3LocalOwnerPepperMaterialGc" ("state")
WHERE "state" = 'prepared'
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_pepper_gc_complete_mutation_uidx"
ON "QingLong3LocalOwnerPepperMaterialGc" ("complete_mutation_id")
WHERE "complete_mutation_id" IS NOT NULL
`,
`
CREATE INDEX "ql3_local_owner_pepper_gc_state_idx"
ON "QingLong3LocalOwnerPepperMaterialGc" (
"state", "retention_eligible_at_ms", "pepper_key_id"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0024CapabilityV12Migration = defineLocalSqliteMigration({
id: '0024-capability-v12',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 12,
migration_id = '0023-local-owner-pepper-material-gc',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 11
AND migration_id = '0021-local-owner-credential-recovery'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,91 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0025LocalOwnerDeliveryAcknowledgementGcMigration =
defineLocalSqliteMigration({
id: '0025-local-owner-delivery-acknowledgement-gc',
statements: [
`
CREATE TABLE "QingLong3LocalOwnerDeliveryAcknowledgementGc" (
"gc_mutation_id" TEXT PRIMARY KEY NOT NULL,
"gc_request_id" TEXT NOT NULL,
"acknowledgement_mutation_id" TEXT NOT NULL,
"acknowledgement_kind" TEXT NOT NULL,
"delivery_digest" TEXT NOT NULL,
"acknowledged_at_ms" INTEGER NOT NULL,
"acknowledgement_semantic_digest" TEXT NOT NULL,
"bridge_clear_evidence_digest" TEXT NOT NULL,
"retention_policy_version" INTEGER NOT NULL,
"replay_retention_ms" INTEGER NOT NULL,
"audit_retention_ms" INTEGER NOT NULL,
"retention_policy_digest" TEXT NOT NULL,
"retention_eligible_at_ms" INTEGER NOT NULL,
"compacted_at_ms" INTEGER NOT NULL,
"audit_event_id" TEXT NOT NULL,
"provisioning_mutation_id" TEXT,
"challenge_mutation_id" TEXT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
FOREIGN KEY ("provisioning_mutation_id")
REFERENCES "QingLong3LocalIdentityProvisionings" ("mutation_id")
ON DELETE RESTRICT,
FOREIGN KEY ("challenge_mutation_id")
REFERENCES "QingLong3LocalOwnerBootstrapChallenges" ("issue_mutation_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_local_owner_delivery_ack_gc_mutation_check CHECK (
length("gc_mutation_id") = 36
AND "audit_event_id" = "gc_mutation_id"
AND length("acknowledgement_mutation_id") = 36
AND "acknowledgement_mutation_id" <> "gc_mutation_id"
),
CONSTRAINT ql3_local_owner_delivery_ack_gc_request_check CHECK (
length("gc_request_id") BETWEEN 1 AND 128
),
CONSTRAINT ql3_local_owner_delivery_ack_gc_digest_check CHECK (
length("delivery_digest") = 64
AND "delivery_digest" NOT GLOB '*[^0-9a-f]*'
AND length("acknowledgement_semantic_digest") = 64
AND "acknowledgement_semantic_digest" NOT GLOB '*[^0-9a-f]*'
AND length("bridge_clear_evidence_digest") = 64
AND "bridge_clear_evidence_digest" NOT GLOB '*[^0-9a-f]*'
AND length("retention_policy_digest") = 64
AND "retention_policy_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_owner_delivery_ack_gc_retention_check CHECK (
"retention_policy_version" = 1
AND "replay_retention_ms" BETWEEN 2592000000 AND 315360000000
AND "audit_retention_ms" BETWEEN 2592000000 AND 315360000000
),
CONSTRAINT ql3_local_owner_delivery_ack_gc_time_check CHECK (
"acknowledged_at_ms" >= 0
AND "retention_eligible_at_ms" <= "compacted_at_ms"
AND "compacted_at_ms" >= "acknowledged_at_ms"
),
CONSTRAINT ql3_local_owner_delivery_ack_gc_shape_check CHECK (
(
"acknowledgement_kind" = 'credential'
AND "provisioning_mutation_id" = "acknowledgement_mutation_id"
AND "challenge_mutation_id" IS NULL
)
OR (
"acknowledgement_kind" = 'challenge'
AND "provisioning_mutation_id" IS NULL
AND "challenge_mutation_id" = "acknowledgement_mutation_id"
)
)
)
`,
`
CREATE UNIQUE INDEX "ql3_local_owner_delivery_ack_gc_ack_uidx"
ON "QingLong3LocalOwnerDeliveryAcknowledgementGc" (
"acknowledgement_mutation_id"
)
`,
`
CREATE INDEX "ql3_local_owner_delivery_ack_gc_compacted_idx"
ON "QingLong3LocalOwnerDeliveryAcknowledgementGc" (
"acknowledgement_kind", "compacted_at_ms", "acknowledgement_mutation_id"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0026CapabilityV13Migration = defineLocalSqliteMigration({
id: '0026-capability-v13',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 13,
migration_id = '0025-local-owner-delivery-acknowledgement-gc',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 12
AND migration_id = '0023-local-owner-pepper-material-gc'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,100 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0027TaskDefinitionsMigration = defineLocalSqliteMigration({
id: '0027-task-definitions',
statements: [
`
CREATE TABLE "QingLong3TaskDefinitions" (
"project_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"current_revision" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
"updated_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "task_id"),
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id")
ON DELETE RESTRICT,
CONSTRAINT ql3_task_definitions_id_check CHECK (
length("project_id") BETWEEN 1 AND 128
AND length("task_id") BETWEEN 1 AND 128
AND "project_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
AND "task_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
),
CONSTRAINT ql3_task_definitions_revision_check CHECK (
"current_revision" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_task_definitions_time_check CHECK (
"created_at_ms" >= 0 AND "updated_at_ms" >= "created_at_ms"
)
)
`,
`
CREATE TABLE "QingLong3TaskDefinitionRevisions" (
"project_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"revision" INTEGER NOT NULL,
"mutation_id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"kind" TEXT NOT NULL,
"spec_json" TEXT NOT NULL,
"labels_json" TEXT NOT NULL,
"enabled" INTEGER NOT NULL,
"content_digest" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "task_id", "revision"),
FOREIGN KEY ("project_id", "task_id")
REFERENCES "QingLong3TaskDefinitions" ("project_id", "task_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_task_definition_revisions_revision_check CHECK (
"revision" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_task_definition_revisions_mutation_check CHECK (
length("mutation_id") = 36
AND substr("mutation_id", 9, 1) = '-'
AND substr("mutation_id", 14, 1) = '-'
AND substr("mutation_id", 19, 1) = '-'
AND substr("mutation_id", 24, 1) = '-'
AND replace("mutation_id", '-', '') NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_task_definition_revisions_name_check CHECK (
length("name") BETWEEN 1 AND 255
AND ("description" IS NULL OR length("description") BETWEEN 1 AND 4096)
),
CONSTRAINT ql3_task_definition_revisions_kind_check CHECK (
"kind" IN ('script','command','workflow','agent','tool')
),
CONSTRAINT ql3_task_definition_revisions_spec_check CHECK (
json_valid("spec_json")
AND json_type("spec_json") = 'object'
AND length("spec_json") BETWEEN 1 AND 65536
),
CONSTRAINT ql3_task_definition_revisions_labels_check CHECK (
json_valid("labels_json")
AND json_type("labels_json") = 'object'
AND length("labels_json") BETWEEN 2 AND 16384
),
CONSTRAINT ql3_task_definition_revisions_enabled_check CHECK (
"enabled" IN (0, 1)
),
CONSTRAINT ql3_task_definition_revisions_digest_check CHECK (
length("content_digest") = 64
AND "content_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_task_definition_revisions_created_check CHECK (
"created_at_ms" >= 0
)
)
`,
`
CREATE UNIQUE INDEX "ql3_task_definition_revisions_mutation_uidx"
ON "QingLong3TaskDefinitionRevisions" ("mutation_id")
`,
`
CREATE INDEX "ql3_task_definition_revisions_project_kind_idx"
ON "QingLong3TaskDefinitionRevisions" (
"project_id", "kind", "enabled", "task_id", "revision"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0028CapabilityV14Migration = defineLocalSqliteMigration({
id: '0028-capability-v14',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 14,
migration_id = '0027-task-definitions',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 13
AND migration_id = '0025-local-owner-delivery-acknowledgement-gc'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,261 @@
import {
createLocalTaskExecutionRevision,
type LocalDispatchCommand,
} from '@qinglong/runtime-core/local-dispatch';
import {
normalizeTaskDefinitionRecord,
type TaskDefinitionRecord,
} from '@qinglong/runtime-core/task-definition';
import { compileLocalCommandTaskDefinition } from '@qinglong/runtime-core/task-definition-execution-compiler';
import {
BUILT_IN_COMMAND_TASK_SPEC_SCHEMA,
createBuiltInTaskSpecSemanticRegistry,
} from '@qinglong/runtime-core/task-spec-semantic';
import { LocalSqliteDispatchDefinitionStore } from '../task-definition/dispatchDefinitionStore';
import { defineLocalSqliteProgrammaticMigration } from './sqlMigration';
const REPLACEMENT_TABLE = `
CREATE TABLE "QingLong3LocalTaskExecutionRevisions_v15" (
"project_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"task_revision" TEXT NOT NULL,
"executor_type" TEXT NOT NULL,
"command_json" TEXT NOT NULL,
"working_directory" TEXT,
"timeout_ms" INTEGER,
"context_ref" TEXT NOT NULL,
"content_digest" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "task_id", "task_revision"),
CONSTRAINT ql3_local_revision_executor_check CHECK (
"executor_type" = 'local_process'
),
CONSTRAINT ql3_local_revision_command_check CHECK (
json_valid("command_json")
AND json_type("command_json") = 'object'
AND length("command_json") BETWEEN 1 AND 131072
),
CONSTRAINT ql3_local_revision_working_directory_check CHECK (
"working_directory" IS NULL
OR (length("working_directory") BETWEEN 1 AND 4096
AND substr("working_directory", 1, 1) = '/')
),
CONSTRAINT ql3_local_revision_timeout_check CHECK (
"timeout_ms" IS NULL OR "timeout_ms" BETWEEN 1 AND 31536000000
),
CONSTRAINT ql3_local_revision_digest_check CHECK (
length("content_digest") = 64
AND "content_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_local_revision_created_check CHECK ("created_at_ms" >= 0),
FOREIGN KEY ("context_ref")
REFERENCES "QingLong3LocalExecutionContextRecipes" ("context_ref")
ON DELETE RESTRICT
)
`;
type RevisionRow = Record<string, unknown>;
function requiredText(row: RevisionRow, key: string): string {
const value = row[key];
if (typeof value !== 'string') {
throw new TypeError(`Local execution revision ${key} is invalid`);
}
return value;
}
function optionalText(row: RevisionRow, key: string): string | undefined {
const value = row[key];
if (value === null) return undefined;
return requiredText(row, key);
}
function requiredInteger(row: RevisionRow, key: string): number {
const value = row[key];
if (!Number.isSafeInteger(value)) {
throw new TypeError(`Local execution revision ${key} is invalid`);
}
return value as number;
}
function optionalInteger(row: RevisionRow, key: string): number | undefined {
const value = row[key];
if (value === null) return undefined;
return requiredInteger(row, key);
}
function command(row: RevisionRow): LocalDispatchCommand {
try {
return JSON.parse(requiredText(row, 'commandJson')) as LocalDispatchCommand;
} catch {
throw new TypeError('Local execution revision commandJson is invalid');
}
}
function requiredJson(row: RevisionRow, key: string): unknown {
try {
return JSON.parse(requiredText(row, key)) as unknown;
} catch {
throw new TypeError(`TaskDefinition ${key} is invalid`);
}
}
function taskDefinition(row: RevisionRow): TaskDefinitionRecord {
const description = optionalText(row, 'description');
const enabled = requiredInteger(row, 'enabled');
if (enabled !== 0 && enabled !== 1) {
throw new TypeError('TaskDefinition enabled is invalid');
}
return normalizeTaskDefinitionRecord({
projectId: requiredText(row, 'projectId'),
taskId: requiredText(row, 'taskId'),
revision: requiredInteger(row, 'revision'),
mutationId: requiredText(row, 'mutationId'),
name: requiredText(row, 'name'),
...(description === undefined ? {} : { description }),
kind: requiredText(row, 'kind') as TaskDefinitionRecord['kind'],
spec: requiredJson(row, 'specJson') as TaskDefinitionRecord['spec'],
labels: requiredJson(row, 'labelsJson') as TaskDefinitionRecord['labels'],
enabled: enabled === 1,
contentDigest: requiredText(row, 'taskContentDigest'),
createdAtMs: requiredInteger(row, 'taskCreatedAtMs'),
updatedAtMs: requiredInteger(row, 'taskUpdatedAtMs'),
});
}
export const local0029LocalExecutionRevisionDigestMigration =
defineLocalSqliteProgrammaticMigration({
id: '0029-local-execution-revision-digest',
program: [
REPLACEMENT_TABLE,
`Read every legacy revision in primary-key order without buffering.
Parse and normalize command_json through
createLocalTaskExecutionRevision using digest domain
qinglong.local-task-execution-revision.v1 NUL. The digest covers
project, task, revision, executor, canonical command, optional working
directory, optional timeout and context ref; created_at_ms is excluded
so an exact semantic replay preserves the first observed timestamp.`,
`Insert every normalized row and computed lowercase SHA-256 digest into
QingLong3LocalTaskExecutionRevisions_v15. Reject malformed legacy rows,
count drift, constraint failures or digest failures so the enclosing
BEGIN IMMEDIATE transaction rolls the entire migration back.`,
`After the digest table replacement, read every historical enabled
qinglong/command@v1 TaskDefinition revision in primary-key order,
revalidate its stored TaskDefinition content digest and built-in
semantics, compile the deterministic local plan, and append its context
recipe and execution revision through exact-content replay. Skip
disabled and non-built-in revisions; reject missing Projects, corrupt
built-in records or pre-existing derived identity conflicts.`,
'DROP TABLE "QingLong3LocalTaskExecutionRevisions"',
`ALTER TABLE "QingLong3LocalTaskExecutionRevisions_v15"
RENAME TO "QingLong3LocalTaskExecutionRevisions"`,
],
up({ client }) {
client.exec(REPLACEMENT_TABLE);
const rows = client.prepare(
`SELECT "project_id" AS "projectId", "task_id" AS "taskId",
"task_revision" AS "taskRevision",
"executor_type" AS "executorType",
"command_json" AS "commandJson",
"working_directory" AS "workingDirectory",
"timeout_ms" AS "timeoutMs", "context_ref" AS "contextRef",
"created_at_ms" AS "createdAtMs"
FROM "QingLong3LocalTaskExecutionRevisions"
ORDER BY "project_id", "task_id", "task_revision"`,
);
const insert = client.prepare(
`INSERT INTO "QingLong3LocalTaskExecutionRevisions_v15" (
"project_id", "task_id", "task_revision", "executor_type",
"command_json", "working_directory", "timeout_ms", "context_ref",
"content_digest", "created_at_ms"
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
);
let backfilled = 0;
for (const value of rows.iterate() as Iterable<RevisionRow>) {
const executorType = requiredText(value, 'executorType');
if (executorType !== 'local_process') {
throw new TypeError('Local execution revision executorType is invalid');
}
const workingDirectory = optionalText(value, 'workingDirectory');
const timeoutMs = optionalInteger(value, 'timeoutMs');
const revision = createLocalTaskExecutionRevision({
projectId: requiredText(value, 'projectId'),
taskId: requiredText(value, 'taskId'),
taskRevision: requiredText(value, 'taskRevision'),
executorType,
command: command(value),
...(workingDirectory === undefined ? {} : { workingDirectory }),
...(timeoutMs === undefined ? {} : { timeoutMs }),
contextRef: requiredText(value, 'contextRef'),
createdAtMs: requiredInteger(value, 'createdAtMs'),
});
insert.run(
revision.projectId,
revision.taskId,
revision.taskRevision,
revision.executorType,
JSON.stringify(revision.command),
revision.workingDirectory ?? null,
revision.timeoutMs ?? null,
revision.contextRef,
revision.contentDigest,
revision.createdAtMs,
);
backfilled += 1;
}
const sourceCount = client
.prepare(
'SELECT COUNT(*) AS "count" FROM "QingLong3LocalTaskExecutionRevisions"',
)
.get() as { count?: unknown } | undefined;
if (
!sourceCount ||
!Number.isSafeInteger(sourceCount.count) ||
sourceCount.count !== backfilled
) {
throw new TypeError('Local execution revision backfill count drifted');
}
client.exec('DROP TABLE "QingLong3LocalTaskExecutionRevisions"');
client.exec(
`ALTER TABLE "QingLong3LocalTaskExecutionRevisions_v15"
RENAME TO "QingLong3LocalTaskExecutionRevisions"`,
);
const semanticRegistry = createBuiltInTaskSpecSemanticRegistry();
const definitions = client.prepare(
`SELECT revision."project_id" AS "projectId",
revision."task_id" AS "taskId",
revision."revision" AS "revision",
revision."mutation_id" AS "mutationId",
revision."name" AS "name",
revision."description" AS "description",
revision."kind" AS "kind",
revision."spec_json" AS "specJson",
revision."labels_json" AS "labelsJson",
revision."enabled" AS "enabled",
revision."content_digest" AS "taskContentDigest",
head."created_at_ms" AS "taskCreatedAtMs",
revision."created_at_ms" AS "taskUpdatedAtMs"
FROM "QingLong3TaskDefinitionRevisions" AS revision
JOIN "QingLong3TaskDefinitions" AS head
ON head."project_id" = revision."project_id"
AND head."task_id" = revision."task_id"
ORDER BY revision."project_id", revision."task_id",
revision."revision"`,
);
const dispatchDefinitions = new LocalSqliteDispatchDefinitionStore(client);
for (const value of definitions.iterate() as Iterable<RevisionRow>) {
const definition = taskDefinition(value);
if (
!definition.enabled ||
definition.kind !== 'command' ||
definition.spec.schema !== BUILT_IN_COMMAND_TASK_SPEC_SCHEMA
) {
continue;
}
dispatchDefinitions.appendPlan(
compileLocalCommandTaskDefinition(definition, semanticRegistry),
);
}
},
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0030CapabilityV15Migration = defineLocalSqliteMigration({
id: '0030-capability-v15',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 15,
migration_id = '0029-local-execution-revision-digest',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 14
AND migration_id = '0027-task-definitions'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,111 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0031TriggerDefinitionsMigration = defineLocalSqliteMigration({
id: '0031-trigger-definitions',
statements: [
`
CREATE TABLE "QingLong3Triggers" (
"project_id" TEXT NOT NULL,
"trigger_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"current_revision" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
"updated_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "trigger_id"),
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id")
ON DELETE RESTRICT,
FOREIGN KEY ("project_id", "task_id")
REFERENCES "QingLong3TaskDefinitions" ("project_id", "task_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_triggers_id_check CHECK (
length("project_id") BETWEEN 1 AND 128
AND length("trigger_id") BETWEEN 1 AND 128
AND length("task_id") BETWEEN 1 AND 128
AND "project_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
AND "trigger_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
AND "task_id" NOT GLOB '*[' || char(0) || '-' || char(31) || char(127) || ']*'
),
CONSTRAINT ql3_triggers_revision_check CHECK (
"current_revision" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_triggers_time_check CHECK (
"created_at_ms" >= 0 AND "updated_at_ms" >= "created_at_ms"
)
)
`,
`
CREATE UNIQUE INDEX "ql3_triggers_task_uidx"
ON "QingLong3Triggers" ("project_id", "trigger_id", "task_id")
`,
`
CREATE TABLE "QingLong3TriggerRevisions" (
"project_id" TEXT NOT NULL,
"trigger_id" TEXT NOT NULL,
"revision" INTEGER NOT NULL,
"mutation_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"task_revision" INTEGER NOT NULL,
"task_content_digest" TEXT NOT NULL,
"spec_json" TEXT NOT NULL,
"enabled" INTEGER NOT NULL,
"content_digest" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
PRIMARY KEY ("project_id", "trigger_id", "revision"),
FOREIGN KEY ("project_id", "trigger_id", "task_id")
REFERENCES "QingLong3Triggers" ("project_id", "trigger_id", "task_id")
ON DELETE RESTRICT,
FOREIGN KEY ("project_id", "task_id", "task_revision")
REFERENCES "QingLong3TaskDefinitionRevisions" ("project_id", "task_id", "revision")
ON DELETE RESTRICT,
CONSTRAINT ql3_trigger_revisions_revision_check CHECK (
"revision" BETWEEN 1 AND 2147483647
AND "task_revision" BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_trigger_revisions_mutation_check CHECK (
length("mutation_id") = 36
AND substr("mutation_id", 9, 1) = '-'
AND substr("mutation_id", 14, 1) = '-'
AND substr("mutation_id", 19, 1) = '-'
AND substr("mutation_id", 24, 1) = '-'
AND replace("mutation_id", '-', '') NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_trigger_revisions_task_digest_check CHECK (
length("task_content_digest") = 64
AND "task_content_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_trigger_revisions_spec_check CHECK (
json_valid("spec_json")
AND json_type("spec_json") = 'object'
AND length("spec_json") BETWEEN 1 AND 16384
),
CONSTRAINT ql3_trigger_revisions_enabled_check CHECK (
"enabled" IN (0, 1)
),
CONSTRAINT ql3_trigger_revisions_digest_check CHECK (
length("content_digest") = 64
AND "content_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_trigger_revisions_created_check CHECK (
"created_at_ms" >= 0
)
)
`,
`
CREATE UNIQUE INDEX "ql3_trigger_revisions_mutation_uidx"
ON "QingLong3TriggerRevisions" ("mutation_id")
`,
`
CREATE INDEX "ql3_trigger_revisions_project_enabled_idx"
ON "QingLong3TriggerRevisions" (
"project_id", "enabled", "trigger_id", "revision"
)
`,
`
CREATE INDEX "ql3_trigger_revisions_task_idx"
ON "QingLong3TriggerRevisions" (
"project_id", "task_id", "task_revision", "trigger_id", "revision"
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0032CapabilityV16Migration = defineLocalSqliteMigration({
id: '0032-capability-v16',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 16,
migration_id = '0031-trigger-definitions',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 15
AND migration_id = '0029-local-execution-revision-digest'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,80 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0033LegacyAdoptionLedgerMigration =
defineLocalSqliteMigration({
id: '0033-legacy-adoption-ledger',
statements: [
`
CREATE TABLE "QingLong3LegacyAdoptions" (
"mutation_id" TEXT PRIMARY KEY,
"decision_id" TEXT NOT NULL,
"project_id" TEXT NOT NULL,
"profile" TEXT NOT NULL,
"plan_digest" TEXT NOT NULL,
"inventory_digest" TEXT NOT NULL,
"decision_digest" TEXT NOT NULL,
"receipt_digest" TEXT NOT NULL,
"authorization_file_digest" TEXT NOT NULL,
"publication_digest" TEXT NOT NULL,
"row_count" INTEGER NOT NULL,
"adopted_task_count" INTEGER NOT NULL,
"adopted_trigger_count" INTEGER NOT NULL,
"skipped_count" INTEGER NOT NULL,
"audit_event_id" TEXT NOT NULL,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id")
ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_legacy_adoptions_mutation_check CHECK (
length("mutation_id") = 36
AND "audit_event_id" = "mutation_id"
),
CONSTRAINT ql3_legacy_adoptions_decision_check CHECK (
length("decision_id") = 36
AND substr("decision_id", 15, 1) = '7'
AND replace("decision_id", '-', '') NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_legacy_adoptions_profile_check CHECK (
"profile" IN ('edge', 'standalone')
),
CONSTRAINT ql3_legacy_adoptions_digest_check CHECK (
length("plan_digest") = 64
AND "plan_digest" NOT GLOB '*[^0-9a-f]*'
AND length("inventory_digest") = 64
AND "inventory_digest" NOT GLOB '*[^0-9a-f]*'
AND length("decision_digest") = 64
AND "decision_digest" NOT GLOB '*[^0-9a-f]*'
AND length("receipt_digest") = 64
AND "receipt_digest" NOT GLOB '*[^0-9a-f]*'
AND length("authorization_file_digest") = 64
AND "authorization_file_digest" NOT GLOB '*[^0-9a-f]*'
AND length("publication_digest") = 64
AND "publication_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_legacy_adoptions_count_check CHECK (
"row_count" BETWEEN 0 AND 100000
AND "adopted_task_count" BETWEEN 0 AND "row_count"
AND "skipped_count" BETWEEN 0 AND "row_count"
AND "adopted_task_count" + "skipped_count" = "row_count"
AND "adopted_trigger_count" BETWEEN 0 AND 500000
),
CONSTRAINT ql3_legacy_adoptions_created_check CHECK (
"created_at_ms" >= 0
)
)
`,
`
CREATE UNIQUE INDEX "ql3_legacy_adoptions_decision_uidx"
ON "QingLong3LegacyAdoptions" ("decision_id")
`,
`
CREATE INDEX "ql3_legacy_adoptions_project_time_idx"
ON "QingLong3LegacyAdoptions" (
"project_id", "created_at_ms" DESC, "mutation_id" DESC
)
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0034CapabilityV17Migration = defineLocalSqliteMigration({
id: '0034-capability-v17',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 17,
migration_id = '0033-legacy-adoption-ledger',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 16
AND migration_id = '0031-trigger-definitions'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,42 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0035LocalSchedulerMigration = defineLocalSqliteMigration({
id: '0035-local-scheduler',
statements: [
`
CREATE TABLE "QingLong3LocalTriggerSchedules" (
project_id TEXT NOT NULL,
trigger_id TEXT NOT NULL,
trigger_revision INTEGER NOT NULL,
next_fire_at_ms INTEGER,
last_scheduled_at_ms INTEGER,
state_version INTEGER NOT NULL DEFAULT 0,
updated_at_ms INTEGER NOT NULL,
PRIMARY KEY (project_id, trigger_id),
CONSTRAINT ql3_local_trigger_schedules_trigger_fk
FOREIGN KEY (project_id, trigger_id)
REFERENCES "QingLong3Triggers" (project_id, trigger_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_local_trigger_schedules_revision_check
CHECK (trigger_revision BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_local_trigger_schedules_state_check
CHECK (state_version >= 0),
CONSTRAINT ql3_local_trigger_schedules_time_check CHECK (
updated_at_ms >= 0 AND
(next_fire_at_ms IS NULL OR next_fire_at_ms >= 0) AND
(last_scheduled_at_ms IS NULL OR last_scheduled_at_ms >= 0)
)
)
`,
`CREATE INDEX ql3_local_trigger_schedules_due_idx ON "QingLong3LocalTriggerSchedules" (next_fire_at_ms, project_id, trigger_id) WHERE next_fire_at_ms IS NOT NULL`,
`CREATE INDEX ql3_local_trigger_schedules_initialize_idx ON "QingLong3LocalTriggerSchedules" (project_id, trigger_id) WHERE next_fire_at_ms IS NULL`,
`
INSERT INTO "QingLong3LocalTriggerSchedules" (
project_id, trigger_id, trigger_revision, next_fire_at_ms,
last_scheduled_at_ms, state_version, updated_at_ms
)
SELECT project_id, trigger_id, current_revision, NULL, NULL, 0, updated_at_ms
FROM "QingLong3Triggers"
`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0036CapabilityV18Migration = defineLocalSqliteMigration({
id: '0036-capability-v18',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 18,
migration_id = '0035-local-scheduler',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 17
AND migration_id = '0033-legacy-adoption-ledger'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,125 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0037PluginPackageInstallsMigration =
defineLocalSqliteMigration({
id: '0037-plugin-package-installs',
statements: [
`
CREATE TABLE "QingLong3PluginPackageInstalls" (
installation_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
package_version TEXT NOT NULL,
operation TEXT NOT NULL,
lock_digest TEXT NOT NULL,
target_generation INTEGER NOT NULL,
previous_active_lock_digest TEXT,
active_lock_digest TEXT,
state TEXT NOT NULL,
version INTEGER NOT NULL,
last_mutation_id TEXT NOT NULL,
last_mutation_digest TEXT NOT NULL,
lock_json TEXT NOT NULL,
record_json TEXT NOT NULL,
record_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_plugin_package_installs_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_installs_identity_check CHECK (
length(installation_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 253 AND
length(package_version) BETWEEN 1 AND 128 AND
length(last_mutation_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_plugin_package_installs_operation_check
CHECK (operation IN ('install','reinstall','upgrade','rollback')),
CONSTRAINT ql3_plugin_package_installs_state_check
CHECK (state IN ('queued','staged','activating','active','failed')),
CONSTRAINT ql3_plugin_package_installs_version_check CHECK (
target_generation BETWEEN 1 AND 2147483647 AND
version BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_installs_digest_check CHECK (
length(lock_digest) = 64 AND lock_digest NOT GLOB '*[^0-9a-f]*' AND
(previous_active_lock_digest IS NULL OR
(length(previous_active_lock_digest) = 64 AND
previous_active_lock_digest NOT GLOB '*[^0-9a-f]*')) AND
(active_lock_digest IS NULL OR
(length(active_lock_digest) = 64 AND
active_lock_digest NOT GLOB '*[^0-9a-f]*')) AND
length(last_mutation_digest) = 64 AND
last_mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(record_digest) = 64 AND record_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_installs_record_check CHECK (
length(lock_json) BETWEEN 2 AND 262144 AND
json_valid(lock_json) AND json_type(lock_json) = 'object' AND
json_extract(lock_json, '$.lockDigest') = lock_digest AND
json_extract(lock_json, '$.projectId') = project_id AND
json_extract(lock_json, '$.packageName') = package_name AND
length(record_json) BETWEEN 2 AND 262144 AND
json_valid(record_json) AND json_type(record_json) = 'object' AND
json_extract(record_json, '$.installationId') = installation_id AND
json_extract(record_json, '$.projectId') = project_id AND
json_extract(record_json, '$.packageName') = package_name AND
json_extract(record_json, '$.lockDigest') = lock_digest AND
json_extract(record_json, '$.state') = state AND
json_extract(record_json, '$.version') = version AND
json_extract(record_json, '$.recordDigest') = record_digest
),
CONSTRAINT ql3_plugin_package_installs_time_check CHECK (
created_at_ms >= 0 AND updated_at_ms >= created_at_ms
)
)
`,
`
CREATE TABLE "QingLong3PluginPackageInstallHeads" (
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
PRIMARY KEY (project_id, package_name),
CONSTRAINT ql3_plugin_package_install_heads_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_heads_install_fk
FOREIGN KEY (installation_id)
REFERENCES "QingLong3PluginPackageInstalls" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_heads_identity_check CHECK (
length(package_name) BETWEEN 1 AND 253 AND
length(installation_id) BETWEEN 1 AND 128
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_install_heads_install_uidx ON "QingLong3PluginPackageInstallHeads" (installation_id)`,
`
CREATE TABLE "QingLong3PluginPackageInstallMutations" (
installation_id TEXT NOT NULL,
mutation_id TEXT NOT NULL,
mutation_digest TEXT NOT NULL,
resulting_record_digest TEXT NOT NULL,
occurred_at_ms INTEGER NOT NULL,
PRIMARY KEY (installation_id, mutation_id),
CONSTRAINT ql3_plugin_package_install_mutations_install_fk
FOREIGN KEY (installation_id)
REFERENCES "QingLong3PluginPackageInstalls" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_mutations_identity_check
CHECK (length(mutation_id) BETWEEN 1 AND 128),
CONSTRAINT ql3_plugin_package_install_mutations_digest_check CHECK (
length(mutation_digest) = 64 AND
mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(resulting_record_digest) = 64 AND
resulting_record_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_install_mutations_time_check
CHECK (occurred_at_ms >= 0)
)
`,
`CREATE INDEX ql3_plugin_package_installs_recovery_idx ON "QingLong3PluginPackageInstalls" (state, package_name, installation_id) WHERE state IN ('queued','staged','activating')`,
`CREATE INDEX ql3_plugin_package_installs_project_history_idx ON "QingLong3PluginPackageInstalls" (project_id, package_name, created_at_ms, installation_id)`,
`CREATE INDEX ql3_plugin_package_install_mutations_result_idx ON "QingLong3PluginPackageInstallMutations" (installation_id, resulting_record_digest)`,
],
});
@@ -0,0 +1,18 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0038CapabilityV19Migration = defineLocalSqliteMigration({
id: '0038-capability-v19',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 19,
migration_id = '0037-plugin-package-installs',
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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 18
AND migration_id = '0035-local-scheduler'
AND 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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}'
`,
],
});
@@ -0,0 +1,124 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0039ApprovedActionsMigration = defineLocalSqliteMigration({
id: '0039-approved-actions',
statements: [
`
CREATE TABLE "QingLong3ApprovalRequests" (
request_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
version INTEGER NOT NULL,
state TEXT NOT NULL,
action_type TEXT NOT NULL,
action_ref TEXT NOT NULL,
action_digest TEXT NOT NULL,
preview_digest TEXT NOT NULL,
requested_by_type TEXT NOT NULL,
requested_by_id TEXT NOT NULL,
decision_id TEXT,
consumption_id TEXT,
dispatch_id TEXT,
expires_at_ms INTEGER NOT NULL,
request_json TEXT NOT NULL,
request_digest TEXT NOT NULL,
updated_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_approval_requests_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approval_requests_identity_check CHECK (
length(request_id) BETWEEN 1 AND 128 AND
length(action_type) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255
),
CONSTRAINT ql3_approval_requests_state_version_check CHECK (
(state = 'pending' AND version = 1) OR
(state IN ('approved','rejected') AND version = 2) OR
(state = 'consumed' AND version = 3)
),
CONSTRAINT ql3_approval_requests_digest_check CHECK (
length(action_digest) = 64 AND action_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_digest) = 64 AND preview_digest NOT GLOB '*[^0-9a-f]*' AND
length(request_digest) = 64 AND request_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_approval_requests_subject_check CHECK (
requested_by_type IN
('user','api_app','mcp_client','agent','system','worker') AND
length(requested_by_id) BETWEEN 1 AND 255
),
CONSTRAINT ql3_approval_requests_mutation_tuple_check CHECK (
(version = 1 AND decision_id IS NULL AND consumption_id IS NULL AND
dispatch_id IS NULL) OR
(version = 2 AND decision_id IS NOT NULL AND consumption_id IS NULL AND
dispatch_id IS NULL) OR
(version = 3 AND decision_id IS NOT NULL AND consumption_id IS NOT NULL AND
dispatch_id IS NOT NULL)
),
CONSTRAINT ql3_approval_requests_json_check CHECK (
length(request_json) BETWEEN 2 AND 65536 AND
json_valid(request_json) AND json_type(request_json) = 'object' AND
json_extract(request_json, '$.id') = request_id AND
json_extract(request_json, '$.projectId') = project_id AND
json_extract(request_json, '$.version') = version AND
json_extract(request_json, '$.state') = state AND
json_extract(request_json, '$.action.actionType') = action_type AND
json_extract(request_json, '$.action.actionRef') = action_ref AND
json_extract(request_json, '$.action.actionDigest') = action_digest AND
json_extract(request_json, '$.action.previewDigest') = preview_digest
),
CONSTRAINT ql3_approval_requests_time_check
CHECK (expires_at_ms > 0 AND updated_at_ms >= 0)
)
`,
`CREATE UNIQUE INDEX ql3_approval_requests_decision_uidx ON "QingLong3ApprovalRequests" (decision_id)`,
`CREATE UNIQUE INDEX ql3_approval_requests_consumption_uidx ON "QingLong3ApprovalRequests" (consumption_id)`,
`CREATE UNIQUE INDEX ql3_approval_requests_dispatch_uidx ON "QingLong3ApprovalRequests" (dispatch_id)`,
`CREATE INDEX ql3_approval_requests_pending_idx ON "QingLong3ApprovalRequests" (expires_at_ms, request_id) WHERE state = 'pending'`,
`CREATE INDEX ql3_approval_requests_project_idx ON "QingLong3ApprovalRequests" (project_id, updated_at_ms, request_id)`,
`
CREATE TABLE "QingLong3ApprovedActionDispatches" (
dispatch_id TEXT PRIMARY KEY,
approval_request_id TEXT NOT NULL,
project_id TEXT NOT NULL,
action_type TEXT NOT NULL,
action_ref TEXT NOT NULL,
action_digest TEXT NOT NULL,
preview_digest TEXT NOT NULL,
dispatch_json TEXT NOT NULL,
dispatch_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_approved_action_dispatch_request_fk
FOREIGN KEY (approval_request_id)
REFERENCES "QingLong3ApprovalRequests" (request_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_dispatch_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_dispatch_identity_check CHECK (
length(dispatch_id) BETWEEN 1 AND 128 AND
length(action_type) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255
),
CONSTRAINT ql3_approved_action_dispatch_digest_check CHECK (
length(action_digest) = 64 AND action_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_digest) = 64 AND preview_digest NOT GLOB '*[^0-9a-f]*' AND
length(dispatch_digest) = 64 AND dispatch_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_approved_action_dispatch_json_check CHECK (
length(dispatch_json) BETWEEN 2 AND 65536 AND
json_valid(dispatch_json) AND json_type(dispatch_json) = 'object' AND
json_extract(dispatch_json, '$.id') = dispatch_id AND
json_extract(dispatch_json, '$.approvalRequestId') = approval_request_id AND
json_extract(dispatch_json, '$.projectId') = project_id AND
json_extract(dispatch_json, '$.action.actionType') = action_type AND
json_extract(dispatch_json, '$.action.actionRef') = action_ref AND
json_extract(dispatch_json, '$.action.actionDigest') = action_digest AND
json_extract(dispatch_json, '$.action.previewDigest') = preview_digest
),
CONSTRAINT ql3_approved_action_dispatch_time_check
CHECK (created_at_ms >= 0)
)
`,
`CREATE UNIQUE INDEX ql3_approved_action_dispatch_request_uidx ON "QingLong3ApprovedActionDispatches" (approval_request_id)`,
`CREATE INDEX ql3_approved_action_dispatch_project_idx ON "QingLong3ApprovedActionDispatches" (project_id, created_at_ms, dispatch_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
export const local0040CapabilityV20Migration = defineLocalSqliteMigration({
id: '0040-capability-v20',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 20,
migration_id = '0039-approved-actions',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 19
AND migration_id = '0037-plugin-package-installs'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,90 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0041PluginPackageAdmissionReceiptsMigration =
defineLocalSqliteMigration({
id: '0041-plugin-package-admission-receipts',
statements: [
`
CREATE TABLE "QingLong3PluginPackageAdmissionReceipts" (
dispatch_id TEXT PRIMARY KEY,
dispatch_digest TEXT NOT NULL,
approval_request_id TEXT NOT NULL,
action_ref TEXT NOT NULL,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
record_digest TEXT NOT NULL,
mutation_id TEXT NOT NULL,
mutation_digest TEXT NOT NULL,
audit_event_id TEXT NOT NULL,
admitted_at_ms INTEGER NOT NULL,
receipt_json TEXT NOT NULL,
receipt_digest TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_admission_dispatch_fk
FOREIGN KEY (dispatch_id)
REFERENCES "QingLong3ApprovedActionDispatches" (dispatch_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_request_fk
FOREIGN KEY (approval_request_id)
REFERENCES "QingLong3ApprovalRequests" (request_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_install_fk
FOREIGN KEY (installation_id)
REFERENCES "QingLong3PluginPackageInstalls" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "QingLong3SecurityAuditEvents" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_identity_check CHECK (
length(dispatch_id) BETWEEN 1 AND 128 AND
length(approval_request_id) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255 AND
length(project_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 64 AND
length(installation_id) BETWEEN 1 AND 128 AND
length(mutation_id) BETWEEN 1 AND 128 AND
length(audit_event_id) = 36
),
CONSTRAINT ql3_plugin_package_admission_digest_check CHECK (
length(dispatch_digest) = 64 AND
dispatch_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(record_digest) = 64 AND record_digest NOT GLOB '*[^0-9a-f]*' AND
length(mutation_digest) = 64 AND
mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(receipt_digest) = 64 AND receipt_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_admission_json_check CHECK (
length(receipt_json) BETWEEN 2 AND 65536 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-admission-receipt@v1' AND
json_extract(receipt_json, '$.dispatchId') = dispatch_id AND
json_extract(receipt_json, '$.dispatchDigest') = dispatch_digest AND
json_extract(receipt_json, '$.approvalRequestId') = approval_request_id AND
json_extract(receipt_json, '$.actionRef') = action_ref AND
json_extract(receipt_json, '$.projectId') = project_id AND
json_extract(receipt_json, '$.packageName') = package_name AND
json_extract(receipt_json, '$.installationId') = installation_id AND
json_extract(receipt_json, '$.lockDigest') = lock_digest AND
json_extract(receipt_json, '$.recordDigest') = record_digest AND
json_extract(receipt_json, '$.mutationId') = mutation_id AND
json_extract(receipt_json, '$.mutationDigest') = mutation_digest AND
json_extract(receipt_json, '$.auditEventId') = audit_event_id AND
json_extract(receipt_json, '$.admittedAtMs') = admitted_at_ms AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
),
CONSTRAINT ql3_plugin_package_admission_time_check
CHECK (admitted_at_ms >= 0)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_admission_install_uidx ON "QingLong3PluginPackageAdmissionReceipts" (installation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_admission_audit_uidx ON "QingLong3PluginPackageAdmissionReceipts" (audit_event_id)`,
`CREATE INDEX ql3_plugin_package_admission_project_idx ON "QingLong3PluginPackageAdmissionReceipts" (project_id, admitted_at_ms, dispatch_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
export const local0042CapabilityV21Migration = defineLocalSqliteMigration({
id: '0042-capability-v21',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 21,
migration_id = '0041-plugin-package-admission-receipts',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 20
AND migration_id = '0039-approved-actions'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,149 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0043ApprovedActionExecutionsAndPackageProposalsMigration =
defineLocalSqliteMigration({
id: '0043-approved-action-executions-and-package-proposals',
statements: [
`
CREATE TABLE "QingLong3PluginPackageInstallProposals" (
action_ref TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
action_type TEXT NOT NULL,
permission TEXT NOT NULL,
action_digest TEXT NOT NULL,
preview_digest TEXT NOT NULL,
proposed_by_type TEXT NOT NULL,
proposed_by_id TEXT NOT NULL,
fence_project_version INTEGER NOT NULL,
fence_binding_version INTEGER,
created_at_ms INTEGER NOT NULL,
proposal_json TEXT NOT NULL,
proposal_digest TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_proposal_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_proposal_identity_check CHECK (
length(action_ref) BETWEEN 1 AND 255 AND
action_type = 'plugin_package.install' AND
permission = 'package.manage' AND
proposed_by_type IN
('user','api_app','mcp_client','agent','system','worker') AND
length(proposed_by_id) BETWEEN 1 AND 255
),
CONSTRAINT ql3_plugin_package_proposal_digest_check CHECK (
length(action_digest) = 64 AND action_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_digest) = 64 AND preview_digest NOT GLOB '*[^0-9a-f]*' AND
length(proposal_digest) = 64 AND
proposal_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_proposal_json_check CHECK (
length(proposal_json) BETWEEN 2 AND 262144 AND
json_valid(proposal_json) AND json_type(proposal_json) = 'object' AND
json_extract(proposal_json, '$.schema') =
'qinglong/plugin-package-install-proposal@v1' AND
json_extract(proposal_json, '$.actionRef') = action_ref AND
json_extract(proposal_json, '$.projectId') = project_id AND
json_extract(proposal_json, '$.actionType') = action_type AND
json_extract(proposal_json, '$.permission') = permission AND
json_extract(proposal_json, '$.actionDigest') = action_digest AND
json_extract(proposal_json, '$.previewDigest') = preview_digest AND
json_extract(proposal_json, '$.proposedBy.type') = proposed_by_type AND
json_extract(proposal_json, '$.proposedBy.id') = proposed_by_id AND
json_extract(proposal_json, '$.proposalFence.projectVersion') =
fence_project_version AND
json_extract(proposal_json, '$.proposalFence.bindingVersion')
IS fence_binding_version AND
json_extract(proposal_json, '$.createdAtMs') = created_at_ms AND
json_extract(proposal_json, '$.proposalDigest') = proposal_digest
),
CONSTRAINT ql3_plugin_package_proposal_time_check CHECK (
fence_project_version > 0 AND
(fence_binding_version IS NULL OR fence_binding_version > 0) AND
created_at_ms >= 0
)
)
`,
`CREATE INDEX ql3_plugin_package_proposal_project_idx ON "QingLong3PluginPackageInstallProposals" (project_id, created_at_ms, action_ref)`,
`
CREATE TABLE "QingLong3ApprovedActionExecutions" (
dispatch_id TEXT PRIMARY KEY,
dispatch_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
status TEXT NOT NULL,
version INTEGER NOT NULL,
attempt_count INTEGER NOT NULL,
max_attempts INTEGER NOT NULL,
eligible_at_ms INTEGER,
next_attempt_at_ms INTEGER,
lease_owner TEXT,
lease_token TEXT,
lease_expires_at_ms INTEGER,
started_at_ms INTEGER,
result_mutation_id TEXT,
result_code TEXT,
result_digest TEXT,
completed_at_ms INTEGER,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
execution_json TEXT NOT NULL,
execution_digest TEXT NOT NULL,
CONSTRAINT ql3_approved_action_execution_dispatch_fk
FOREIGN KEY (dispatch_id)
REFERENCES "QingLong3ApprovedActionDispatches" (dispatch_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_execution_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_execution_state_check CHECK (
status IN
('pending','leased','executing','retry_wait','succeeded','failed','blocked')
AND version BETWEEN 0 AND 2147483647
AND attempt_count BETWEEN 0 AND 16
AND max_attempts BETWEEN 1 AND 16
AND attempt_count <= max_attempts
),
CONSTRAINT ql3_approved_action_execution_lease_check CHECK (
(lease_owner IS NULL AND lease_token IS NULL AND
lease_expires_at_ms IS NULL) OR
(length(lease_owner) BETWEEN 1 AND 128 AND
length(lease_token) BETWEEN 1 AND 128 AND
lease_expires_at_ms > updated_at_ms)
),
CONSTRAINT ql3_approved_action_execution_result_check CHECK (
(result_mutation_id IS NULL AND result_code IS NULL) OR
(length(result_mutation_id) BETWEEN 1 AND 128 AND
length(result_code) BETWEEN 1 AND 64)
),
CONSTRAINT ql3_approved_action_execution_digest_check CHECK (
length(dispatch_digest) = 64 AND
dispatch_digest NOT GLOB '*[^0-9a-f]*' AND
(result_digest IS NULL OR
(length(result_digest) = 64 AND
result_digest NOT GLOB '*[^0-9a-f]*')) AND
length(execution_digest) = 64 AND
execution_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_approved_action_execution_json_check CHECK (
length(execution_json) BETWEEN 2 AND 65536 AND
json_valid(execution_json) AND json_type(execution_json) = 'object' AND
json_extract(execution_json, '$.schema') =
'qinglong/approved-action-execution@v1' AND
json_extract(execution_json, '$.dispatchId') = dispatch_id AND
json_extract(execution_json, '$.dispatchDigest') = dispatch_digest AND
json_extract(execution_json, '$.projectId') = project_id AND
json_extract(execution_json, '$.status') = status AND
json_extract(execution_json, '$.version') = version AND
json_extract(execution_json, '$.attemptCount') = attempt_count AND
json_extract(execution_json, '$.maxAttempts') = max_attempts AND
json_extract(execution_json, '$.executionDigest') = execution_digest
),
CONSTRAINT ql3_approved_action_execution_time_check CHECK (
created_at_ms >= 0 AND updated_at_ms >= created_at_ms
)
)
`,
`CREATE INDEX ql3_approved_action_execution_due_idx ON "QingLong3ApprovedActionExecutions" (eligible_at_ms, dispatch_id) WHERE status IN ('pending','leased','retry_wait')`,
`CREATE INDEX ql3_approved_action_execution_recovery_idx ON "QingLong3ApprovedActionExecutions" (lease_expires_at_ms, dispatch_id) WHERE status = 'executing'`,
`CREATE INDEX ql3_approved_action_execution_project_idx ON "QingLong3ApprovedActionExecutions" (project_id, updated_at_ms, dispatch_id)`,
],
});
@@ -0,0 +1,24 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
export const local0044CapabilityV22Migration = defineLocalSqliteMigration({
id: '0044-capability-v22',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 22,
migration_id =
'0043-approved-action-executions-and-package-proposals',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 21
AND migration_id = '0041-plugin-package-admission-receipts'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,57 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0045PluginPackageMaterializedRevisionsMigration =
defineLocalSqliteMigration({
id: '0045-plugin-package-materialized-revisions',
statements: [
`
CREATE TABLE "QingLong3PluginPackageMaterializedRevisions" (
generation_digest TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
generation INTEGER NOT NULL,
lock_digest TEXT NOT NULL,
manifest_digest TEXT NOT NULL,
revision_digest TEXT NOT NULL,
revision_json TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_plugin_package_materialized_revision_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_materialized_revision_identity_check CHECK (
length(package_name) BETWEEN 1 AND 63 AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_materialized_revision_digest_check CHECK (
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(manifest_digest) = 64 AND
manifest_digest NOT GLOB '*[^0-9a-f]*' AND
length(revision_digest) = 64 AND
revision_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_materialized_revision_json_check CHECK (
length(revision_json) BETWEEN 2 AND 25165824 AND
json_valid(revision_json) AND json_type(revision_json) = 'object' AND
json_extract(revision_json, '$.schema') =
'qinglong/plugin-package-materialized-revision@v1' AND
json_extract(revision_json, '$.generation.generationDigest') =
generation_digest AND
json_extract(revision_json, '$.generation.projectId') = project_id AND
json_extract(revision_json, '$.generation.packageName') = package_name AND
json_extract(revision_json, '$.generation.generation') = generation AND
json_extract(revision_json, '$.generation.lockDigest') = lock_digest AND
json_extract(revision_json, '$.manifestDigest') = manifest_digest AND
json_extract(revision_json, '$.revisionDigest') = revision_digest
),
CONSTRAINT ql3_plugin_package_materialized_revision_time_check CHECK (
created_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_materialized_revision_generation_uidx ON "QingLong3PluginPackageMaterializedRevisions" (project_id, package_name, generation)`,
`CREATE INDEX ql3_plugin_package_materialized_revision_lock_idx ON "QingLong3PluginPackageMaterializedRevisions" (lock_digest, generation_digest)`,
],
});
@@ -0,0 +1,24 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
export const local0046CapabilityV23Migration = defineLocalSqliteMigration({
id: '0046-capability-v23',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 23,
migration_id = '0045-plugin-package-materialized-revisions',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 22
AND migration_id =
'0043-approved-action-executions-and-package-proposals'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,118 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0047PluginPackageTaskReconciliationsMigration =
defineLocalSqliteMigration({
id: '0047-plugin-package-task-reconciliations',
statements: [
`
CREATE TABLE "QingLong3PluginPackageTaskOwnerships" (
project_id TEXT NOT NULL,
task_id TEXT NOT NULL,
package_name TEXT NOT NULL,
claimed_generation_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
PRIMARY KEY (project_id, task_id),
CONSTRAINT ql3_plugin_package_task_ownership_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_ownership_task_fk
FOREIGN KEY (project_id, task_id)
REFERENCES "QingLong3TaskDefinitions" (project_id, task_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_ownership_identity_check CHECK (
length(task_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63
),
CONSTRAINT ql3_plugin_package_task_ownership_digest_check CHECK (
length(claimed_generation_digest) = 64 AND
claimed_generation_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_task_ownership_namespace_check CHECK (
task_id LIKE 'pkg:' || package_name || ':%'
),
CONSTRAINT ql3_plugin_package_task_ownership_time_check CHECK (
created_at_ms >= 0
)
)
`,
`CREATE INDEX ql3_plugin_package_task_ownership_package_idx ON "QingLong3PluginPackageTaskOwnerships" (project_id, package_name, task_id)`,
`
CREATE TABLE "QingLong3PluginPackageTaskReconciliations" (
generation_digest TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
generation INTEGER NOT NULL,
materialized_revision_digest TEXT NOT NULL,
lock_digest TEXT NOT NULL,
previous_lock_digest TEXT,
receipt_digest TEXT NOT NULL,
receipt_json TEXT NOT NULL,
committed_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_plugin_package_task_reconciliation_materialized_fk
FOREIGN KEY (generation_digest)
REFERENCES "QingLong3PluginPackageMaterializedRevisions" (generation_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_reconciliation_identity_check CHECK (
length(package_name) BETWEEN 1 AND 63 AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_task_reconciliation_digest_check CHECK (
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(materialized_revision_digest) = 64 AND
materialized_revision_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND lock_digest NOT GLOB '*[^0-9a-f]*' AND
(previous_lock_digest IS NULL OR
(length(previous_lock_digest) = 64 AND
previous_lock_digest NOT GLOB '*[^0-9a-f]*')) AND
length(receipt_digest) = 64 AND receipt_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_task_reconciliation_json_check CHECK (
length(receipt_json) BETWEEN 2 AND 8388608 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-task-reconciliation@v1' AND
json_extract(receipt_json, '$.generationDigest') = generation_digest AND
json_extract(receipt_json, '$.projectId') = project_id AND
json_extract(receipt_json, '$.packageName') = package_name AND
json_extract(receipt_json, '$.generation') = generation AND
json_extract(receipt_json, '$.materializedRevisionDigest') =
materialized_revision_digest AND
json_extract(receipt_json, '$.lockDigest') = lock_digest AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
),
CONSTRAINT ql3_plugin_package_task_reconciliation_time_check CHECK (
committed_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_task_reconciliation_generation_uidx ON "QingLong3PluginPackageTaskReconciliations" (project_id, package_name, generation)`,
`CREATE INDEX ql3_plugin_package_task_reconciliation_lock_idx ON "QingLong3PluginPackageTaskReconciliations" (lock_digest, generation_digest)`,
`
CREATE TABLE "QingLong3PluginPackageTaskReconciliationItems" (
generation_digest TEXT NOT NULL,
task_id TEXT NOT NULL,
revision INTEGER NOT NULL,
disposition TEXT NOT NULL,
content_digest TEXT NOT NULL,
PRIMARY KEY (generation_digest, task_id),
CONSTRAINT ql3_plugin_package_task_reconciliation_item_reconciliation_fk
FOREIGN KEY (generation_digest)
REFERENCES "QingLong3PluginPackageTaskReconciliations" (generation_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_reconciliation_item_identity_check CHECK (
length(task_id) BETWEEN 1 AND 128 AND
revision BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_task_reconciliation_item_disposition_check
CHECK (disposition IN (
'already_disabled','created','disabled','retained','updated'
)),
CONSTRAINT ql3_plugin_package_task_reconciliation_item_digest_check CHECK (
length(content_digest) = 64 AND content_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_plugin_package_task_reconciliation_item_task_idx ON "QingLong3PluginPackageTaskReconciliationItems" (task_id, generation_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1}';
export const local0048CapabilityV24Migration = defineLocalSqliteMigration({
id: '0048-capability-v24',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 24,
migration_id = '0047-plugin-package-task-reconciliations',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 23
AND migration_id = '0045-plugin-package-materialized-revisions'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,118 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0049ProjectToolDefinitionSnapshotsMigration =
defineLocalSqliteMigration({
id: '0049-project-tool-definition-snapshots',
statements: [
`
CREATE UNIQUE INDEX ql3_plugin_package_installs_snapshot_source_uidx
ON "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, target_generation, lock_digest
)
`,
`
CREATE UNIQUE INDEX ql3_plugin_package_materialized_revision_snapshot_source_uidx
ON "QingLong3PluginPackageMaterializedRevisions" (
project_id, package_name, generation, generation_digest,
lock_digest, revision_digest
)
`,
`
CREATE TABLE "QingLong3ProjectToolDefinitionSnapshots" (
project_id TEXT NOT NULL,
active_vector_digest TEXT NOT NULL,
definitions_digest TEXT NOT NULL,
snapshot_digest TEXT NOT NULL,
snapshot_json TEXT NOT NULL,
committed_at_ms INTEGER NOT NULL,
PRIMARY KEY (project_id, active_vector_digest),
CONSTRAINT ql3_project_tool_definition_snapshot_project_fk
FOREIGN KEY (project_id) REFERENCES "QingLong3Projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_identity_check CHECK (
length(project_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_project_tool_definition_snapshot_digest_check CHECK (
length(active_vector_digest) = 64 AND
active_vector_digest NOT GLOB '*[^0-9a-f]*' AND
length(definitions_digest) = 64 AND
definitions_digest NOT GLOB '*[^0-9a-f]*' AND
length(snapshot_digest) = 64 AND
snapshot_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_project_tool_definition_snapshot_json_check CHECK (
length(snapshot_json) BETWEEN 2 AND 8388608 AND
json_valid(snapshot_json) AND json_type(snapshot_json) = 'object' AND
json_extract(snapshot_json, '$.schema') =
'qinglong/project-tool-definition-snapshot@v1' AND
json_extract(snapshot_json, '$.projectId') = project_id AND
json_extract(snapshot_json, '$.activeVectorDigest') =
active_vector_digest AND
json_extract(snapshot_json, '$.definitionsDigest') =
definitions_digest AND
json_extract(snapshot_json, '$.snapshotDigest') = snapshot_digest
),
CONSTRAINT ql3_project_tool_definition_snapshot_time_check CHECK (
committed_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_project_tool_definition_snapshot_digest_uidx ON "QingLong3ProjectToolDefinitionSnapshots" (snapshot_digest)`,
`CREATE INDEX ql3_project_tool_definition_snapshot_current_idx ON "QingLong3ProjectToolDefinitionSnapshots" (project_id, committed_at_ms DESC, active_vector_digest)`,
`
CREATE TABLE "QingLong3ProjectToolDefinitionSnapshotSources" (
project_id TEXT NOT NULL,
active_vector_digest TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
generation INTEGER NOT NULL,
generation_digest TEXT NOT NULL,
lock_digest TEXT NOT NULL,
revision_digest TEXT NOT NULL,
PRIMARY KEY (project_id, active_vector_digest, package_name),
CONSTRAINT ql3_project_tool_definition_snapshot_source_snapshot_fk
FOREIGN KEY (project_id, active_vector_digest)
REFERENCES "QingLong3ProjectToolDefinitionSnapshots" (
project_id, active_vector_digest
)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_source_install_fk
FOREIGN KEY (
project_id, package_name, installation_id, generation, lock_digest
)
REFERENCES "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, target_generation, lock_digest
)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_source_revision_fk
FOREIGN KEY (
project_id, package_name, generation, generation_digest,
lock_digest, revision_digest
)
REFERENCES "QingLong3PluginPackageMaterializedRevisions" (
project_id, package_name, generation, generation_digest,
lock_digest, revision_digest
)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_source_identity_check
CHECK (
length(package_name) BETWEEN 1 AND 63 AND
length(installation_id) BETWEEN 1 AND 128 AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_project_tool_definition_snapshot_source_digest_check CHECK (
length(active_vector_digest) = 64 AND
active_vector_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(revision_digest) = 64 AND
revision_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_project_tool_definition_snapshot_source_generation_idx ON "QingLong3ProjectToolDefinitionSnapshotSources" (generation_digest, project_id, package_name)`,
`CREATE INDEX ql3_project_tool_definition_snapshot_source_install_idx ON "QingLong3ProjectToolDefinitionSnapshotSources" (installation_id, active_vector_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1}';
export const local0050CapabilityV25Migration = defineLocalSqliteMigration({
id: '0050-capability-v25',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 25,
migration_id = '0049-project-tool-definition-snapshots',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 24
AND migration_id = '0047-plugin-package-task-reconciliations'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,222 @@
import { defineLocalSqliteMigration } from './sqlMigration';
import { LOCAL_STEP_RUN_REFERENCE_TRIGGERS } from '../run/stepRunSchemaContract';
export const local0051StepRunsMigration = defineLocalSqliteMigration({
id: '0051-step-runs',
statements: [
`
CREATE TEMP TABLE "QingLong3StepRunReferenceUpgradeGuard" (
valid INTEGER NOT NULL CHECK (valid = 1)
)
`,
`
INSERT INTO "QingLong3StepRunReferenceUpgradeGuard" (valid)
SELECT CASE
WHEN EXISTS (
SELECT 1 FROM "RunAttempts" WHERE step_run_id IS NOT NULL
UNION ALL
SELECT 1 FROM "RunEvents" WHERE step_run_id IS NOT NULL
) THEN 0
ELSE 1
END
`,
`DROP TABLE "QingLong3StepRunReferenceUpgradeGuard"`,
`
CREATE TABLE "StepRuns" (
id TEXT PRIMARY KEY NOT NULL,
run_id TEXT NOT NULL,
parent_step_run_id TEXT,
step_key TEXT NOT NULL,
kind TEXT NOT NULL,
definition_ref TEXT NOT NULL,
definition_digest TEXT NOT NULL,
required INTEGER NOT NULL,
status TEXT NOT NULL,
version INTEGER NOT NULL,
attempt_count INTEGER NOT NULL,
input_ref TEXT,
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,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
last_mutation_id TEXT NOT NULL,
step_run_digest TEXT NOT NULL,
step_run_json TEXT NOT NULL,
CONSTRAINT ql3_step_runs_run_fk
FOREIGN KEY (run_id) REFERENCES "Runs" (id) ON DELETE CASCADE,
CONSTRAINT ql3_step_runs_parent_fk
FOREIGN KEY (run_id, parent_step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_step_runs_identity_check CHECK (
length(id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
(parent_step_run_id IS NULL OR
(length(parent_step_run_id) BETWEEN 1 AND 128 AND
parent_step_run_id <> id)) AND
length(step_key) BETWEEN 1 AND 128 AND
length(CAST(definition_ref AS BLOB)) BETWEEN 1 AND 512
),
CONSTRAINT ql3_step_runs_kind_check CHECK (
kind IN (
'task', 'tool', 'model', 'agent', 'condition', 'approval',
'subworkflow'
)
),
CONSTRAINT ql3_step_runs_status_check CHECK (
status IN (
'pending', 'ready', 'waiting_approval', 'running', 'lost',
'succeeded', 'failed', 'skipped', 'cancelled', 'timed_out'
)
),
CONSTRAINT ql3_step_runs_digest_check CHECK (
length(definition_digest) = 64 AND
definition_digest NOT GLOB '*[^0-9a-f]*' AND
length(step_run_digest) = 64 AND
step_run_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_step_runs_counter_check CHECK (
required IN (0, 1) AND
version BETWEEN 1 AND 2147483647 AND
attempt_count BETWEEN 0 AND 64
),
CONSTRAINT ql3_step_runs_reference_check CHECK (
(input_ref IS NULL OR
length(CAST(input_ref AS BLOB)) BETWEEN 1 AND 512) AND
(output_ref IS NULL OR
length(CAST(output_ref AS BLOB)) BETWEEN 1 AND 512) AND
(approval_request_id IS NULL OR
length(approval_request_id) BETWEEN 1 AND 128)
),
CONSTRAINT ql3_step_runs_time_check CHECK (
created_at_ms >= 0 AND updated_at_ms >= created_at_ms AND
(ready_at_ms IS NULL OR
ready_at_ms BETWEEN created_at_ms AND updated_at_ms) AND
(started_at_ms IS NULL OR
(ready_at_ms IS NOT NULL AND
started_at_ms BETWEEN ready_at_ms AND updated_at_ms)) AND
(finished_at_ms IS NULL OR
(finished_at_ms BETWEEN created_at_ms AND updated_at_ms AND
(ready_at_ms IS NULL OR finished_at_ms >= ready_at_ms) AND
(started_at_ms IS NULL OR finished_at_ms >= started_at_ms)))
),
CONSTRAINT ql3_step_runs_state_shape_check CHECK (
(status = 'pending' AND ready_at_ms IS NULL AND
started_at_ms IS NULL AND finished_at_ms IS NULL) OR
(status IN ('ready', 'waiting_approval') AND ready_at_ms IS NOT NULL AND
started_at_ms IS NULL AND finished_at_ms IS NULL) OR
(status IN ('running', 'lost') AND ready_at_ms IS NOT NULL AND
started_at_ms IS NOT NULL AND finished_at_ms IS NULL) OR
(status IN ('succeeded', 'failed', 'skipped', 'cancelled', 'timed_out')
AND finished_at_ms IS NOT NULL)
),
CONSTRAINT ql3_step_runs_result_shape_check CHECK (
(status = 'waiting_approval' AND approval_request_id IS NOT NULL) OR
status <> 'waiting_approval'
),
CONSTRAINT ql3_step_runs_result_value_check CHECK (
(output_ref IS NULL OR status = 'succeeded') AND
(status = 'succeeded' AND result_code IS NULL AND error_summary IS NULL OR
status IN ('failed', 'skipped', 'cancelled', 'timed_out', 'lost') AND
result_code IS NOT NULL OR
status IN ('pending', 'ready', 'waiting_approval', 'running') AND
result_code IS NULL AND error_summary IS NULL) AND
(result_code IS NULL OR
(length(result_code) BETWEEN 1 AND 64 AND
result_code NOT GLOB '*[^a-z0-9_]*' AND
substr(result_code, 1, 1) GLOB '[a-z]')) AND
(error_summary IS NULL OR
length(CAST(error_summary AS BLOB)) BETWEEN 1 AND 2048)
),
CONSTRAINT ql3_step_runs_mutation_identity_check CHECK (
length(last_mutation_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_step_runs_json_check CHECK (
length(CAST(step_run_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(step_run_json) AND json_type(step_run_json) = 'object' AND
json_extract(step_run_json, '$.schema') = 'qinglong/step-run@v1' AND
json_extract(step_run_json, '$.id') = id AND
json_extract(step_run_json, '$.runId') = run_id AND
json_extract(step_run_json, '$.parentStepRunId') IS parent_step_run_id AND
json_extract(step_run_json, '$.stepKey') = step_key AND
json_extract(step_run_json, '$.kind') = kind AND
json_extract(step_run_json, '$.definitionRef') = definition_ref AND
json_extract(step_run_json, '$.definitionDigest') = definition_digest AND
json_extract(step_run_json, '$.required') IS required AND
json_extract(step_run_json, '$.status') = status AND
json_extract(step_run_json, '$.version') = version AND
json_extract(step_run_json, '$.attemptCount') IS attempt_count AND
json_extract(step_run_json, '$.inputRef') IS input_ref AND
json_extract(step_run_json, '$.outputRef') IS output_ref AND
json_extract(step_run_json, '$.approvalRequestId') IS
approval_request_id AND
json_extract(step_run_json, '$.readyAtMs') IS ready_at_ms AND
json_extract(step_run_json, '$.startedAtMs') IS started_at_ms AND
json_extract(step_run_json, '$.finishedAtMs') IS finished_at_ms AND
json_extract(step_run_json, '$.resultCode') IS result_code AND
json_extract(step_run_json, '$.errorSummary') IS error_summary AND
json_extract(step_run_json, '$.createdAtMs') IS created_at_ms AND
json_extract(step_run_json, '$.updatedAtMs') IS updated_at_ms AND
json_extract(step_run_json, '$.lastMutationId') = last_mutation_id AND
json_extract(step_run_json, '$.stepRunDigest') = step_run_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_step_runs_run_id_uidx ON "StepRuns" (run_id, id)`,
`CREATE UNIQUE INDEX ql3_step_runs_run_step_uidx ON "StepRuns" (run_id, step_key)`,
`CREATE INDEX ql3_step_runs_run_status_idx ON "StepRuns" (run_id, status, id)`,
`CREATE INDEX ql3_step_runs_recovery_idx ON "StepRuns" (status, updated_at_ms, id) WHERE status IN ('waiting_approval', 'running', 'lost')`,
`
CREATE TABLE "StepRunMutations" (
mutation_id TEXT PRIMARY KEY NOT NULL,
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,
CONSTRAINT ql3_step_run_mutations_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_step_run_mutations_event_fk
FOREIGN KEY (event_id) REFERENCES "RunEvents" (id) ON DELETE CASCADE,
CONSTRAINT ql3_step_run_mutations_identity_check CHECK (
length(mutation_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(event_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_step_run_mutations_digest_check CHECK (
length(mutation_digest) = 64 AND
mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(step_run_digest) = 64 AND
step_run_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_step_run_mutations_counter_check CHECK (
event_sequence BETWEEN 1 AND 2147483647 AND
run_version BETWEEN 1 AND 2147483647 AND
committed_at_ms >= 0
),
CONSTRAINT ql3_step_run_mutations_json_check CHECK (
length(CAST(step_run_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(step_run_json) AND json_type(step_run_json) = 'object' AND
json_extract(step_run_json, '$.schema') = 'qinglong/step-run@v1' AND
json_extract(step_run_json, '$.id') = step_run_id AND
json_extract(step_run_json, '$.runId') = run_id AND
json_extract(step_run_json, '$.lastMutationId') = mutation_id AND
json_extract(step_run_json, '$.stepRunDigest') = step_run_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_step_run_mutations_event_uidx ON "StepRunMutations" (event_id)`,
`CREATE INDEX ql3_step_run_mutations_step_idx ON "StepRunMutations" (run_id, step_run_id, event_sequence, mutation_id)`,
...LOCAL_STEP_RUN_REFERENCE_TRIGGERS.map((trigger) => trigger.sql),
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1}';
export const local0052CapabilityV26Migration = defineLocalSqliteMigration({
id: '0052-capability-v26',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 26,
migration_id = '0051-step-runs',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 25
AND migration_id = '0049-project-tool-definition-snapshots'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,169 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0053ToolExecutionEvidenceMigration =
defineLocalSqliteMigration({
id: '0053-tool-execution-evidence',
statements: [
`
CREATE TABLE "ToolExecutionTraceAnchors" (
trace_id TEXT NOT NULL,
span_id TEXT NOT NULL,
parent_span_id TEXT,
project_id TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
invocation_plan_digest TEXT NOT NULL,
binding_digest TEXT NOT NULL,
adapter_digest TEXT NOT NULL,
redaction_contract_digest TEXT NOT NULL,
audit_contract_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
trace_digest TEXT NOT NULL,
trace_json TEXT NOT NULL,
CONSTRAINT tool_execution_trace_anchors_pkey
PRIMARY KEY (trace_id, span_id),
CONSTRAINT ql3_tool_execution_trace_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_trace_identity_check CHECK (
length(trace_id) = 32 AND trace_id NOT GLOB '*[^0-9a-f]*' AND
length(span_id) = 16 AND span_id NOT GLOB '*[^0-9a-f]*' AND
(parent_span_id IS NULL OR (
length(parent_span_id) = 16 AND
parent_span_id NOT GLOB '*[^0-9a-f]*' AND
parent_span_id <> span_id
)) AND
length(project_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_execution_trace_digest_check CHECK (
length(invocation_plan_digest) = 64 AND
invocation_plan_digest NOT GLOB '*[^0-9a-f]*' AND
length(binding_digest) = 64 AND
binding_digest NOT GLOB '*[^0-9a-f]*' AND
length(adapter_digest) = 64 AND
adapter_digest NOT GLOB '*[^0-9a-f]*' AND
length(redaction_contract_digest) = 64 AND
redaction_contract_digest NOT GLOB '*[^0-9a-f]*' AND
length(audit_contract_digest) = 64 AND
audit_contract_digest NOT GLOB '*[^0-9a-f]*' AND
length(trace_digest) = 64 AND
trace_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_execution_trace_time_check CHECK (
created_at_ms >= 0
),
CONSTRAINT ql3_tool_execution_trace_json_check CHECK (
length(CAST(trace_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(trace_json) AND json_type(trace_json) = 'object' AND
json_extract(trace_json, '$.schema') =
'qinglong/tool-execution-trace-anchor@v1' AND
json_extract(trace_json, '$.traceId') = trace_id AND
json_extract(trace_json, '$.spanId') = span_id AND
json_extract(trace_json, '$.parentSpanId') IS parent_span_id AND
json_extract(trace_json, '$.projectId') = project_id AND
json_extract(trace_json, '$.runId') = run_id AND
json_extract(trace_json, '$.stepRunId') = step_run_id AND
json_extract(trace_json, '$.invocationPlanDigest') =
invocation_plan_digest AND
json_extract(trace_json, '$.bindingDigest') = binding_digest AND
json_extract(trace_json, '$.adapterDigest') = adapter_digest AND
json_extract(trace_json, '$.redactionContractDigest') =
redaction_contract_digest AND
json_extract(trace_json, '$.auditContractDigest') =
audit_contract_digest AND
json_extract(trace_json, '$.createdAtMs') IS created_at_ms AND
json_extract(trace_json, '$.traceDigest') = trace_digest
)
)
`,
`CREATE INDEX ql3_tool_execution_trace_run_idx ON "ToolExecutionTraceAnchors" (run_id, created_at_ms, trace_id, span_id)`,
`CREATE INDEX ql3_tool_execution_trace_step_idx ON "ToolExecutionTraceAnchors" (run_id, step_run_id, created_at_ms, trace_id, span_id)`,
`
CREATE TABLE "ToolExecutionAuditReceipts" (
event_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
trace_id TEXT NOT NULL,
span_id TEXT NOT NULL,
trace_digest TEXT NOT NULL,
invocation_plan_digest TEXT NOT NULL,
binding_digest TEXT NOT NULL,
audit_record_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
receipt_digest TEXT NOT NULL,
audit_json TEXT NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_tool_execution_audit_event_fk
FOREIGN KEY (event_id)
REFERENCES "QingLong3SecurityAuditEvents" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_execution_audit_trace_fk
FOREIGN KEY (trace_id, span_id)
REFERENCES "ToolExecutionTraceAnchors" (trace_id, span_id)
ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_audit_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_audit_identity_check CHECK (
length(event_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(trace_id) = 32 AND trace_id NOT GLOB '*[^0-9a-f]*' AND
length(span_id) = 16 AND span_id NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_execution_audit_digest_check CHECK (
length(trace_digest) = 64 AND
trace_digest NOT GLOB '*[^0-9a-f]*' AND
length(invocation_plan_digest) = 64 AND
invocation_plan_digest NOT GLOB '*[^0-9a-f]*' AND
length(binding_digest) = 64 AND
binding_digest NOT GLOB '*[^0-9a-f]*' AND
length(audit_record_digest) = 64 AND
audit_record_digest NOT GLOB '*[^0-9a-f]*' AND
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_execution_audit_time_check CHECK (
created_at_ms >= 0
),
CONSTRAINT ql3_tool_execution_audit_json_check CHECK (
length(CAST(audit_json AS BLOB)) BETWEEN 2 AND 8192 AND
json_valid(audit_json) AND json_type(audit_json) = 'object' AND
json_extract(audit_json, '$.eventId') = event_id AND
json_extract(audit_json, '$.projectId') = project_id AND
json_extract(audit_json, '$.operationId') = 'tool.invoke.start' AND
json_extract(audit_json, '$.outcome') = 'allowed' AND
json_type(audit_json, '$.fence') = 'object' AND
json_extract(audit_json, '$.occurredAtMs') IS created_at_ms
),
CONSTRAINT ql3_tool_execution_audit_receipt_json_check CHECK (
length(CAST(receipt_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/tool-execution-audit-receipt@v1' AND
json_extract(receipt_json, '$.eventId') = event_id AND
json_extract(receipt_json, '$.projectId') = project_id AND
json_extract(receipt_json, '$.runId') = run_id AND
json_extract(receipt_json, '$.stepRunId') = step_run_id AND
json_extract(receipt_json, '$.traceId') = trace_id AND
json_extract(receipt_json, '$.spanId') = span_id AND
json_extract(receipt_json, '$.traceDigest') = trace_digest AND
json_extract(receipt_json, '$.invocationPlanDigest') =
invocation_plan_digest AND
json_extract(receipt_json, '$.bindingDigest') = binding_digest AND
json_extract(receipt_json, '$.auditRecordDigest') =
audit_record_digest AND
json_extract(receipt_json, '$.createdAtMs') IS created_at_ms AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_execution_audit_trace_uidx ON "ToolExecutionAuditReceipts" (trace_id, span_id)`,
`CREATE INDEX ql3_tool_execution_audit_run_idx ON "ToolExecutionAuditReceipts" (run_id, created_at_ms, trace_id, span_id)`,
`CREATE INDEX ql3_tool_execution_audit_step_idx ON "ToolExecutionAuditReceipts" (run_id, step_run_id, created_at_ms, event_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1}';
export const local0054CapabilityV27Migration = defineLocalSqliteMigration({
id: '0054-capability-v27',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 27,
migration_id = '0053-tool-execution-evidence',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 26
AND migration_id = '0051-step-runs'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,91 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0055ToolExecutionStartBarriersMigration =
defineLocalSqliteMigration({
id: '0055-tool-execution-start-barriers',
statements: [
`
CREATE TABLE "ToolExecutionStartBarriers" (
start_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
started_step_run_version INTEGER NOT NULL,
step_run_mutation_id TEXT NOT NULL,
run_event_id TEXT NOT NULL,
trace_id TEXT NOT NULL,
span_id TEXT NOT NULL,
audit_event_id TEXT NOT NULL,
command_digest TEXT NOT NULL,
barrier_digest TEXT NOT NULL,
started_at_ms INTEGER NOT NULL,
barrier_json TEXT NOT NULL,
CONSTRAINT ql3_tool_start_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "StepRunMutations" (mutation_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "RunEvents" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_trace_fk
FOREIGN KEY (trace_id, span_id)
REFERENCES "ToolExecutionTraceAnchors" (trace_id, span_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ToolExecutionAuditReceipts" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_identity_check CHECK (
length(start_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(step_run_mutation_id) BETWEEN 1 AND 128 AND
length(run_event_id) BETWEEN 1 AND 128 AND
length(trace_id) = 32 AND trace_id NOT GLOB '*[^0-9a-f]*' AND
length(span_id) = 16 AND span_id NOT GLOB '*[^0-9a-f]*' AND
length(audit_event_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_start_version_time_check CHECK (
started_step_run_version BETWEEN 2 AND 2147483647 AND
started_at_ms >= 0
),
CONSTRAINT ql3_tool_start_digest_check CHECK (
length(command_digest) = 64 AND
command_digest NOT GLOB '*[^0-9a-f]*' AND
length(barrier_digest) = 64 AND
barrier_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_start_json_check CHECK (
length(CAST(barrier_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(barrier_json) AND json_type(barrier_json) = 'object' AND
json_extract(barrier_json, '$.schema') =
'qinglong/tool-execution-start-barrier@v1' AND
json_extract(barrier_json, '$.startId') = start_id AND
json_extract(barrier_json, '$.projectId') = project_id AND
json_extract(barrier_json, '$.runId') = run_id AND
json_extract(barrier_json, '$.stepRunId') = step_run_id AND
json_extract(barrier_json, '$.startedStepRunVersion') IS
started_step_run_version AND
json_extract(barrier_json, '$.stepRunMutationId') =
step_run_mutation_id AND
json_extract(barrier_json, '$.runEventId') = run_event_id AND
json_extract(barrier_json, '$.traceId') = trace_id AND
json_extract(barrier_json, '$.spanId') = span_id AND
json_extract(barrier_json, '$.auditEventId') = audit_event_id AND
json_extract(barrier_json, '$.commandDigest') = command_digest AND
json_extract(barrier_json, '$.barrierDigest') = barrier_digest AND
json_extract(barrier_json, '$.startedAtMs') IS started_at_ms
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_start_step_version_uidx ON "ToolExecutionStartBarriers" (run_id, step_run_id, started_step_run_version)`,
`CREATE UNIQUE INDEX ql3_tool_start_mutation_uidx ON "ToolExecutionStartBarriers" (step_run_mutation_id)`,
`CREATE UNIQUE INDEX ql3_tool_start_event_uidx ON "ToolExecutionStartBarriers" (run_event_id)`,
`CREATE UNIQUE INDEX ql3_tool_start_trace_uidx ON "ToolExecutionStartBarriers" (trace_id, span_id)`,
`CREATE UNIQUE INDEX ql3_tool_start_audit_uidx ON "ToolExecutionStartBarriers" (audit_event_id)`,
`CREATE INDEX ql3_tool_start_run_time_idx ON "ToolExecutionStartBarriers" (run_id, started_at_ms, start_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1}';
export const local0056CapabilityV28Migration = defineLocalSqliteMigration({
id: '0056-capability-v28',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 28,
migration_id = '0055-tool-execution-start-barriers',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 27
AND migration_id = '0053-tool-execution-evidence'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,117 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0057ToolInvocationArtifactsMigration =
defineLocalSqliteMigration({
id: '0057-tool-invocation-artifacts',
statements: [
`
CREATE TABLE "ToolInvocationInputArtifacts" (
artifact_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
action_ref TEXT NOT NULL,
input_digest TEXT NOT NULL,
invocation_action_digest TEXT NOT NULL,
artifact_digest TEXT NOT NULL,
key_id TEXT NOT NULL,
algorithm TEXT NOT NULL,
plaintext_bytes INTEGER NOT NULL,
sealed_at_ms INTEGER NOT NULL,
artifact_json TEXT NOT NULL,
CONSTRAINT ql3_tool_input_artifact_project_fk
FOREIGN KEY (project_id)
REFERENCES "QingLong3Projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_input_artifact_identity_check CHECK (
length(artifact_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255 AND
length(key_id) BETWEEN 1 AND 128 AND
algorithm = 'aes-256-gcm'
),
CONSTRAINT ql3_tool_input_artifact_digest_check CHECK (
length(input_digest) = 64 AND
input_digest NOT GLOB '*[^0-9a-f]*' AND
length(invocation_action_digest) = 64 AND
invocation_action_digest NOT GLOB '*[^0-9a-f]*' AND
length(artifact_digest) = 64 AND
artifact_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_input_artifact_budget_check CHECK (
plaintext_bytes BETWEEN 0 AND 65536 AND sealed_at_ms >= 0
),
CONSTRAINT ql3_tool_input_artifact_json_check CHECK (
length(CAST(artifact_json AS BLOB)) BETWEEN 2 AND 98304 AND
json_valid(artifact_json) AND json_type(artifact_json) = 'object' AND
json_extract(artifact_json, '$.schema') =
'qinglong/tool-invocation-input-artifact@v1' AND
json_extract(artifact_json, '$.artifactId') = artifact_id AND
json_extract(artifact_json, '$.projectId') = project_id AND
json_extract(artifact_json, '$.actionRef') = action_ref AND
json_extract(artifact_json, '$.inputDigest') = input_digest AND
json_extract(artifact_json, '$.invocationActionDigest') =
invocation_action_digest AND
json_extract(artifact_json, '$.artifactDigest') = artifact_digest AND
json_extract(artifact_json, '$.keyId') = key_id AND
json_extract(artifact_json, '$.algorithm') = algorithm AND
json_extract(artifact_json, '$.plaintextBytes') IS plaintext_bytes AND
json_extract(artifact_json, '$.sealedAtMs') IS sealed_at_ms
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_input_artifact_action_uidx ON "ToolInvocationInputArtifacts" (project_id, action_ref)`,
`CREATE INDEX ql3_tool_input_artifact_project_time_idx ON "ToolInvocationInputArtifacts" (project_id, sealed_at_ms, artifact_id)`,
`
CREATE TABLE "ToolInvocationPreviewArtifacts" (
artifact_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
action_ref TEXT NOT NULL,
action_digest TEXT NOT NULL,
preview_digest TEXT NOT NULL,
redaction_contract_digest TEXT NOT NULL,
artifact_digest TEXT NOT NULL,
byte_length INTEGER NOT NULL,
sealed_at_ms INTEGER NOT NULL,
artifact_json TEXT NOT NULL,
CONSTRAINT ql3_tool_preview_artifact_project_fk
FOREIGN KEY (project_id)
REFERENCES "QingLong3Projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_preview_artifact_identity_check CHECK (
length(artifact_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255
),
CONSTRAINT ql3_tool_preview_artifact_digest_check CHECK (
length(action_digest) = 64 AND
action_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_digest) = 64 AND
preview_digest NOT GLOB '*[^0-9a-f]*' AND
length(redaction_contract_digest) = 64 AND
redaction_contract_digest NOT GLOB '*[^0-9a-f]*' AND
length(artifact_digest) = 64 AND
artifact_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_preview_artifact_budget_check CHECK (
byte_length BETWEEN 2 AND 8192 AND sealed_at_ms >= 0
),
CONSTRAINT ql3_tool_preview_artifact_json_check CHECK (
length(CAST(artifact_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(artifact_json) AND json_type(artifact_json) = 'object' AND
json_extract(artifact_json, '$.schema') =
'qinglong/tool-invocation-preview-artifact@v1' AND
json_extract(artifact_json, '$.artifactId') = artifact_id AND
json_extract(artifact_json, '$.projectId') = project_id AND
json_extract(artifact_json, '$.actionRef') = action_ref AND
json_extract(artifact_json, '$.actionDigest') = action_digest AND
json_extract(artifact_json, '$.previewDigest') = preview_digest AND
json_extract(artifact_json, '$.redactionContractDigest') =
redaction_contract_digest AND
json_extract(artifact_json, '$.artifactDigest') = artifact_digest AND
json_extract(artifact_json, '$.byteLength') IS byte_length AND
json_extract(artifact_json, '$.sealedAtMs') IS sealed_at_ms
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_preview_artifact_action_uidx ON "ToolInvocationPreviewArtifacts" (project_id, action_ref)`,
`CREATE UNIQUE INDEX ql3_tool_preview_artifact_action_digest_uidx ON "ToolInvocationPreviewArtifacts" (action_digest)`,
`CREATE INDEX ql3_tool_preview_artifact_project_time_idx ON "ToolInvocationPreviewArtifacts" (project_id, sealed_at_ms, artifact_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const PREVIOUS_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1}';
const NEXT_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_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1}';
export const local0058CapabilityV29Migration = defineLocalSqliteMigration({
id: '0058-capability-v29',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 29,
migration_id = '0057-tool-invocation-artifacts',
capabilities = '${NEXT_CAPABILITIES}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 28
AND migration_id = '0055-tool-execution-start-barriers'
AND capabilities = '${PREVIOUS_CAPABILITIES}'
`,
],
});
@@ -0,0 +1,81 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0059ToolExecutionArtifactBindingsMigration =
defineLocalSqliteMigration({
id: '0059-tool-execution-artifact-bindings',
statements: [
`
CREATE UNIQUE INDEX ql3_tool_input_artifact_start_binding_uidx
ON "ToolInvocationInputArtifacts" (
artifact_id, artifact_digest, project_id, action_ref, input_digest
)
`,
`
CREATE UNIQUE INDEX ql3_tool_preview_artifact_start_binding_uidx
ON "ToolInvocationPreviewArtifacts" (
artifact_id, artifact_digest, project_id, action_ref, action_digest,
preview_digest, redaction_contract_digest
)
`,
`
CREATE TABLE "ToolExecutionStartArtifactBindings" (
start_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
action_ref TEXT NOT NULL,
input_artifact_id TEXT NOT NULL,
input_artifact_digest TEXT NOT NULL,
input_digest TEXT NOT NULL,
preview_artifact_id TEXT NOT NULL,
preview_artifact_digest TEXT NOT NULL,
action_digest TEXT NOT NULL,
preview_digest TEXT NOT NULL,
redaction_contract_digest TEXT NOT NULL,
bound_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_tool_start_artifact_barrier_fk
FOREIGN KEY (start_id)
REFERENCES "ToolExecutionStartBarriers" (start_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_input_artifact_fk
FOREIGN KEY (
input_artifact_id, input_artifact_digest, project_id, action_ref,
input_digest
)
REFERENCES "ToolInvocationInputArtifacts" (
artifact_id, artifact_digest, project_id, action_ref, input_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_preview_artifact_fk
FOREIGN KEY (
preview_artifact_id, preview_artifact_digest, project_id, action_ref,
action_digest, preview_digest, redaction_contract_digest
)
REFERENCES "ToolInvocationPreviewArtifacts" (
artifact_id, artifact_digest, project_id, action_ref, action_digest,
preview_digest, redaction_contract_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_artifact_identity_check CHECK (
length(start_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(action_ref) BETWEEN 1 AND 255 AND
length(input_artifact_id) BETWEEN 1 AND 128 AND
length(preview_artifact_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_start_artifact_digest_check CHECK (
length(input_artifact_digest) = 64 AND
input_artifact_digest NOT GLOB '*[^0-9a-f]*' AND
length(input_digest) = 64 AND
input_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_artifact_digest) = 64 AND
preview_artifact_digest NOT GLOB '*[^0-9a-f]*' AND
length(action_digest) = 64 AND
action_digest NOT GLOB '*[^0-9a-f]*' AND
length(preview_digest) = 64 AND
preview_digest NOT GLOB '*[^0-9a-f]*' AND
length(redaction_contract_digest) = 64 AND
redaction_contract_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_start_artifact_time_check CHECK (bound_at_ms >= 0)
)
`,
`CREATE INDEX ql3_tool_start_artifact_input_idx ON "ToolExecutionStartArtifactBindings" (input_artifact_id, start_id)`,
`CREATE INDEX ql3_tool_start_artifact_preview_idx ON "ToolExecutionStartArtifactBindings" (preview_artifact_id, start_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V29 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_task_reconciliation":1,"project_tool_definition_snapshot":1,"step_run":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1}';
const CAPABILITIES_V30 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0060CapabilityV30Migration = defineLocalSqliteMigration({
id: '0060-capability-v30',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 30,
migration_id = '0059-tool-execution-artifact-bindings',
capabilities = '${CAPABILITIES_V30}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 29
AND migration_id = '0057-tool-invocation-artifacts'
AND capabilities = '${CAPABILITIES_V29}'
`,
],
});
@@ -0,0 +1,144 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0061ToolExecutionCompletionsMigration =
defineLocalSqliteMigration({
id: '0061-tool-execution-completions',
statements: [
`
CREATE TABLE "ToolExecutionCompletions" (
start_id TEXT PRIMARY KEY NOT NULL,
artifact_id TEXT NOT NULL,
project_id TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
started_step_run_version INTEGER NOT NULL,
completed_step_run_version INTEGER NOT NULL,
barrier_digest TEXT NOT NULL,
adapter_digest TEXT NOT NULL,
output_digest TEXT NOT NULL,
execution_result_digest TEXT NOT NULL,
artifact_digest TEXT NOT NULL,
key_id TEXT NOT NULL,
algorithm TEXT NOT NULL,
plaintext_bytes INTEGER NOT NULL,
step_run_mutation_id TEXT NOT NULL,
step_run_mutation_digest TEXT NOT NULL,
completed_step_run_digest TEXT NOT NULL,
run_event_id TEXT NOT NULL,
completed_at_ms INTEGER NOT NULL,
completion_digest TEXT NOT NULL,
artifact_json TEXT NOT NULL,
completion_json TEXT NOT NULL,
CONSTRAINT ql3_tool_completion_start_fk
FOREIGN KEY (start_id)
REFERENCES "ToolExecutionStartBarriers" (start_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "StepRunMutations" (mutation_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "RunEvents" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_identity_check CHECK (
length(start_id) BETWEEN 1 AND 128 AND
length(artifact_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(key_id) BETWEEN 1 AND 128 AND
length(step_run_mutation_id) BETWEEN 1 AND 128 AND
length(run_event_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_completion_version_check CHECK (
started_step_run_version BETWEEN 2 AND 2147483646 AND
completed_step_run_version = started_step_run_version + 1
),
CONSTRAINT ql3_tool_completion_digest_check CHECK (
length(barrier_digest) = 64 AND
barrier_digest NOT GLOB '*[^0-9a-f]*' AND
length(adapter_digest) = 64 AND
adapter_digest NOT GLOB '*[^0-9a-f]*' AND
length(output_digest) = 64 AND
output_digest NOT GLOB '*[^0-9a-f]*' AND
length(execution_result_digest) = 64 AND
execution_result_digest NOT GLOB '*[^0-9a-f]*' AND
length(artifact_digest) = 64 AND
artifact_digest NOT GLOB '*[^0-9a-f]*' AND
length(step_run_mutation_digest) = 64 AND
step_run_mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(completed_step_run_digest) = 64 AND
completed_step_run_digest NOT GLOB '*[^0-9a-f]*' AND
length(completion_digest) = 64 AND
completion_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_completion_budget_check CHECK (
algorithm = 'aes-256-gcm' AND
plaintext_bytes BETWEEN 0 AND 262144 AND
completed_at_ms >= 0 AND
length(CAST(artifact_json AS BLOB)) BETWEEN 2 AND 393216 AND
length(CAST(completion_json AS BLOB)) BETWEEN 2 AND 24576
),
CONSTRAINT ql3_tool_completion_json_check CHECK (
json_valid(artifact_json) AND
json_type(artifact_json) = 'object' AND
json_extract(artifact_json, '$.schema') =
'qinglong/tool-execution-result-artifact@v1' AND
json_extract(artifact_json, '$.artifactId') = artifact_id AND
json_extract(artifact_json, '$.projectId') = project_id AND
json_extract(artifact_json, '$.startId') = start_id AND
json_extract(artifact_json, '$.runId') = run_id AND
json_extract(artifact_json, '$.stepRunId') = step_run_id AND
json_extract(artifact_json, '$.barrierDigest') = barrier_digest AND
json_extract(artifact_json, '$.adapterDigest') = adapter_digest AND
json_extract(artifact_json, '$.outputDigest') = output_digest AND
json_extract(artifact_json, '$.executionResultDigest') =
execution_result_digest AND
json_extract(artifact_json, '$.artifactDigest') = artifact_digest AND
json_extract(artifact_json, '$.keyId') = key_id AND
json_extract(artifact_json, '$.algorithm') = algorithm AND
json_extract(artifact_json, '$.plaintextBytes') = plaintext_bytes AND
json_extract(artifact_json, '$.sealedAtMs') = completed_at_ms AND
json_valid(completion_json) AND
json_type(completion_json) = 'object' AND
json_extract(completion_json, '$.schema') =
'qinglong/tool-execution-completion@v1' AND
json_extract(completion_json, '$.startId') = start_id AND
json_extract(completion_json, '$.projectId') = project_id AND
json_extract(completion_json, '$.runId') = run_id AND
json_extract(completion_json, '$.stepRunId') = step_run_id AND
json_extract(completion_json, '$.startedStepRunVersion') =
started_step_run_version AND
json_extract(completion_json, '$.completedStepRunVersion') =
completed_step_run_version AND
json_extract(completion_json, '$.barrierDigest') = barrier_digest AND
json_extract(completion_json, '$.adapterDigest') = adapter_digest AND
json_extract(completion_json, '$.resultArtifact.artifactId') =
artifact_id AND
json_extract(completion_json, '$.resultArtifact.artifactDigest') =
artifact_digest AND
json_extract(completion_json, '$.resultArtifact.outputDigest') =
output_digest AND
json_extract(
completion_json, '$.resultArtifact.executionResultDigest'
) = execution_result_digest AND
json_extract(completion_json, '$.stepRunMutationId') =
step_run_mutation_id AND
json_extract(completion_json, '$.stepRunMutationDigest') =
step_run_mutation_digest AND
json_extract(completion_json, '$.completedStepRunDigest') =
completed_step_run_digest AND
json_extract(completion_json, '$.runEventId') = run_event_id AND
json_extract(completion_json, '$.completedAtMs') = completed_at_ms AND
json_extract(completion_json, '$.completionDigest') = completion_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_completion_artifact_uidx ON "ToolExecutionCompletions" (artifact_id)`,
`CREATE UNIQUE INDEX ql3_tool_completion_mutation_uidx ON "ToolExecutionCompletions" (step_run_mutation_id)`,
`CREATE UNIQUE INDEX ql3_tool_completion_event_uidx ON "ToolExecutionCompletions" (run_event_id)`,
`CREATE UNIQUE INDEX ql3_tool_completion_step_version_uidx ON "ToolExecutionCompletions" (run_id, step_run_id, completed_step_run_version)`,
`CREATE INDEX ql3_tool_completion_project_time_idx ON "ToolExecutionCompletions" (project_id, completed_at_ms, start_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V30 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V31 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0062CapabilityV31Migration = defineLocalSqliteMigration({
id: '0062-capability-v31',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 31,
migration_id = '0061-tool-execution-completions',
capabilities = '${CAPABILITIES_V31}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 30
AND migration_id = '0059-tool-execution-artifact-bindings'
AND capabilities = '${CAPABILITIES_V30}'
`,
],
});
@@ -0,0 +1,113 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0063ToolExecutionFailureCompletionsMigration =
defineLocalSqliteMigration({
id: '0063-tool-execution-failure-completions',
statements: [
`
CREATE TABLE "ToolExecutionFailureCompletions" (
start_id TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
started_step_run_version INTEGER NOT NULL,
completed_step_run_version INTEGER NOT NULL,
barrier_digest TEXT NOT NULL,
adapter_digest TEXT NOT NULL,
outcome TEXT NOT NULL,
result_code TEXT NOT NULL,
error_summary TEXT NOT NULL,
step_run_mutation_id TEXT NOT NULL,
step_run_mutation_digest TEXT NOT NULL,
completed_step_run_digest TEXT NOT NULL,
run_event_id TEXT NOT NULL,
completed_at_ms INTEGER NOT NULL,
completion_digest TEXT NOT NULL,
completion_json TEXT NOT NULL,
CONSTRAINT ql3_tool_failure_completion_start_fk
FOREIGN KEY (start_id)
REFERENCES "ToolExecutionStartBarriers" (start_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "StepRunMutations" (mutation_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "RunEvents" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_identity_check CHECK (
length(start_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(step_run_mutation_id) BETWEEN 1 AND 128 AND
length(run_event_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_failure_completion_version_check CHECK (
started_step_run_version BETWEEN 2 AND 2147483646 AND
completed_step_run_version = started_step_run_version + 1
),
CONSTRAINT ql3_tool_failure_completion_digest_check CHECK (
length(barrier_digest) = 64 AND
barrier_digest NOT GLOB '*[^0-9a-f]*' AND
length(adapter_digest) = 64 AND
adapter_digest NOT GLOB '*[^0-9a-f]*' AND
length(step_run_mutation_digest) = 64 AND
step_run_mutation_digest NOT GLOB '*[^0-9a-f]*' AND
length(completed_step_run_digest) = 64 AND
completed_step_run_digest NOT GLOB '*[^0-9a-f]*' AND
length(completion_digest) = 64 AND
completion_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_failure_completion_fact_check CHECK (
(
outcome = 'failed' AND
result_code = 'tool_adapter_failed' AND
error_summary = 'Trusted Tool execution failed'
) OR (
outcome = 'timed_out' AND
result_code = 'tool_deadline_exceeded' AND
error_summary = 'Trusted Tool execution deadline exceeded'
)
),
CONSTRAINT ql3_tool_failure_completion_budget_check CHECK (
completed_at_ms >= 0 AND
length(CAST(completion_json AS BLOB)) BETWEEN 2 AND 24576
),
CONSTRAINT ql3_tool_failure_completion_json_check CHECK (
json_valid(completion_json) AND
json_type(completion_json) = 'object' AND
json_extract(completion_json, '$.schema') =
'qinglong/tool-execution-failure-completion@v1' AND
json_extract(completion_json, '$.startId') = start_id AND
json_extract(completion_json, '$.projectId') = project_id AND
json_extract(completion_json, '$.runId') = run_id AND
json_extract(completion_json, '$.stepRunId') = step_run_id AND
json_extract(completion_json, '$.startedStepRunVersion') =
started_step_run_version AND
json_extract(completion_json, '$.completedStepRunVersion') =
completed_step_run_version AND
json_extract(completion_json, '$.barrierDigest') = barrier_digest AND
json_extract(completion_json, '$.adapterDigest') = adapter_digest AND
json_extract(completion_json, '$.outcome') = outcome AND
json_extract(completion_json, '$.resultCode') = result_code AND
json_extract(completion_json, '$.errorSummary') = error_summary AND
json_extract(completion_json, '$.stepRunMutationId') =
step_run_mutation_id AND
json_extract(completion_json, '$.stepRunMutationDigest') =
step_run_mutation_digest AND
json_extract(completion_json, '$.completedStepRunDigest') =
completed_step_run_digest AND
json_extract(completion_json, '$.runEventId') = run_event_id AND
json_extract(completion_json, '$.completedAtMs') = completed_at_ms AND
json_extract(completion_json, '$.completionDigest') = completion_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_tool_failure_completion_mutation_uidx ON "ToolExecutionFailureCompletions" (step_run_mutation_id)`,
`CREATE UNIQUE INDEX ql3_tool_failure_completion_event_uidx ON "ToolExecutionFailureCompletions" (run_event_id)`,
`CREATE UNIQUE INDEX ql3_tool_failure_completion_step_version_uidx ON "ToolExecutionFailureCompletions" (run_id, step_run_id, completed_step_run_version)`,
`CREATE INDEX ql3_tool_failure_completion_project_time_idx ON "ToolExecutionFailureCompletions" (project_id, completed_at_ms, start_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V31 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V32 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0064CapabilityV32Migration = defineLocalSqliteMigration({
id: '0064-capability-v32',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 32,
migration_id = '0063-tool-execution-failure-completions',
capabilities = '${CAPABILITIES_V32}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 31
AND migration_id = '0061-tool-execution-completions'
AND capabilities = '${CAPABILITIES_V31}'
`,
],
});
@@ -0,0 +1,155 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0065ToolResultKeyCatalogMigration =
defineLocalSqliteMigration({
id: '0065-tool-result-key-catalog',
statements: [
`
CREATE TABLE "ToolResultKeyCatalogGenerations" (
authority TEXT NOT NULL,
generation INTEGER NOT NULL,
previous_generation INTEGER,
previous_catalog_digest TEXT,
active_key_id TEXT,
mutation_kind TEXT NOT NULL,
mutation_id TEXT NOT NULL,
catalog_digest TEXT NOT NULL,
command_digest TEXT NOT NULL,
committed_at_ms INTEGER NOT NULL,
catalog_json TEXT NOT NULL,
PRIMARY KEY (authority, generation),
UNIQUE (authority, generation, catalog_digest),
UNIQUE (mutation_id),
UNIQUE (catalog_digest),
CONSTRAINT ql3_tool_result_key_catalog_previous_fk
FOREIGN KEY (
authority, previous_generation, previous_catalog_digest
)
REFERENCES "ToolResultKeyCatalogGenerations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_catalog_authority_check CHECK (
authority = 'trusted-tool-results'
),
CONSTRAINT ql3_tool_result_key_catalog_generation_check CHECK (
generation BETWEEN 1 AND 2147483647 AND
(
(
generation = 1 AND
previous_generation IS NULL AND
previous_catalog_digest IS NULL AND
mutation_kind = 'bootstrap'
) OR (
generation > 1 AND
previous_generation = generation - 1 AND
previous_catalog_digest IS NOT NULL AND
mutation_kind IN (
'rotate', 'retire', 'mark_lost', 'restore'
)
)
)
),
CONSTRAINT ql3_tool_result_key_catalog_identity_check CHECK (
active_key_id IS NULL OR
length(active_key_id) BETWEEN 1 AND 128 AND
active_key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(active_key_id, 1, 1) GLOB '[A-Za-z0-9]'
),
CONSTRAINT ql3_tool_result_key_catalog_digest_check CHECK (
(
previous_catalog_digest IS NULL OR
length(previous_catalog_digest) = 64 AND
previous_catalog_digest NOT GLOB '*[^0-9a-f]*'
) AND
length(catalog_digest) = 64 AND
catalog_digest NOT GLOB '*[^0-9a-f]*' AND
length(command_digest) = 64 AND
command_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_result_key_catalog_budget_check CHECK (
committed_at_ms >= 0 AND
length(mutation_id) BETWEEN 1 AND 128 AND
length(CAST(catalog_json AS BLOB)) BETWEEN 2 AND 65536
),
CONSTRAINT ql3_tool_result_key_catalog_json_check CHECK (
json_valid(catalog_json) AND
json_type(catalog_json) = 'object' AND
json_extract(catalog_json, '$.schema') =
'qinglong/tool-result-key-catalog@v1' AND
json_extract(catalog_json, '$.generation') = generation AND
(
(
previous_catalog_digest IS NULL AND
json_type(catalog_json, '$.previousCatalogDigest') = 'null'
) OR
json_extract(catalog_json, '$.previousCatalogDigest') =
previous_catalog_digest
) AND
(
(
active_key_id IS NULL AND
json_type(catalog_json, '$.activeKeyId') = 'null'
) OR
json_extract(catalog_json, '$.activeKeyId') = active_key_id
) AND
json_extract(catalog_json, '$.mutationKind') = mutation_kind AND
json_extract(catalog_json, '$.mutationId') = mutation_id AND
json_extract(catalog_json, '$.catalogDigest') = catalog_digest AND
json_extract(catalog_json, '$.committedAtMs') = committed_at_ms AND
json_type(catalog_json, '$.keys') = 'array' AND
json_array_length(json_extract(catalog_json, '$.keys'))
BETWEEN 1 AND 64
)
)
`,
`CREATE INDEX ql3_tool_result_key_catalog_current_idx ON "ToolResultKeyCatalogGenerations" (authority, generation DESC)`,
`
CREATE TABLE "ToolExecutionResultKeyBindings" (
start_id TEXT PRIMARY KEY NOT NULL,
artifact_id TEXT NOT NULL UNIQUE,
artifact_digest TEXT NOT NULL,
catalog_authority TEXT NOT NULL,
catalog_generation INTEGER NOT NULL,
catalog_digest TEXT NOT NULL,
key_id TEXT NOT NULL,
material_proof TEXT NOT NULL,
binding_digest TEXT NOT NULL UNIQUE,
CONSTRAINT ql3_tool_result_key_binding_completion_fk
FOREIGN KEY (start_id)
REFERENCES "ToolExecutionCompletions" (start_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_binding_artifact_fk
FOREIGN KEY (artifact_id)
REFERENCES "ToolExecutionCompletions" (artifact_id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_binding_catalog_fk
FOREIGN KEY (
catalog_authority, catalog_generation, catalog_digest
)
REFERENCES "ToolResultKeyCatalogGenerations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_binding_authority_check CHECK (
catalog_authority = 'trusted-tool-results'
),
CONSTRAINT ql3_tool_result_key_binding_identity_check CHECK (
length(start_id) BETWEEN 1 AND 128 AND
length(artifact_id) BETWEEN 1 AND 128 AND
length(key_id) BETWEEN 1 AND 128 AND
key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(key_id, 1, 1) GLOB '[A-Za-z0-9]' AND
catalog_generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_tool_result_key_binding_digest_check CHECK (
length(artifact_digest) = 64 AND
artifact_digest NOT GLOB '*[^0-9a-f]*' AND
length(catalog_digest) = 64 AND
catalog_digest NOT GLOB '*[^0-9a-f]*' AND
length(material_proof) = 64 AND
material_proof NOT GLOB '*[^0-9a-f]*' AND
length(binding_digest) = 64 AND
binding_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_tool_result_key_binding_catalog_idx ON "ToolExecutionResultKeyBindings" (catalog_generation, key_id, start_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V32 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V33 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0066CapabilityV33Migration = defineLocalSqliteMigration({
id: '0066-capability-v33',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 33,
migration_id = '0065-tool-result-key-catalog',
capabilities = '${CAPABILITIES_V33}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 32
AND migration_id = '0063-tool-execution-failure-completions'
AND capabilities = '${CAPABILITIES_V32}'
`,
],
});
@@ -0,0 +1,238 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0067ToolResultRekeyOverlaysMigration =
defineLocalSqliteMigration({
id: '0067-tool-result-rekey-overlays',
statements: [
`
CREATE TABLE "ToolExecutionResultRekeyOverlays" (
overlay_id TEXT PRIMARY KEY NOT NULL,
artifact_id TEXT NOT NULL,
source_binding_digest TEXT NOT NULL,
revision INTEGER NOT NULL,
previous_overlay_digest TEXT,
from_key_id TEXT NOT NULL,
target_catalog_authority TEXT NOT NULL,
target_catalog_generation INTEGER NOT NULL,
target_catalog_digest TEXT NOT NULL,
target_key_id TEXT NOT NULL,
target_material_proof TEXT NOT NULL,
mutation_id TEXT NOT NULL UNIQUE,
command_digest TEXT NOT NULL,
overlay_digest TEXT NOT NULL UNIQUE,
rekeyed_at_ms INTEGER NOT NULL,
overlay_json TEXT NOT NULL,
UNIQUE (artifact_id, revision),
UNIQUE (artifact_id, revision, overlay_digest),
CONSTRAINT ql3_tool_result_rekey_artifact_fk
FOREIGN KEY (artifact_id)
REFERENCES "ToolExecutionResultKeyBindings" (artifact_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_rekey_binding_fk
FOREIGN KEY (source_binding_digest)
REFERENCES "ToolExecutionResultKeyBindings" (binding_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_rekey_previous_fk
FOREIGN KEY (previous_overlay_digest)
REFERENCES "ToolExecutionResultRekeyOverlays" (overlay_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_rekey_catalog_fk
FOREIGN KEY (
target_catalog_authority,
target_catalog_generation,
target_catalog_digest
)
REFERENCES "ToolResultKeyCatalogGenerations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_rekey_revision_check CHECK (
revision BETWEEN 1 AND 2147483647 AND
(
(revision = 1 AND previous_overlay_digest IS NULL) OR
(revision > 1 AND previous_overlay_digest IS NOT NULL)
)
),
CONSTRAINT ql3_tool_result_rekey_authority_check CHECK (
target_catalog_authority = 'trusted-tool-results'
),
CONSTRAINT ql3_tool_result_rekey_identity_check CHECK (
length(overlay_id) BETWEEN 1 AND 128 AND
length(artifact_id) BETWEEN 1 AND 128 AND
length(mutation_id) BETWEEN 1 AND 128 AND
length(from_key_id) BETWEEN 1 AND 128 AND
from_key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(from_key_id, 1, 1) GLOB '[A-Za-z0-9]' AND
length(target_key_id) BETWEEN 1 AND 128 AND
target_key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(target_key_id, 1, 1) GLOB '[A-Za-z0-9]' AND
from_key_id <> target_key_id AND
target_catalog_generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_tool_result_rekey_digest_check CHECK (
(
previous_overlay_digest IS NULL OR
length(previous_overlay_digest) = 64 AND
previous_overlay_digest NOT GLOB '*[^0-9a-f]*'
) AND
length(source_binding_digest) = 64 AND
source_binding_digest NOT GLOB '*[^0-9a-f]*' AND
length(target_catalog_digest) = 64 AND
target_catalog_digest NOT GLOB '*[^0-9a-f]*' AND
length(target_material_proof) = 64 AND
target_material_proof NOT GLOB '*[^0-9a-f]*' AND
length(command_digest) = 64 AND
command_digest NOT GLOB '*[^0-9a-f]*' AND
length(overlay_digest) = 64 AND
overlay_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_result_rekey_budget_check CHECK (
rekeyed_at_ms >= 0 AND
length(CAST(overlay_json AS BLOB)) BETWEEN 2 AND 393216
),
CONSTRAINT ql3_tool_result_rekey_json_check CHECK (
json_valid(overlay_json) AND
json_type(overlay_json) = 'object' AND
json_extract(overlay_json, '$.schema') =
'qinglong/tool-execution-result-rekey-overlay@v1' AND
json_extract(overlay_json, '$.overlayId') = overlay_id AND
json_extract(overlay_json, '$.sourceArtifact.artifactId') =
artifact_id AND
json_extract(overlay_json, '$.sourceBindingDigest') =
source_binding_digest AND
json_extract(overlay_json, '$.revision') = revision AND
(
(
previous_overlay_digest IS NULL AND
json_type(overlay_json, '$.previousOverlayDigest') = 'null'
) OR
json_extract(overlay_json, '$.previousOverlayDigest') =
previous_overlay_digest
) AND
json_extract(overlay_json, '$.fromKeyId') = from_key_id AND
json_extract(overlay_json, '$.targetCatalogFence.generation') =
target_catalog_generation AND
json_extract(overlay_json, '$.targetCatalogFence.catalogDigest') =
target_catalog_digest AND
json_extract(overlay_json, '$.targetCatalogFence.keyId') =
target_key_id AND
json_extract(overlay_json, '$.targetCatalogFence.materialProof') =
target_material_proof AND
json_extract(overlay_json, '$.rekeyedAtMs') = rekeyed_at_ms AND
json_extract(overlay_json, '$.overlayDigest') = overlay_digest
)
)
`,
`CREATE INDEX ql3_tool_result_rekey_artifact_idx ON "ToolExecutionResultRekeyOverlays" (artifact_id, revision DESC)`,
`CREATE INDEX ql3_tool_result_rekey_target_idx ON "ToolExecutionResultRekeyOverlays" (target_key_id, artifact_id, revision DESC)`,
`
CREATE TABLE "ToolExecutionResultRekeyHeads" (
artifact_id TEXT PRIMARY KEY NOT NULL,
revision INTEGER NOT NULL,
overlay_id TEXT NOT NULL UNIQUE,
overlay_digest TEXT NOT NULL UNIQUE,
target_catalog_generation INTEGER NOT NULL,
target_catalog_digest TEXT NOT NULL,
target_key_id TEXT NOT NULL,
updated_at_ms INTEGER NOT NULL,
CONSTRAINT ql3_tool_result_rekey_head_overlay_fk
FOREIGN KEY (artifact_id, revision, overlay_digest)
REFERENCES "ToolExecutionResultRekeyOverlays" (
artifact_id, revision, overlay_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_rekey_head_identity_check CHECK (
revision BETWEEN 1 AND 2147483647 AND
length(artifact_id) BETWEEN 1 AND 128 AND
length(overlay_id) BETWEEN 1 AND 128 AND
length(target_key_id) BETWEEN 1 AND 128 AND
target_key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(target_key_id, 1, 1) GLOB '[A-Za-z0-9]' AND
target_catalog_generation BETWEEN 1 AND 2147483647 AND
updated_at_ms >= 0
),
CONSTRAINT ql3_tool_result_rekey_head_digest_check CHECK (
length(overlay_digest) = 64 AND
overlay_digest NOT GLOB '*[^0-9a-f]*' AND
length(target_catalog_digest) = 64 AND
target_catalog_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_tool_result_rekey_head_target_idx ON "ToolExecutionResultRekeyHeads" (target_key_id, artifact_id)`,
`
CREATE TABLE "ToolResultKeyRetirementReceipts" (
receipt_digest TEXT PRIMARY KEY NOT NULL,
catalog_authority TEXT NOT NULL,
catalog_generation INTEGER NOT NULL,
catalog_digest TEXT NOT NULL,
key_id TEXT NOT NULL,
material_proof TEXT NOT NULL,
mutation_id TEXT NOT NULL UNIQUE,
command_digest TEXT NOT NULL,
binding_count INTEGER NOT NULL,
overlay_head_count INTEGER NOT NULL,
uncovered_binding_count INTEGER NOT NULL,
uncovered_overlay_head_count INTEGER NOT NULL,
coverage_digest TEXT NOT NULL,
created_at_ms INTEGER NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_tool_result_key_retirement_catalog_fk
FOREIGN KEY (
catalog_authority, catalog_generation, catalog_digest
)
REFERENCES "ToolResultKeyCatalogGenerations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_retirement_authority_check CHECK (
catalog_authority = 'trusted-tool-results'
),
CONSTRAINT ql3_tool_result_key_retirement_identity_check CHECK (
catalog_generation BETWEEN 1 AND 2147483647 AND
length(key_id) BETWEEN 1 AND 128 AND
key_id NOT GLOB '*[^A-Za-z0-9._-]*' AND
substr(key_id, 1, 1) GLOB '[A-Za-z0-9]' AND
length(mutation_id) BETWEEN 1 AND 128
),
CONSTRAINT ql3_tool_result_key_retirement_count_check CHECK (
binding_count BETWEEN 0 AND 2147483647 AND
overlay_head_count BETWEEN 0 AND 2147483647 AND
uncovered_binding_count = 0 AND
uncovered_overlay_head_count = 0 AND
created_at_ms >= 0
),
CONSTRAINT ql3_tool_result_key_retirement_digest_check CHECK (
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*' AND
length(catalog_digest) = 64 AND
catalog_digest NOT GLOB '*[^0-9a-f]*' AND
length(material_proof) = 64 AND
material_proof NOT GLOB '*[^0-9a-f]*' AND
length(command_digest) = 64 AND
command_digest NOT GLOB '*[^0-9a-f]*' AND
length(coverage_digest) = 64 AND
coverage_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_tool_result_key_retirement_json_check CHECK (
json_valid(receipt_json) AND
json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/tool-result-key-retirement-receipt@v1' AND
json_extract(receipt_json, '$.catalogGeneration') =
catalog_generation AND
json_extract(receipt_json, '$.catalogDigest') = catalog_digest AND
json_extract(receipt_json, '$.keyId') = key_id AND
json_extract(receipt_json, '$.materialProof') = material_proof AND
json_extract(receipt_json, '$.mutationId') = mutation_id AND
json_extract(receipt_json, '$.bindingCount') = binding_count AND
json_extract(receipt_json, '$.overlayHeadCount') =
overlay_head_count AND
json_extract(receipt_json, '$.uncoveredBindingCount') = 0 AND
json_extract(receipt_json, '$.uncoveredOverlayHeadCount') = 0 AND
json_extract(receipt_json, '$.coverageDigest') = coverage_digest AND
json_extract(receipt_json, '$.createdAtMs') = created_at_ms AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
)
)
`,
`CREATE INDEX ql3_tool_result_key_retirement_catalog_idx ON "ToolResultKeyRetirementReceipts" (catalog_generation, key_id)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V33 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V34 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0068CapabilityV34Migration = defineLocalSqliteMigration({
id: '0068-capability-v34',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 34,
migration_id = '0067-tool-result-rekey-overlays',
capabilities = '${CAPABILITIES_V34}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 33
AND migration_id = '0065-tool-result-key-catalog'
AND capabilities = '${CAPABILITIES_V33}'
`,
],
});
@@ -0,0 +1,298 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0069PluginPackageQuarantineMigration =
defineLocalSqliteMigration({
id: '0069-plugin-package-quarantine',
statements: [
`
CREATE UNIQUE INDEX ql3_plugin_package_installs_quarantine_target_uidx
ON "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, lock_digest, record_digest
)
`,
`
CREATE UNIQUE INDEX ql3_project_tool_definition_snapshot_withdrawal_uidx
ON "QingLong3ProjectToolDefinitionSnapshots" (
project_id, active_vector_digest, snapshot_digest
)
`,
`
CREATE TABLE "QingLong3PluginPackageQuarantineEvents" (
event_digest TEXT PRIMARY KEY NOT NULL,
mutation_id TEXT NOT NULL,
revocation_receipt_digest TEXT NOT NULL,
impact_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
install_state TEXT NOT NULL,
install_version INTEGER NOT NULL,
install_record_digest TEXT NOT NULL,
active_lock_digest TEXT,
proposer_type TEXT NOT NULL,
proposer_id TEXT NOT NULL,
confirmer_type TEXT NOT NULL,
confirmer_id TEXT NOT NULL,
authorization_mode TEXT NOT NULL,
reason_code TEXT NOT NULL,
occurred_at_ms INTEGER NOT NULL,
event_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_quarantine_install_fk
FOREIGN KEY (
project_id, package_name, installation_id, lock_digest,
install_record_digest
)
REFERENCES "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, lock_digest, record_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_quarantine_identity_check CHECK (
length(mutation_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63 AND
length(installation_id) BETWEEN 1 AND 128 AND
install_state IN ('queued','staged','activating','active') AND
install_version BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_quarantine_state_check CHECK (
(
install_state = 'active' AND active_lock_digest = lock_digest
) OR (
install_state <> 'active' AND
(active_lock_digest IS NULL OR active_lock_digest <> lock_digest)
)
),
CONSTRAINT ql3_plugin_package_quarantine_subject_check CHECK (
proposer_type IN ('user','api_app','mcp_client','agent','system','worker') AND
confirmer_type IN ('user','api_app','mcp_client','agent','system','worker') AND
length(proposer_id) BETWEEN 1 AND 255 AND
length(confirmer_id) BETWEEN 1 AND 255 AND
authorization_mode IN ('dual_control','break_glass') AND
(
authorization_mode = 'break_glass' OR
proposer_type <> confirmer_type OR proposer_id <> confirmer_id
) AND
reason_code IN (
'suspected_key_compromise','confirmed_key_compromise'
)
),
CONSTRAINT ql3_plugin_package_quarantine_digest_check CHECK (
length(event_digest) = 64 AND
event_digest NOT GLOB '*[^0-9a-f]*' AND
length(revocation_receipt_digest) = 64 AND
revocation_receipt_digest NOT GLOB '*[^0-9a-f]*' AND
length(impact_digest) = 64 AND
impact_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(install_record_digest) = 64 AND
install_record_digest NOT GLOB '*[^0-9a-f]*' AND
(
active_lock_digest IS NULL OR
length(active_lock_digest) = 64 AND
active_lock_digest NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_plugin_package_quarantine_json_check CHECK (
length(CAST(event_json AS BLOB)) BETWEEN 2 AND 262144 AND
json_valid(event_json) AND json_type(event_json) = 'object' AND
json_extract(event_json, '$.schema') =
'qinglong/plugin-package-quarantine-event@v1' AND
json_extract(event_json, '$.mutationId') = mutation_id AND
json_extract(event_json, '$.revocationReceiptDigest') =
revocation_receipt_digest AND
json_extract(event_json, '$.impactDigest') = impact_digest AND
json_extract(event_json, '$.target.projectId') = project_id AND
json_extract(event_json, '$.target.packageName') = package_name AND
json_extract(event_json, '$.target.installationId') = installation_id AND
json_extract(event_json, '$.target.lockDigest') = lock_digest AND
json_extract(event_json, '$.target.installState') = install_state AND
json_extract(event_json, '$.target.installVersion') = install_version AND
json_extract(event_json, '$.target.installRecordDigest') =
install_record_digest AND
(
(
active_lock_digest IS NULL AND
json_type(event_json, '$.target.activeLockDigest') = 'null'
) OR
json_extract(event_json, '$.target.activeLockDigest') =
active_lock_digest
) AND
json_extract(event_json, '$.proposer.type') = proposer_type AND
json_extract(event_json, '$.proposer.id') = proposer_id AND
json_extract(event_json, '$.confirmer.type') = confirmer_type AND
json_extract(event_json, '$.confirmer.id') = confirmer_id AND
json_extract(event_json, '$.authorizationMode') = authorization_mode AND
json_extract(event_json, '$.reasonCode') = reason_code AND
json_extract(event_json, '$.occurredAtMs') = occurred_at_ms AND
json_extract(event_json, '$.eventDigest') = event_digest
),
CONSTRAINT ql3_plugin_package_quarantine_time_check CHECK (
occurred_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_quarantine_mutation_uidx ON "QingLong3PluginPackageQuarantineEvents" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_quarantine_target_uidx ON "QingLong3PluginPackageQuarantineEvents" (project_id, package_name, installation_id, lock_digest)`,
`CREATE INDEX ql3_plugin_package_quarantine_lock_idx ON "QingLong3PluginPackageQuarantineEvents" (lock_digest, project_id, package_name)`,
`CREATE INDEX ql3_plugin_package_quarantine_project_idx ON "QingLong3PluginPackageQuarantineEvents" (project_id, package_name, occurred_at_ms, event_digest)`,
`
CREATE TABLE "QingLong3PluginPackageWithdrawalReceipts" (
event_digest TEXT PRIMARY KEY NOT NULL,
receipt_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
capability_status TEXT NOT NULL,
task_count INTEGER NOT NULL,
previous_active_vector_digest TEXT,
current_active_vector_digest TEXT,
current_tool_snapshot_digest TEXT,
retained_source_count INTEGER NOT NULL,
committed_at_ms INTEGER NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_withdrawal_event_fk
FOREIGN KEY (event_digest)
REFERENCES "QingLong3PluginPackageQuarantineEvents" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_snapshot_fk
FOREIGN KEY (
project_id, current_active_vector_digest, current_tool_snapshot_digest
)
REFERENCES "QingLong3ProjectToolDefinitionSnapshots" (
project_id, active_vector_digest, snapshot_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_disposition_check CHECK (
(
capability_status = 'not_active' AND
task_count = 0 AND
previous_active_vector_digest IS NULL AND
current_active_vector_digest IS NULL AND
current_tool_snapshot_digest IS NULL AND
retained_source_count = 0
) OR (
capability_status = 'withdrawn' AND
task_count BETWEEN 0 AND 128 AND
previous_active_vector_digest IS NOT NULL AND
current_active_vector_digest IS NOT NULL AND
previous_active_vector_digest <> current_active_vector_digest AND
current_tool_snapshot_digest IS NOT NULL AND
retained_source_count BETWEEN 0 AND 128
)
),
CONSTRAINT ql3_plugin_package_withdrawal_digest_check CHECK (
length(event_digest) = 64 AND
event_digest NOT GLOB '*[^0-9a-f]*' AND
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*' AND
(
previous_active_vector_digest IS NULL OR
length(previous_active_vector_digest) = 64 AND
previous_active_vector_digest NOT GLOB '*[^0-9a-f]*'
) AND
(
current_active_vector_digest IS NULL OR
length(current_active_vector_digest) = 64 AND
current_active_vector_digest NOT GLOB '*[^0-9a-f]*'
) AND
(
current_tool_snapshot_digest IS NULL OR
length(current_tool_snapshot_digest) = 64 AND
current_tool_snapshot_digest NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_plugin_package_withdrawal_json_check CHECK (
length(CAST(receipt_json AS BLOB)) BETWEEN 2 AND 8388608 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-withdrawal-receipt@v1' AND
json_extract(receipt_json, '$.eventDigest') = event_digest AND
json_extract(receipt_json, '$.target.projectId') = project_id AND
json_extract(receipt_json, '$.capability.status') = capability_status AND
json_array_length(
json_extract(receipt_json, '$.capability.taskWithdrawals')
) = task_count AND
(
(
previous_active_vector_digest IS NULL AND
json_type(
receipt_json, '$.capability.previousActiveVectorDigest'
) = 'null'
) OR
json_extract(
receipt_json, '$.capability.previousActiveVectorDigest'
) = previous_active_vector_digest
) AND
(
(
current_active_vector_digest IS NULL AND
json_type(
receipt_json, '$.capability.currentActiveVectorDigest'
) = 'null'
) OR
json_extract(
receipt_json, '$.capability.currentActiveVectorDigest'
) = current_active_vector_digest
) AND
(
(
current_tool_snapshot_digest IS NULL AND
json_type(
receipt_json, '$.capability.currentToolSnapshotDigest'
) = 'null'
) OR
json_extract(
receipt_json, '$.capability.currentToolSnapshotDigest'
) = current_tool_snapshot_digest
) AND
json_extract(receipt_json, '$.capability.retainedSourceCount') =
retained_source_count AND
json_extract(receipt_json, '$.committedAtMs') = committed_at_ms AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
),
CONSTRAINT ql3_plugin_package_withdrawal_time_check CHECK (
committed_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_withdrawal_receipt_uidx ON "QingLong3PluginPackageWithdrawalReceipts" (receipt_digest)`,
`CREATE INDEX ql3_plugin_package_withdrawal_snapshot_idx ON "QingLong3PluginPackageWithdrawalReceipts" (current_tool_snapshot_digest, event_digest)`,
`
CREATE TABLE "QingLong3PluginPackageWithdrawalTasks" (
event_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
task_id TEXT NOT NULL,
previous_revision INTEGER NOT NULL,
disabled_revision INTEGER NOT NULL,
previous_content_digest TEXT NOT NULL,
disabled_content_digest TEXT NOT NULL,
PRIMARY KEY (event_digest, task_id),
CONSTRAINT ql3_plugin_package_withdrawal_task_receipt_fk
FOREIGN KEY (event_digest)
REFERENCES "QingLong3PluginPackageWithdrawalReceipts" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_task_previous_fk
FOREIGN KEY (project_id, task_id, previous_revision)
REFERENCES "QingLong3TaskDefinitionRevisions" (
project_id, task_id, revision
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_task_disabled_fk
FOREIGN KEY (project_id, task_id, disabled_revision)
REFERENCES "QingLong3TaskDefinitionRevisions" (
project_id, task_id, revision
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_task_identity_check CHECK (
length(task_id) BETWEEN 1 AND 128 AND
previous_revision BETWEEN 1 AND 2147483646 AND
disabled_revision = previous_revision + 1
),
CONSTRAINT ql3_plugin_package_withdrawal_task_digest_check CHECK (
length(event_digest) = 64 AND
event_digest NOT GLOB '*[^0-9a-f]*' AND
length(previous_content_digest) = 64 AND
previous_content_digest NOT GLOB '*[^0-9a-f]*' AND
length(disabled_content_digest) = 64 AND
disabled_content_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_plugin_package_withdrawal_task_task_idx ON "QingLong3PluginPackageWithdrawalTasks" (project_id, task_id, event_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V34 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V35 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
export const local0070CapabilityV35Migration = defineLocalSqliteMigration({
id: '0070-capability-v35',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 35,
migration_id = '0069-plugin-package-quarantine',
capabilities = '${CAPABILITIES_V35}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 34
AND migration_id = '0067-tool-result-rekey-overlays'
AND capabilities = '${CAPABILITIES_V34}'
`,
],
});
@@ -0,0 +1,221 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0071LocalIdentityCredentialAdministrationMigration =
defineLocalSqliteMigration({
id: '0071-local-identity-credential-administration',
statements: [
`
CREATE UNIQUE INDEX "ql3_local_credential_pepper_binding_triple_uidx"
ON "QingLong3ApiCredentialPepperBindings" (
"credential_id", "credential_version", "pepper_key_id"
)
`,
`
CREATE TABLE "QingLong3IdentityAdministrationMutations" (
"mutation_id" TEXT PRIMARY KEY NOT NULL,
"project_id" TEXT NOT NULL,
"operation" TEXT NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"subject_version" INTEGER NOT NULL,
"expected_previous_version" INTEGER NOT NULL,
"status" TEXT NOT NULL,
"changed_by_type" TEXT NOT NULL,
"changed_by_id" TEXT NOT NULL,
"audit_event_id" TEXT NOT NULL UNIQUE,
"identity_created_at_ms" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("subject_type", "subject_id")
REFERENCES "QingLong3IdentitySubjects" ("subject_type", "subject_id")
ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_identity_admin_mutation_id_check CHECK (
length("mutation_id") = 36
),
CONSTRAINT ql3_identity_admin_operation_check CHECK (
"operation" IN ('register','enable','disable')
),
CONSTRAINT ql3_identity_admin_subject_check CHECK (
"subject_type" IN ('user','api_app','mcp_client','agent')
AND length("subject_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_identity_admin_transition_check CHECK (
"subject_version" = "expected_previous_version" + 1
AND "subject_version" BETWEEN 1 AND 2147483647
AND "expected_previous_version" BETWEEN 0 AND 2147483646
AND (
("operation" = 'register'
AND "expected_previous_version" = 0 AND "status" = 'active')
OR ("operation" = 'enable'
AND "expected_previous_version" > 0 AND "status" = 'active')
OR ("operation" = 'disable'
AND "expected_previous_version" > 0 AND "status" = 'disabled')
)
),
CONSTRAINT ql3_identity_admin_actor_check CHECK (
"changed_by_type" = 'user'
AND length("changed_by_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_identity_admin_audit_check CHECK (
"audit_event_id" = "mutation_id"
),
CONSTRAINT ql3_identity_admin_time_check CHECK (
"identity_created_at_ms" >= 0
AND "created_at_ms" >= "identity_created_at_ms"
)
)
`,
`
CREATE INDEX "ql3_identity_admin_subject_idx"
ON "QingLong3IdentityAdministrationMutations" (
"subject_type", "subject_id", "subject_version" DESC
)
`,
`
CREATE TABLE "QingLong3ApiCredentialAdministrationMutations" (
"mutation_id" TEXT PRIMARY KEY NOT NULL,
"project_id" TEXT NOT NULL,
"operation" TEXT NOT NULL,
"credential_id" TEXT NOT NULL,
"credential_version" INTEGER NOT NULL,
"expected_previous_version" INTEGER NOT NULL,
"subject_type" TEXT NOT NULL,
"subject_id" TEXT NOT NULL,
"subject_status" TEXT NOT NULL,
"state" TEXT NOT NULL,
"pepper_key_id" TEXT NOT NULL,
"secret_digest" TEXT NOT NULL,
"not_before_at_ms" INTEGER NOT NULL,
"expires_at_ms" INTEGER NOT NULL,
"delivery_digest" TEXT,
"changed_by_type" TEXT NOT NULL,
"changed_by_id" TEXT NOT NULL,
"audit_event_id" TEXT NOT NULL UNIQUE,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("credential_id", "credential_version")
REFERENCES "QingLong3ApiCredentials" ("credential_id", "version")
ON DELETE RESTRICT,
FOREIGN KEY ("credential_id", "credential_version", "pepper_key_id")
REFERENCES "QingLong3ApiCredentialPepperBindings" (
"credential_id", "credential_version", "pepper_key_id"
) ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_credential_admin_mutation_id_check CHECK (
length("mutation_id") = 36
),
CONSTRAINT ql3_credential_admin_operation_check CHECK (
"operation" IN ('issue','rotate','revoke')
),
CONSTRAINT ql3_credential_admin_identity_check CHECK (
length("credential_id") BETWEEN 1 AND 64
AND "credential_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND "subject_type" IN ('user','api_app','mcp_client','agent')
AND length("subject_id") BETWEEN 1 AND 255
AND "subject_status" IN ('active','disabled')
),
CONSTRAINT ql3_credential_admin_transition_check CHECK (
"credential_version" = "expected_previous_version" + 1
AND "credential_version" BETWEEN 1 AND 2147483647
AND "expected_previous_version" BETWEEN 0 AND 2147483646
AND (
("operation" = 'issue'
AND "expected_previous_version" = 0 AND "state" = 'active')
OR ("operation" = 'rotate'
AND "expected_previous_version" > 0 AND "state" = 'active')
OR ("operation" = 'revoke'
AND "expected_previous_version" > 0 AND "state" = 'revoked')
)
),
CONSTRAINT ql3_credential_admin_digest_check CHECK (
length("pepper_key_id") BETWEEN 1 AND 64
AND "pepper_key_id" NOT GLOB '*[^A-Za-z0-9._:-]*'
AND length("secret_digest") = 64
AND "secret_digest" NOT GLOB '*[^0-9a-f]*'
AND (
("operation" IN ('issue','rotate')
AND length("delivery_digest") = 64
AND "delivery_digest" NOT GLOB '*[^0-9a-f]*')
OR ("operation" = 'revoke' AND "delivery_digest" IS NULL)
)
),
CONSTRAINT ql3_credential_admin_lifetime_check CHECK (
"created_at_ms" >= 0
AND "not_before_at_ms" >= "created_at_ms"
AND "expires_at_ms" > "not_before_at_ms"
),
CONSTRAINT ql3_credential_admin_actor_check CHECK (
"changed_by_type" = 'user'
AND length("changed_by_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_credential_admin_audit_check CHECK (
"audit_event_id" = "mutation_id"
)
)
`,
`
CREATE INDEX "ql3_credential_admin_credential_idx"
ON "QingLong3ApiCredentialAdministrationMutations" (
"credential_id", "credential_version" DESC
)
`,
`
CREATE INDEX "ql3_credential_admin_subject_idx"
ON "QingLong3ApiCredentialAdministrationMutations" (
"subject_type", "subject_id", "created_at_ms" DESC
)
`,
`
CREATE TABLE "QingLong3ApiCredentialDeliveryAcknowledgements" (
"credential_mutation_id" TEXT PRIMARY KEY NOT NULL,
"acknowledgement_mutation_id" TEXT NOT NULL UNIQUE,
"project_id" TEXT NOT NULL,
"delivery_digest" TEXT NOT NULL,
"acknowledged_by_type" TEXT NOT NULL,
"acknowledged_by_id" TEXT NOT NULL,
"audit_event_id" TEXT NOT NULL UNIQUE,
"acknowledged_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("credential_mutation_id")
REFERENCES "QingLong3ApiCredentialAdministrationMutations" ("mutation_id")
ON DELETE RESTRICT,
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_credential_delivery_ack_identity_check CHECK (
length("credential_mutation_id") = 36
AND length("acknowledgement_mutation_id") = 36
AND "credential_mutation_id" <> "acknowledgement_mutation_id"
),
CONSTRAINT ql3_credential_delivery_ack_digest_check CHECK (
length("delivery_digest") = 64
AND "delivery_digest" NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_credential_delivery_ack_actor_check CHECK (
"acknowledged_by_type" = 'user'
AND length("acknowledged_by_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_credential_delivery_ack_audit_check CHECK (
"audit_event_id" = "acknowledgement_mutation_id"
),
CONSTRAINT ql3_credential_delivery_ack_time_check CHECK (
"acknowledged_at_ms" >= 0
)
)
`,
`
CREATE INDEX "ql3_credential_delivery_ack_project_idx"
ON "QingLong3ApiCredentialDeliveryAcknowledgements" (
"project_id", "acknowledged_at_ms" DESC
)
`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V35 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":1,"local_secret_authorized_mutation":1,"local_identity":1,"local_api_credential":1,"local_identity_provisioning":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_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}';
const CAPABILITIES_V36 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":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_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}';
export const local0072CapabilityV36Migration = defineLocalSqliteMigration({
id: '0072-capability-v36',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 36,
migration_id = '0071-local-identity-credential-administration',
capabilities = '${CAPABILITIES_V36}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 35
AND migration_id = '0069-plugin-package-quarantine'
AND capabilities = '${CAPABILITIES_V35}'
`,
],
});
@@ -0,0 +1,97 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0073LocalProjectAdministrationMigration =
defineLocalSqliteMigration({
id: '0073-local-project-administration',
statements: [
`
CREATE TABLE "QingLong3ProjectAdministrationMutations" (
"mutation_id" TEXT PRIMARY KEY NOT NULL,
"operation" TEXT NOT NULL,
"authority_project_id" TEXT NOT NULL,
"project_id" TEXT NOT NULL,
"project_name" TEXT NOT NULL,
"project_slug" TEXT NOT NULL,
"project_status" TEXT NOT NULL,
"project_version" INTEGER NOT NULL,
"expected_previous_version" INTEGER NOT NULL,
"changed_by_type" TEXT NOT NULL,
"changed_by_id" TEXT NOT NULL,
"initial_owner_binding_version" INTEGER,
"audit_event_id" TEXT NOT NULL UNIQUE,
"project_created_at_ms" INTEGER NOT NULL,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("authority_project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_project_admin_mutation_id_check CHECK (
length("mutation_id") = 36
AND substr("mutation_id", 9, 1) = '-'
AND substr("mutation_id", 14, 1) = '-'
AND substr("mutation_id", 19, 1) = '-'
AND substr("mutation_id", 24, 1) = '-'
AND replace("mutation_id", '-', '') NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_project_admin_operation_check CHECK (
"operation" IN ('create','archive','restore')
),
CONSTRAINT ql3_project_admin_identity_check CHECK (
length("authority_project_id") BETWEEN 1 AND 128
AND length("project_id") BETWEEN 1 AND 128
AND length("project_name") BETWEEN 1 AND 255
AND length("project_slug") BETWEEN 1 AND 128
AND "project_slug" = lower("project_slug")
AND "project_slug" NOT GLOB '*[^a-z0-9-]*'
AND substr("project_slug", 1, 1) NOT GLOB '[^a-z0-9]'
AND substr("project_slug", -1, 1) NOT GLOB '[^a-z0-9]'
),
CONSTRAINT ql3_project_admin_transition_check CHECK (
"project_version" = "expected_previous_version" + 1
AND "project_version" BETWEEN 1 AND 2147483647
AND "expected_previous_version" BETWEEN 0 AND 2147483646
AND (
("operation" = 'create'
AND "expected_previous_version" = 0
AND "project_status" = 'active'
AND "initial_owner_binding_version" = 1)
OR ("operation" = 'archive'
AND "expected_previous_version" > 0
AND "project_status" = 'archived'
AND "initial_owner_binding_version" IS NULL)
OR ("operation" = 'restore'
AND "expected_previous_version" > 0
AND "project_status" = 'active'
AND "initial_owner_binding_version" IS NULL)
)
),
CONSTRAINT ql3_project_admin_actor_check CHECK (
"changed_by_type" = 'user'
AND length("changed_by_id") BETWEEN 1 AND 255
),
CONSTRAINT ql3_project_admin_audit_check CHECK (
"audit_event_id" = "mutation_id"
),
CONSTRAINT ql3_project_admin_time_check CHECK (
"project_created_at_ms" >= 0
AND "created_at_ms" >= "project_created_at_ms"
)
)
`,
`
CREATE UNIQUE INDEX "ql3_project_admin_project_version_uidx"
ON "QingLong3ProjectAdministrationMutations" (
"project_id", "project_version"
)
`,
`
CREATE INDEX "ql3_project_admin_authority_time_idx"
ON "QingLong3ProjectAdministrationMutations" (
"authority_project_id", "created_at_ms" DESC, "mutation_id" DESC
)
`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V36 =
'{"run_core":1,"run_retry_policy":1,"completion_receipt_journal":1,"local_dispatch_plan":1,"local_secret_envelope":1,"local_project_policy":1,"local_security_audit":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_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}';
const CAPABILITIES_V37 =
'{"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_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_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}';
export const local0074CapabilityV37Migration = defineLocalSqliteMigration({
id: '0074-capability-v37',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 37,
migration_id = '0073-local-project-administration',
capabilities = '${CAPABILITIES_V37}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 36
AND migration_id = '0071-local-identity-credential-administration'
AND capabilities = '${CAPABILITIES_V36}'
`,
],
});
@@ -0,0 +1,84 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0075SecurityAuditCompactionsMigration =
defineLocalSqliteMigration({
id: '0075-security-audit-compactions',
statements: [
`
CREATE TABLE "QingLong3SecurityAuditCompactions" (
"mutation_id" TEXT PRIMARY KEY NOT NULL,
"request_id" TEXT NOT NULL,
"authority_project_id" TEXT NOT NULL,
"retention_ms" INTEGER NOT NULL,
"eligible_before_ms" INTEGER NOT NULL,
"batch_limit" INTEGER NOT NULL,
"deleted_count" INTEGER NOT NULL,
"deleted_payload_bytes" INTEGER NOT NULL,
"first_occurred_at_ms" INTEGER,
"first_event_id" TEXT,
"last_occurred_at_ms" INTEGER,
"last_event_id" TEXT,
"records_digest" TEXT NOT NULL,
"audit_event_id" TEXT NOT NULL UNIQUE,
"created_at_ms" INTEGER NOT NULL,
FOREIGN KEY ("authority_project_id")
REFERENCES "QingLong3Projects" ("id") ON DELETE RESTRICT,
FOREIGN KEY ("audit_event_id")
REFERENCES "QingLong3SecurityAuditEvents" ("event_id")
ON DELETE RESTRICT,
CONSTRAINT ql3_audit_compaction_mutation_check CHECK (
length("mutation_id") = 36
AND substr("mutation_id", 9, 1) = '-'
AND substr("mutation_id", 14, 1) = '-'
AND substr("mutation_id", 19, 1) = '-'
AND substr("mutation_id", 24, 1) = '-'
AND replace("mutation_id", '-', '') NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_audit_compaction_request_check CHECK (
length("request_id") BETWEEN 1 AND 128
),
CONSTRAINT ql3_audit_compaction_authority_check CHECK (
length("authority_project_id") BETWEEN 1 AND 128
),
CONSTRAINT ql3_audit_compaction_policy_check CHECK (
"retention_ms" BETWEEN 2592000000 AND 315360000000
AND "eligible_before_ms" >= 0
AND "eligible_before_ms" + "retention_ms" <= "created_at_ms"
AND "batch_limit" BETWEEN 1 AND 512
),
CONSTRAINT ql3_audit_compaction_result_check CHECK (
"deleted_count" BETWEEN 0 AND "batch_limit"
AND "deleted_payload_bytes" BETWEEN 0 AND 16777216
AND length("records_digest") = 64
AND "records_digest" NOT GLOB '*[^0-9a-f]*'
AND (
("deleted_count" = 0
AND "deleted_payload_bytes" = 0
AND "first_occurred_at_ms" IS NULL
AND "first_event_id" IS NULL
AND "last_occurred_at_ms" IS NULL
AND "last_event_id" IS NULL)
OR ("deleted_count" > 0
AND "deleted_payload_bytes" > 0
AND "first_occurred_at_ms" >= 0
AND "last_occurred_at_ms" >= "first_occurred_at_ms"
AND length("first_event_id") = 36
AND length("last_event_id") = 36)
)
),
CONSTRAINT ql3_audit_compaction_audit_check CHECK (
"audit_event_id" = "mutation_id"
),
CONSTRAINT ql3_audit_compaction_time_check CHECK (
"created_at_ms" >= 2592000000
)
)
`,
`
CREATE INDEX "ql3_audit_compaction_authority_time_idx"
ON "QingLong3SecurityAuditCompactions" (
"authority_project_id", "created_at_ms" DESC, "mutation_id" DESC
)
`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V37 =
'{"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_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_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}';
const CAPABILITIES_V38 =
'{"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_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}';
export const local0076CapabilityV38Migration = defineLocalSqliteMigration({
id: '0076-capability-v38',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 38,
migration_id = '0075-security-audit-compactions',
capabilities = '${CAPABILITIES_V38}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 37
AND migration_id = '0073-local-project-administration'
AND capabilities = '${CAPABILITIES_V37}'
`,
],
});
@@ -0,0 +1,349 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0077PluginPackageLifecycleMigration =
defineLocalSqliteMigration({
id: '0077-plugin-package-lifecycle',
statements: [
`
CREATE UNIQUE INDEX ql3_approved_action_dispatch_lifecycle_uidx
ON "QingLong3ApprovedActionDispatches" (
dispatch_id, project_id, action_type, action_digest, preview_digest
)
`,
`
CREATE TABLE "QingLong3PluginPackageLifecycleEvents" (
event_digest TEXT PRIMARY KEY NOT NULL,
mutation_id TEXT NOT NULL,
dispatch_id TEXT NOT NULL,
approved_action_type TEXT NOT NULL,
action TEXT NOT NULL,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
install_version INTEGER NOT NULL,
install_record_digest TEXT NOT NULL,
expected_version INTEGER NOT NULL,
expected_disposition TEXT NOT NULL,
expected_event_digest TEXT,
generation_digest TEXT NOT NULL,
materialized_revision_digest TEXT NOT NULL,
current_tool_snapshot_digest TEXT NOT NULL,
reference_graph_digest TEXT NOT NULL,
impact_digest TEXT NOT NULL,
action_digest TEXT NOT NULL,
requested_by_type TEXT NOT NULL,
requested_by_id TEXT NOT NULL,
approved_by_type TEXT NOT NULL,
approved_by_id TEXT NOT NULL,
authorization_mode TEXT NOT NULL,
occurred_at_ms INTEGER NOT NULL,
event_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_lifecycle_install_fk
FOREIGN KEY (
project_id, package_name, installation_id, lock_digest,
install_record_digest
)
REFERENCES "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, lock_digest, record_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_dispatch_fk
FOREIGN KEY (
dispatch_id, project_id, approved_action_type, action_digest,
impact_digest
)
REFERENCES "QingLong3ApprovedActionDispatches" (
dispatch_id, project_id, action_type, action_digest, preview_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_previous_event_fk
FOREIGN KEY (expected_event_digest)
REFERENCES "QingLong3PluginPackageLifecycleEvents" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_identity_check CHECK (
length(mutation_id) BETWEEN 1 AND 128 AND
length(dispatch_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63 AND
length(installation_id) BETWEEN 1 AND 128 AND
install_version BETWEEN 1 AND 2147483647 AND
action IN ('disable','enable','uninstall') AND
approved_action_type = 'plugin_package.lifecycle.' || action
),
CONSTRAINT ql3_plugin_package_lifecycle_expectation_check CHECK (
(
action = 'disable' AND expected_disposition = 'active'
) OR (
action IN ('enable','uninstall') AND
expected_disposition = 'disabled'
)
),
CONSTRAINT ql3_plugin_package_lifecycle_origin_check CHECK (
(
expected_version = 0 AND
expected_disposition = 'active' AND
expected_event_digest IS NULL
) OR (
expected_version BETWEEN 1 AND 2147483646 AND
expected_event_digest IS NOT NULL
)
),
CONSTRAINT ql3_plugin_package_lifecycle_subject_check CHECK (
requested_by_type = 'user' AND approved_by_type = 'user' AND
length(requested_by_id) BETWEEN 1 AND 255 AND
length(approved_by_id) BETWEEN 1 AND 255 AND
authorization_mode IN ('human_confirmation','separation_of_duty') AND
(
(
authorization_mode = 'human_confirmation' AND
requested_by_id = approved_by_id
) OR (
authorization_mode = 'separation_of_duty' AND
requested_by_id <> approved_by_id
)
)
),
CONSTRAINT ql3_plugin_package_lifecycle_digest_check CHECK (
length(event_digest) = 64 AND
event_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(install_record_digest) = 64 AND
install_record_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(materialized_revision_digest) = 64 AND
materialized_revision_digest NOT GLOB '*[^0-9a-f]*' AND
length(current_tool_snapshot_digest) = 64 AND
current_tool_snapshot_digest NOT GLOB '*[^0-9a-f]*' AND
length(reference_graph_digest) = 64 AND
reference_graph_digest NOT GLOB '*[^0-9a-f]*' AND
length(impact_digest) = 64 AND
impact_digest NOT GLOB '*[^0-9a-f]*' AND
length(action_digest) = 64 AND
action_digest NOT GLOB '*[^0-9a-f]*' AND
(
expected_event_digest IS NULL OR
length(expected_event_digest) = 64 AND
expected_event_digest NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_plugin_package_lifecycle_json_check CHECK (
length(CAST(event_json AS BLOB)) BETWEEN 2 AND 524288 AND
json_valid(event_json) AND json_type(event_json) = 'object' AND
json_extract(event_json, '$.schema') =
'qinglong/plugin-package-lifecycle-event@v1' AND
json_extract(event_json, '$.mutationId') = mutation_id AND
json_extract(event_json, '$.dispatchId') = dispatch_id AND
json_extract(event_json, '$.impact.schema') =
'qinglong/plugin-package-lifecycle-impact@v1' AND
json_extract(event_json, '$.impact.action') = action AND
json_extract(event_json, '$.impact.target.projectId') = project_id AND
json_extract(event_json, '$.impact.target.packageName') = package_name AND
json_extract(event_json, '$.impact.target.installationId') =
installation_id AND
json_extract(event_json, '$.impact.target.lockDigest') = lock_digest AND
json_extract(event_json, '$.impact.target.installVersion') =
install_version AND
json_extract(event_json, '$.impact.target.installRecordDigest') =
install_record_digest AND
json_extract(event_json, '$.impact.expected.version') = expected_version AND
json_extract(event_json, '$.impact.expected.disposition') =
expected_disposition AND
(
(
expected_event_digest IS NULL AND
json_type(event_json, '$.impact.expected.eventDigest') = 'null'
) OR
json_extract(event_json, '$.impact.expected.eventDigest') =
expected_event_digest
) AND
json_extract(event_json, '$.impact.generationDigest') =
generation_digest AND
json_extract(event_json, '$.impact.materializedRevisionDigest') =
materialized_revision_digest AND
json_extract(event_json, '$.impact.currentToolSnapshotDigest') =
current_tool_snapshot_digest AND
json_extract(event_json, '$.impact.referenceGraphDigest') =
reference_graph_digest AND
json_extract(event_json, '$.impact.impactDigest') = impact_digest AND
json_extract(event_json, '$.actionDigest') = action_digest AND
json_extract(event_json, '$.requestedBy.type') = requested_by_type AND
json_extract(event_json, '$.requestedBy.id') = requested_by_id AND
json_extract(event_json, '$.approvedBy.type') = approved_by_type AND
json_extract(event_json, '$.approvedBy.id') = approved_by_id AND
json_extract(event_json, '$.authorizationMode') = authorization_mode AND
json_extract(event_json, '$.occurredAtMs') = occurred_at_ms AND
json_extract(event_json, '$.eventDigest') = event_digest
),
CONSTRAINT ql3_plugin_package_lifecycle_time_check CHECK (
occurred_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_mutation_uidx ON "QingLong3PluginPackageLifecycleEvents" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_dispatch_uidx ON "QingLong3PluginPackageLifecycleEvents" (dispatch_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_target_version_uidx ON "QingLong3PluginPackageLifecycleEvents" (project_id, package_name, installation_id, lock_digest, expected_version)`,
`CREATE INDEX ql3_plugin_package_lifecycle_project_idx ON "QingLong3PluginPackageLifecycleEvents" (project_id, package_name, occurred_at_ms, event_digest)`,
`
CREATE TABLE "QingLong3PluginPackageLifecycleHeads" (
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
install_record_digest TEXT NOT NULL,
version INTEGER NOT NULL,
disposition TEXT NOT NULL,
event_digest TEXT NOT NULL,
updated_at_ms INTEGER NOT NULL,
PRIMARY KEY (project_id, package_name),
CONSTRAINT ql3_plugin_package_lifecycle_head_install_fk
FOREIGN KEY (
project_id, package_name, installation_id, lock_digest,
install_record_digest
)
REFERENCES "QingLong3PluginPackageInstalls" (
project_id, package_name, installation_id, lock_digest, record_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_head_event_fk
FOREIGN KEY (event_digest)
REFERENCES "QingLong3PluginPackageLifecycleEvents" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_head_state_check CHECK (
version BETWEEN 1 AND 2147483647 AND
disposition IN ('active','disabled','uninstalled') AND
updated_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_lifecycle_head_digest_check CHECK (
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(install_record_digest) = 64 AND
install_record_digest NOT GLOB '*[^0-9a-f]*' AND
length(event_digest) = 64 AND
event_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_head_event_uidx ON "QingLong3PluginPackageLifecycleHeads" (event_digest)`,
`
CREATE TABLE "QingLong3PluginPackageLifecycleReceipts" (
event_digest TEXT PRIMARY KEY NOT NULL,
receipt_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
action TEXT NOT NULL,
capability_status TEXT NOT NULL,
task_count INTEGER NOT NULL,
previous_active_vector_digest TEXT NOT NULL,
current_active_vector_digest TEXT NOT NULL,
current_tool_snapshot_digest TEXT NOT NULL,
retained_source_count INTEGER NOT NULL,
committed_at_ms INTEGER NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_lifecycle_receipt_event_fk
FOREIGN KEY (event_digest)
REFERENCES "QingLong3PluginPackageLifecycleEvents" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_receipt_snapshot_fk
FOREIGN KEY (
project_id, current_active_vector_digest, current_tool_snapshot_digest
)
REFERENCES "QingLong3ProjectToolDefinitionSnapshots" (
project_id, active_vector_digest, snapshot_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_receipt_state_check CHECK (
(
action = 'disable' AND capability_status = 'withdrawn' AND
previous_active_vector_digest <> current_active_vector_digest
) OR (
action = 'enable' AND capability_status = 'restored' AND
previous_active_vector_digest <> current_active_vector_digest
) OR (
action = 'uninstall' AND capability_status = 'retired' AND
task_count = 0 AND
previous_active_vector_digest = current_active_vector_digest
)
),
CONSTRAINT ql3_plugin_package_lifecycle_receipt_bounds_check CHECK (
task_count BETWEEN 0 AND 128 AND
retained_source_count BETWEEN 0 AND 128 AND
committed_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_lifecycle_receipt_digest_check CHECK (
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*' AND
length(previous_active_vector_digest) = 64 AND
previous_active_vector_digest NOT GLOB '*[^0-9a-f]*' AND
length(current_active_vector_digest) = 64 AND
current_active_vector_digest NOT GLOB '*[^0-9a-f]*' AND
length(current_tool_snapshot_digest) = 64 AND
current_tool_snapshot_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_lifecycle_receipt_json_check CHECK (
length(CAST(receipt_json AS BLOB)) BETWEEN 2 AND 524288 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-lifecycle-receipt@v1' AND
json_extract(receipt_json, '$.eventDigest') = event_digest AND
json_extract(receipt_json, '$.action') = action AND
json_extract(receipt_json, '$.target.projectId') = project_id AND
json_extract(receipt_json, '$.capability.status') = capability_status AND
json_array_length(
json_extract(receipt_json, '$.capability.taskTransitions')
) = task_count AND
json_extract(
receipt_json, '$.capability.previousActiveVectorDigest'
) = previous_active_vector_digest AND
json_extract(
receipt_json, '$.capability.currentActiveVectorDigest'
) = current_active_vector_digest AND
json_extract(receipt_json, '$.capability.currentToolSnapshotDigest') =
current_tool_snapshot_digest AND
json_extract(receipt_json, '$.capability.retainedSourceCount') =
retained_source_count AND
json_extract(receipt_json, '$.committedAtMs') = committed_at_ms AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_receipt_uidx ON "QingLong3PluginPackageLifecycleReceipts" (receipt_digest)`,
`CREATE INDEX ql3_plugin_package_lifecycle_receipt_snapshot_idx ON "QingLong3PluginPackageLifecycleReceipts" (project_id, current_active_vector_digest, event_digest)`,
`
CREATE TABLE "QingLong3PluginPackageLifecycleTasks" (
event_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
task_id TEXT NOT NULL,
previous_revision INTEGER NOT NULL,
current_revision INTEGER NOT NULL,
previous_content_digest TEXT NOT NULL,
current_content_digest TEXT NOT NULL,
previous_enabled INTEGER NOT NULL,
current_enabled INTEGER NOT NULL,
PRIMARY KEY (event_digest, task_id),
CONSTRAINT ql3_plugin_package_lifecycle_task_receipt_fk
FOREIGN KEY (event_digest)
REFERENCES "QingLong3PluginPackageLifecycleReceipts" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_task_previous_fk
FOREIGN KEY (project_id, task_id, previous_revision)
REFERENCES "QingLong3TaskDefinitionRevisions" (
project_id, task_id, revision
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_task_current_fk
FOREIGN KEY (project_id, task_id, current_revision)
REFERENCES "QingLong3TaskDefinitionRevisions" (
project_id, task_id, revision
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_task_transition_check CHECK (
current_revision = previous_revision + 1 AND
previous_enabled IN (0, 1) AND current_enabled IN (0, 1) AND
previous_enabled <> current_enabled
),
CONSTRAINT ql3_plugin_package_lifecycle_task_digest_check CHECK (
length(previous_content_digest) = 64 AND
previous_content_digest NOT GLOB '*[^0-9a-f]*' AND
length(current_content_digest) = 64 AND
current_content_digest NOT GLOB '*[^0-9a-f]*'
)
)
`,
`CREATE INDEX ql3_plugin_package_lifecycle_task_idx ON "QingLong3PluginPackageLifecycleTasks" (project_id, task_id, event_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V38 =
'{"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_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}';
const CAPABILITIES_V39 =
'{"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_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}';
export const local0078CapabilityV39Migration = defineLocalSqliteMigration({
id: '0078-capability-v39',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 39,
migration_id = '0077-plugin-package-lifecycle',
capabilities = '${CAPABILITIES_V39}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 38
AND migration_id = '0075-security-audit-compactions'
AND capabilities = '${CAPABILITIES_V38}'
`,
],
});
@@ -0,0 +1,162 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0079PluginPackageAutomationPublicationsMigration =
defineLocalSqliteMigration({
id: '0079-plugin-package-automation-publications',
statements: [
`
CREATE TABLE "QingLong3PluginPackageAutomationPublications" (
publication_digest TEXT PRIMARY KEY NOT NULL,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
generation INTEGER NOT NULL,
generation_digest TEXT NOT NULL,
materialized_revision_digest TEXT NOT NULL,
state TEXT NOT NULL,
version INTEGER NOT NULL,
previous_publication_digest TEXT,
lifecycle_event_digest TEXT,
published_at_ms INTEGER NOT NULL,
publication_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_automation_publication_revision_fk
FOREIGN KEY (generation_digest)
REFERENCES "QingLong3PluginPackageMaterializedRevisions" (
generation_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_previous_fk
FOREIGN KEY (previous_publication_digest)
REFERENCES "QingLong3PluginPackageAutomationPublications" (
publication_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_lifecycle_fk
FOREIGN KEY (lifecycle_event_digest)
REFERENCES "QingLong3PluginPackageLifecycleEvents" (event_digest)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_identity_check CHECK (
length(project_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63 AND
length(installation_id) BETWEEN 1 AND 128 AND
generation BETWEEN 1 AND 2147483647 AND
state IN ('active','withdrawn','absent') AND
version BETWEEN 1 AND 2147483647 AND
published_at_ms >= 0 AND
(
version = 1 AND state IN ('active','absent') AND
previous_publication_digest IS NULL AND
lifecycle_event_digest IS NULL
OR
version > 1 AND previous_publication_digest IS NOT NULL
) AND
(state <> 'withdrawn' OR lifecycle_event_digest IS NOT NULL)
),
CONSTRAINT ql3_plugin_package_automation_publication_digest_check CHECK (
length(publication_digest) = 64 AND
publication_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(materialized_revision_digest) = 64 AND
materialized_revision_digest NOT GLOB '*[^0-9a-f]*' AND
(
previous_publication_digest IS NULL OR
length(previous_publication_digest) = 64 AND
previous_publication_digest NOT GLOB '*[^0-9a-f]*'
) AND
(
lifecycle_event_digest IS NULL OR
length(lifecycle_event_digest) = 64 AND
lifecycle_event_digest NOT GLOB '*[^0-9a-f]*'
)
),
CONSTRAINT ql3_plugin_package_automation_publication_json_check CHECK (
length(CAST(publication_json AS BLOB)) BETWEEN 2 AND 12582912 AND
json_valid(publication_json) AND
json_type(publication_json) = 'object' AND
json_extract(publication_json, '$.schema') =
'qinglong/plugin-package-automation-publication@v1' AND
json_extract(publication_json, '$.target.projectId') = project_id AND
json_extract(publication_json, '$.target.packageName') = package_name AND
json_extract(publication_json, '$.target.installationId') =
installation_id AND
json_extract(publication_json, '$.target.lockDigest') = lock_digest AND
json_extract(publication_json, '$.target.generation') = generation AND
json_extract(publication_json, '$.target.generationDigest') =
generation_digest AND
json_extract(publication_json, '$.target.materializedRevisionDigest') =
materialized_revision_digest AND
json_extract(publication_json, '$.state') = state AND
json_extract(publication_json, '$.version') = version AND
(
previous_publication_digest IS NULL AND
json_type(publication_json, '$.previousPublicationDigest') = 'null'
OR
json_extract(publication_json, '$.previousPublicationDigest') =
previous_publication_digest
) AND
(
lifecycle_event_digest IS NULL AND
json_type(publication_json, '$.lifecycleEventDigest') = 'null'
OR
json_extract(publication_json, '$.lifecycleEventDigest') =
lifecycle_event_digest
) AND
json_extract(publication_json, '$.publishedAtMs') = published_at_ms AND
json_extract(publication_json, '$.publicationDigest') =
publication_digest AND
json_type(publication_json, '$.definitions.workflows') = 'array' AND
json_type(publication_json, '$.definitions.prompts') = 'array' AND
(
state = 'absent' AND
json_array_length(
json_extract(publication_json, '$.definitions.workflows')
) + json_array_length(
json_extract(publication_json, '$.definitions.prompts')
) = 0
OR
state <> 'absent' AND
json_array_length(
json_extract(publication_json, '$.definitions.workflows')
) + json_array_length(
json_extract(publication_json, '$.definitions.prompts')
) > 0
)
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_version_uidx ON "QingLong3PluginPackageAutomationPublications" (project_id, package_name, version)`,
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_previous_uidx ON "QingLong3PluginPackageAutomationPublications" (previous_publication_digest) WHERE previous_publication_digest IS NOT NULL`,
`CREATE INDEX ql3_plugin_package_automation_publication_generation_idx ON "QingLong3PluginPackageAutomationPublications" (generation_digest, publication_digest)`,
`
CREATE TABLE "QingLong3PluginPackageAutomationPublicationHeads" (
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
publication_digest TEXT NOT NULL,
generation_digest TEXT NOT NULL,
state TEXT NOT NULL,
version INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL,
PRIMARY KEY (project_id, package_name),
CONSTRAINT ql3_plugin_package_automation_publication_head_publication_fk
FOREIGN KEY (publication_digest)
REFERENCES "QingLong3PluginPackageAutomationPublications" (
publication_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_head_state_check CHECK (
length(project_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63 AND
length(publication_digest) = 64 AND
publication_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
state IN ('active','withdrawn','absent') AND
version BETWEEN 1 AND 2147483647 AND
updated_at_ms >= 0
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_head_digest_uidx ON "QingLong3PluginPackageAutomationPublicationHeads" (publication_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V39 =
'{"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_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}';
const CAPABILITIES_V40 =
'{"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_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}';
export const local0080CapabilityV40Migration = defineLocalSqliteMigration({
id: '0080-capability-v40',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 40,
migration_id = '0079-plugin-package-automation-publications',
capabilities = '${CAPABILITIES_V40}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 39
AND migration_id = '0077-plugin-package-lifecycle'
AND capabilities = '${CAPABILITIES_V39}'
`,
],
});
@@ -0,0 +1,174 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0081PluginPackageWorkflowAdmissionsMigration =
defineLocalSqliteMigration({
id: '0081-plugin-package-workflow-admissions',
statements: [
`
CREATE TABLE "QingLong3PluginPackageWorkflowAdmissions" (
plan_digest TEXT PRIMARY KEY NOT NULL,
plan_id TEXT NOT NULL,
run_id TEXT NOT NULL,
project_id TEXT NOT NULL,
package_name TEXT NOT NULL,
installation_id TEXT NOT NULL,
lock_digest TEXT NOT NULL,
generation INTEGER NOT NULL,
generation_digest TEXT NOT NULL,
materialized_revision_digest TEXT NOT NULL,
publication_digest TEXT NOT NULL,
workflow_id TEXT NOT NULL,
workflow_definition_digest TEXT NOT NULL,
step_count INTEGER NOT NULL,
admitted_at_ms INTEGER NOT NULL,
final_run_version INTEGER NOT NULL,
final_run_event_sequence INTEGER NOT NULL,
receipt_digest TEXT NOT NULL,
plan_json TEXT NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_workflow_admission_run_fk
FOREIGN KEY (run_id) REFERENCES "Runs" (id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_publication_fk
FOREIGN KEY (publication_digest)
REFERENCES "QingLong3PluginPackageAutomationPublications" (
publication_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_identity_check CHECK (
length(plan_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(package_name) BETWEEN 1 AND 63 AND
length(installation_id) BETWEEN 1 AND 128 AND
length(workflow_id) BETWEEN 1 AND 63 AND
generation BETWEEN 1 AND 2147483647 AND
step_count BETWEEN 1 AND 128 AND
admitted_at_ms >= 0 AND
final_run_version = step_count + 1 AND
final_run_event_sequence = step_count + 1
),
CONSTRAINT ql3_plugin_package_workflow_admission_digest_check CHECK (
length(plan_digest) = 64 AND
plan_digest NOT GLOB '*[^0-9a-f]*' AND
length(lock_digest) = 64 AND
lock_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(materialized_revision_digest) = 64 AND
materialized_revision_digest NOT GLOB '*[^0-9a-f]*' AND
length(publication_digest) = 64 AND
publication_digest NOT GLOB '*[^0-9a-f]*' AND
length(workflow_definition_digest) = 64 AND
workflow_definition_digest NOT GLOB '*[^0-9a-f]*' AND
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_workflow_admission_plan_json_check CHECK (
length(CAST(plan_json AS BLOB)) BETWEEN 2 AND 262144 AND
json_valid(plan_json) AND json_type(plan_json) = 'object' AND
json_extract(plan_json, '$.schema') =
'qinglong/plugin-package-workflow-execution-plan@v1' AND
json_extract(plan_json, '$.planId') = plan_id AND
json_extract(plan_json, '$.planDigest') = plan_digest AND
json_extract(plan_json, '$.runId') = run_id AND
json_extract(plan_json, '$.target.projectId') = project_id AND
json_extract(plan_json, '$.target.packageName') = package_name AND
json_extract(plan_json, '$.target.installationId') = installation_id AND
json_extract(plan_json, '$.target.lockDigest') = lock_digest AND
json_extract(plan_json, '$.target.generation') = generation AND
json_extract(plan_json, '$.target.generationDigest') =
generation_digest AND
json_extract(plan_json, '$.target.materializedRevisionDigest') =
materialized_revision_digest AND
json_extract(plan_json, '$.target.publicationDigest') =
publication_digest AND
json_extract(plan_json, '$.target.workflowId') = workflow_id AND
json_extract(plan_json, '$.target.workflowDefinitionDigest') =
workflow_definition_digest AND
json_extract(plan_json, '$.plannedAtMs') = admitted_at_ms AND
json_array_length(json_extract(plan_json, '$.steps')) = step_count
),
CONSTRAINT ql3_plugin_package_workflow_admission_receipt_json_check CHECK (
length(CAST(receipt_json AS BLOB)) BETWEEN 2 AND 262144 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-workflow-admission-receipt@v1' AND
json_extract(receipt_json, '$.planId') = plan_id AND
json_extract(receipt_json, '$.planDigest') = plan_digest AND
json_extract(receipt_json, '$.runId') = run_id AND
json_extract(receipt_json, '$.publicationDigest') =
publication_digest AND
json_extract(receipt_json, '$.workflowId') = workflow_id AND
json_extract(receipt_json, '$.admittedAtMs') = admitted_at_ms AND
json_extract(receipt_json, '$.finalRunVersion') =
final_run_version AND
json_extract(receipt_json, '$.finalRunEventSequence') =
final_run_event_sequence AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest AND
json_array_length(json_extract(receipt_json, '$.steps')) = step_count
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_plan_uidx ON "QingLong3PluginPackageWorkflowAdmissions" (plan_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_run_uidx ON "QingLong3PluginPackageWorkflowAdmissions" (run_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_receipt_uidx ON "QingLong3PluginPackageWorkflowAdmissions" (receipt_digest)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_plan_run_uidx ON "QingLong3PluginPackageWorkflowAdmissions" (plan_digest, run_id)`,
`CREATE INDEX ql3_plugin_package_workflow_admission_target_idx ON "QingLong3PluginPackageWorkflowAdmissions" (project_id, package_name, admitted_at_ms, plan_digest)`,
`
CREATE TABLE "QingLong3PluginPackageWorkflowAdmissionSteps" (
plan_digest TEXT NOT NULL,
run_id TEXT NOT NULL,
step_key TEXT NOT NULL,
step_run_id TEXT NOT NULL,
task_id TEXT NOT NULL,
task_definition_ref TEXT NOT NULL,
task_definition_digest TEXT NOT NULL,
needs_json TEXT NOT NULL,
initial_status TEXT NOT NULL,
mutation_id TEXT NOT NULL,
event_id TEXT NOT NULL,
PRIMARY KEY (plan_digest, step_key),
CONSTRAINT ql3_plugin_package_workflow_admission_step_admission_fk
FOREIGN KEY (plan_digest, run_id)
REFERENCES "QingLong3PluginPackageWorkflowAdmissions" (
plan_digest, run_id
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_run_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_mutation_fk
FOREIGN KEY (mutation_id) REFERENCES "StepRunMutations" (mutation_id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_event_fk
FOREIGN KEY (event_id) REFERENCES "RunEvents" (id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_identity_check CHECK (
length(run_id) BETWEEN 1 AND 128 AND
length(step_key) BETWEEN 1 AND 63 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(task_id) BETWEEN 1 AND 63 AND
length(CAST(task_definition_ref AS BLOB)) BETWEEN 1 AND 512 AND
length(mutation_id) BETWEEN 1 AND 128 AND
length(event_id) BETWEEN 1 AND 128 AND
initial_status IN ('pending','ready')
),
CONSTRAINT ql3_plugin_package_workflow_admission_step_digest_check CHECK (
length(plan_digest) = 64 AND
plan_digest NOT GLOB '*[^0-9a-f]*' AND
length(task_definition_digest) = 64 AND
task_definition_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_workflow_admission_step_needs_check CHECK (
length(CAST(needs_json AS BLOB)) BETWEEN 2 AND 8192 AND
json_valid(needs_json) AND json_type(needs_json) = 'array' AND
json_array_length(needs_json) BETWEEN 0 AND 127
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_step_run_uidx ON "QingLong3PluginPackageWorkflowAdmissionSteps" (step_run_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_step_mutation_uidx ON "QingLong3PluginPackageWorkflowAdmissionSteps" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_step_event_uidx ON "QingLong3PluginPackageWorkflowAdmissionSteps" (event_id)`,
`CREATE INDEX ql3_plugin_package_workflow_admission_step_task_idx ON "QingLong3PluginPackageWorkflowAdmissionSteps" (task_id, task_definition_digest, plan_digest)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V40 =
'{"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_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}';
const CAPABILITIES_V41 =
'{"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_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_workflow_admission":1}';
export const local0082CapabilityV41Migration = defineLocalSqliteMigration({
id: '0082-capability-v41',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 41,
migration_id = '0081-plugin-package-workflow-admissions',
capabilities = '${CAPABILITIES_V41}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 40
AND migration_id = '0079-plugin-package-automation-publications'
AND capabilities = '${CAPABILITIES_V40}'
`,
],
});
@@ -0,0 +1,133 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0083PluginPackageWorkflowTaskAttemptAdmissionsMigration =
defineLocalSqliteMigration({
id: '0083-plugin-package-workflow-task-attempt-admissions',
statements: [
`CREATE UNIQUE INDEX ql3_plugin_package_task_reconciliation_receipt_uidx ON "QingLong3PluginPackageTaskReconciliations" (generation_digest, receipt_digest)`,
`
CREATE TABLE "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (
receipt_digest TEXT PRIMARY KEY NOT NULL,
attempt_id TEXT NOT NULL,
plan_digest TEXT NOT NULL,
run_id TEXT NOT NULL,
step_run_id TEXT NOT NULL,
step_run_version INTEGER NOT NULL,
step_run_digest TEXT NOT NULL,
generation_digest TEXT NOT NULL,
resource_task_id TEXT NOT NULL,
task_reconciliation_receipt_digest TEXT NOT NULL,
project_id TEXT NOT NULL,
task_id TEXT NOT NULL,
task_revision TEXT NOT NULL,
task_definition_digest TEXT NOT NULL,
executor_type TEXT NOT NULL,
execution_digest TEXT NOT NULL,
attempt_number INTEGER NOT NULL,
event_id TEXT NOT NULL,
run_version INTEGER NOT NULL,
run_event_sequence INTEGER NOT NULL,
admitted_at_ms INTEGER NOT NULL,
receipt_json TEXT NOT NULL,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_plan_fk
FOREIGN KEY (plan_digest, run_id)
REFERENCES "QingLong3PluginPackageWorkflowAdmissions" (
plan_digest, run_id
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "StepRuns" (run_id, id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_attempt_fk
FOREIGN KEY (attempt_id) REFERENCES "RunAttempts" (id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_event_fk
FOREIGN KEY (event_id) REFERENCES "RunEvents" (id)
ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_reconciliation_fk
FOREIGN KEY (
generation_digest, task_reconciliation_receipt_digest
) REFERENCES "QingLong3PluginPackageTaskReconciliations" (
generation_digest, receipt_digest
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_execution_fk
FOREIGN KEY (project_id, task_id, task_revision)
REFERENCES "QingLong3LocalTaskExecutionRevisions" (
project_id, task_id, task_revision
) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_identity_check
CHECK (
length(attempt_id) BETWEEN 1 AND 128 AND
length(run_id) BETWEEN 1 AND 128 AND
length(step_run_id) BETWEEN 1 AND 128 AND
length(resource_task_id) BETWEEN 1 AND 128 AND
length(project_id) BETWEEN 1 AND 128 AND
length(task_id) BETWEEN 1 AND 128 AND
length(task_revision) BETWEEN 1 AND 128 AND
length(event_id) BETWEEN 1 AND 128 AND
executor_type = 'local_process'
),
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_counter_check
CHECK (
step_run_version BETWEEN 1 AND 2147483647 AND
attempt_number BETWEEN 1 AND 8192 AND
run_version BETWEEN 1 AND 2147483647 AND
run_event_sequence = run_version AND
admitted_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_digest_check
CHECK (
length(receipt_digest) = 64 AND
receipt_digest NOT GLOB '*[^0-9a-f]*' AND
length(plan_digest) = 64 AND
plan_digest NOT GLOB '*[^0-9a-f]*' AND
length(step_run_digest) = 64 AND
step_run_digest NOT GLOB '*[^0-9a-f]*' AND
length(generation_digest) = 64 AND
generation_digest NOT GLOB '*[^0-9a-f]*' AND
length(task_reconciliation_receipt_digest) = 64 AND
task_reconciliation_receipt_digest NOT GLOB '*[^0-9a-f]*' AND
length(task_definition_digest) = 64 AND
task_definition_digest NOT GLOB '*[^0-9a-f]*' AND
length(execution_digest) = 64 AND
execution_digest NOT GLOB '*[^0-9a-f]*'
),
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_json_check
CHECK (
length(CAST(receipt_json AS BLOB)) BETWEEN 2 AND 16384 AND
json_valid(receipt_json) AND json_type(receipt_json) = 'object' AND
json_extract(receipt_json, '$.schema') =
'qinglong/plugin-package-workflow-task-attempt-admission@v1' AND
json_extract(receipt_json, '$.receiptDigest') = receipt_digest AND
json_extract(receipt_json, '$.attemptId') = attempt_id AND
json_extract(receipt_json, '$.planDigest') = plan_digest AND
json_extract(receipt_json, '$.runId') = run_id AND
json_extract(receipt_json, '$.stepRunId') = step_run_id AND
json_extract(receipt_json, '$.stepRunVersion') = step_run_version AND
json_extract(receipt_json, '$.stepRunDigest') = step_run_digest AND
json_extract(receipt_json, '$.resourceTaskId') = resource_task_id AND
json_extract(
receipt_json, '$.taskReconciliationReceiptDigest'
) = task_reconciliation_receipt_digest AND
json_extract(receipt_json, '$.taskId') = task_id AND
json_extract(receipt_json, '$.taskRevision') = task_revision AND
json_extract(receipt_json, '$.taskDefinitionDigest') =
task_definition_digest AND
json_extract(receipt_json, '$.executorType') = executor_type AND
json_extract(receipt_json, '$.executionDigest') = execution_digest AND
json_extract(receipt_json, '$.attemptNumber') = attempt_number AND
json_extract(receipt_json, '$.eventId') = event_id AND
json_extract(receipt_json, '$.runVersion') = run_version AND
json_extract(receipt_json, '$.runEventSequence') =
run_event_sequence AND
json_extract(receipt_json, '$.admittedAtMs') = admitted_at_ms
)
)
`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_task_attempt_admission_attempt_uidx ON "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (attempt_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_task_attempt_admission_event_uidx ON "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (event_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_task_attempt_admission_epoch_uidx ON "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (run_id, step_run_id, step_run_version)`,
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_task_attempt_admission_number_uidx ON "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (run_id, attempt_number)`,
`CREATE INDEX ql3_plugin_package_workflow_task_attempt_admission_candidate_idx ON "QingLong3PluginPackageWorkflowTaskAttemptAdmissions" (run_id, step_run_id, admitted_at_ms)`,
],
});
@@ -0,0 +1,23 @@
import { defineLocalSqliteMigration } from './sqlMigration';
const CAPABILITIES_V41 =
'{"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_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_workflow_admission":1}';
export const CAPABILITIES_V42 =
'{"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_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_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1}';
export const local0084CapabilityV42Migration = defineLocalSqliteMigration({
id: '0084-capability-v42',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 42,
migration_id = '0083-plugin-package-workflow-task-attempt-admissions',
capabilities = '${CAPABILITIES_V42}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 41
AND migration_id = '0081-plugin-package-workflow-admissions'
AND capabilities = '${CAPABILITIES_V41}'
`,
],
});
@@ -0,0 +1,9 @@
import { defineLocalSqliteMigration } from './sqlMigration';
export const local0085PluginPackageWorkflowRunListIndexMigration =
defineLocalSqliteMigration({
id: '0085-plugin-package-workflow-run-list-index',
statements: [
`CREATE INDEX ql3_plugin_package_workflow_admission_workflow_history_idx ON "QingLong3PluginPackageWorkflowAdmissions" (project_id, package_name, workflow_id, admitted_at_ms, run_id)`,
],
});
@@ -0,0 +1,24 @@
import { CAPABILITIES_V42 } from './0084-capability-v42';
import { defineLocalSqliteMigration } from './sqlMigration';
export const CAPABILITIES_V43 = CAPABILITIES_V42.replace(
'"plugin_package_workflow_admission":1,',
'"plugin_package_workflow_admission":1,"plugin_package_workflow_run_list":1,',
);
export const local0086CapabilityV43Migration = defineLocalSqliteMigration({
id: '0086-capability-v43',
statements: [
`
UPDATE "QingLong3SchemaCapabilities"
SET contract_version = 43,
migration_id = '0085-plugin-package-workflow-run-list-index',
capabilities = '${CAPABILITIES_V43}',
updated_at_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER)
WHERE contract_name = 'local-control-core'
AND contract_version = 42
AND migration_id = '0083-plugin-package-workflow-task-attempt-admissions'
AND capabilities = '${CAPABILITIES_V42}'
`,
],
});
@@ -0,0 +1,75 @@
import { createHash } from 'node:crypto';
import type { MigrationStreamStep } from '@qinglong/runtime-core/migration-stream';
import type { DatabaseSync } from 'node:sqlite';
export interface LocalSqliteMigrationContext {
readonly client: DatabaseSync;
}
export function defineLocalSqliteMigration(options: {
readonly id: string;
readonly statements: readonly string[];
}): MigrationStreamStep<LocalSqliteMigrationContext> {
const statements = Object.freeze(
options.statements.map((statement) => statement.trim()),
);
if (
statements.length === 0 ||
statements.length > 64 ||
statements.some(
(statement) => statement.length === 0 || statement.length > 64 * 1024,
)
) {
throw new TypeError('Local SQLite migration statements are invalid');
}
const checksum = createHash('sha256')
.update(statements.join('\n-- ql3-statement-boundary --\n'))
.digest('hex');
return Object.freeze({
id: options.id,
checksum,
async up(context: LocalSqliteMigrationContext) {
for (const statement of statements) context.client.exec(statement);
},
});
}
/**
* Defines a reviewed migration whose bounded row transformation cannot be
* expressed by SQLite alone. `program` is the immutable audit description
* covered by the migration checksum and must change with transformation
* semantics as well as with schema SQL.
*/
export function defineLocalSqliteProgrammaticMigration(options: {
readonly id: string;
readonly program: readonly string[];
readonly up: (
context: LocalSqliteMigrationContext,
) => void | Promise<void>;
}): MigrationStreamStep<LocalSqliteMigrationContext> {
const program = Object.freeze(
options.program.map((instruction) => instruction.trim()),
);
if (
program.length === 0 ||
program.length > 64 ||
program.some(
(instruction) =>
instruction.length === 0 || instruction.length > 64 * 1024,
) ||
typeof options.up !== 'function'
) {
throw new TypeError('Local SQLite migration program is invalid');
}
const checksum = createHash('sha256')
.update('ql3-local-sqlite-programmatic-migration-v1\0', 'utf8')
.update(program.join('\n-- ql3-program-boundary --\n'), 'utf8')
.digest('hex');
return Object.freeze({
id: options.id,
checksum,
async up(context: LocalSqliteMigrationContext) {
await options.up(context);
},
});
}