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,123 @@
import {
POSTGRESQL_MAIN_MIGRATION_STREAM_ID,
type PostgresMigrationContext,
} from './postgresMigrationStreamStore';
import type { MigrationStreamDefinition } from '@qinglong/runtime-core';
import { pg0001SchemaCapabilityMigration } from './pg-0001-schema-capability';
import { pg0002RunCoreMigration } from './pg-0002-run-core';
import { pg0003RunRetryPolicyMigration } from './pg-0003-run-retry-policy';
import { pg0004ProjectPolicyMigration } from './pg-0004-project-policy';
import { pg0005ApiCredentialSecurityAuditMigration } from './pg-0005-api-credential-security-audit';
import { pg0006IdentityCredentialAdministrationMigration } from './pg-0006-identity-credential-administration';
import { pg0007ClusterRecoveryIndexesMigration } from './pg-0007-cluster-recovery-indexes';
import { pg0008RunRecoveryClaimsMigration } from './pg-0008-run-recovery-claims';
import { pg0009WorkerSessionRunLeaseMigration } from './pg-0009-worker-session-run-lease';
import { pg0010WorkerIngressAttestationMigration } from './pg-0010-worker-ingress-attestation';
import { pg0011ApiCredentialPepperBindingMigration } from './pg-0011-api-credential-pepper-binding';
import { pg0012TaskTriggerDefinitionsMigration } from './pg-0012-task-trigger-definitions';
import { pg0013TaskExecutionRevisionsMigration } from './pg-0013-task-execution-revisions';
import { pg0014ClusterSchedulerAdmissionMigration } from './pg-0014-cluster-scheduler-admission';
import { pg0015WorkerCredentialDeliveryLedgerMigration } from './pg-0015-worker-credential-delivery-ledger';
import { pg0016WorkerCredentialStageDiscardLedgerMigration } from './pg-0016-worker-credential-stage-discard-ledger';
import { pg0017DatabaseRoleGrantsMigration } from './pg-0017-database-role-grants';
import { pg0018PluginPackageInstallsMigration } from './pg-0018-plugin-package-installs';
import { pg0019ApprovedActionsMigration } from './pg-0019-approved-actions';
import { pg0020PluginPackageAdmissionReceiptsMigration } from './pg-0020-plugin-package-admission-receipts';
import { pg0021ApprovedActionExecutionsAndPackageProposalsMigration } from './pg-0021-approved-action-executions-and-package-proposals';
import { pg0022PluginPackageAuthoritySplitMigration } from './pg-0022-plugin-package-authority-split';
import { pg0023PluginPackageManagementQuotaMigration } from './pg-0023-plugin-package-management-quota';
import { pg0024PluginPackageIdentityKeysetLedgerMigration } from './pg-0024-plugin-package-identity-keyset-ledger';
import { pg0025PluginPackageMaterializedRevisionsMigration } from './pg-0025-plugin-package-materialized-revisions';
import { pg0026PluginPackageTaskReconciliationsMigration } from './pg-0026-plugin-package-task-reconciliations';
import { pg0027ProjectToolDefinitionSnapshotsMigration } from './pg-0027-project-tool-definition-snapshots';
import { pg0028StepRunsMigration } from './pg-0028-step-runs';
import { pg0029ToolExecutionEvidenceMigration } from './pg-0029-tool-execution-evidence';
import { pg0030ToolExecutionStartBarriersMigration } from './pg-0030-tool-execution-start-barriers';
import { pg0031ToolInvocationArtifactsMigration } from './pg-0031-tool-invocation-artifacts';
import { pg0032ToolExecutionArtifactBindingsMigration } from './pg-0032-tool-execution-artifact-bindings';
import { pg0033ToolExecutionCompletionsMigration } from './pg-0033-tool-execution-completions';
import { pg0034ToolExecutionFailureCompletionsMigration } from './pg-0034-tool-execution-failure-completions';
import { pg0035ToolResultKeyCatalogMigration } from './pg-0035-tool-result-key-catalog';
import { pg0036ToolResultRekeyOverlaysMigration } from './pg-0036-tool-result-rekey-overlays';
import { pg0037PluginPackageQuarantineMigration } from './pg-0037-plugin-package-quarantine';
import { pg0038PluginPackagePublisherProvenanceMigration } from './pg-0038-plugin-package-publisher-provenance';
import { pg0039PluginPackagePublisherTrustAuthorityMigration } from './pg-0039-plugin-package-publisher-trust-authority';
import { pg0040PluginPackagePublisherTrustTransitionsMigration } from './pg-0040-plugin-package-publisher-trust-transitions';
import { pg0041PluginPackageLifecycleMigration } from './pg-0041-plugin-package-lifecycle';
import { pg0042PluginPackageLifecyclePlansMigration } from './pg-0042-plugin-package-lifecycle-plans';
import { pg0043PluginPackageAutomationPublicationsMigration } from './pg-0043-plugin-package-automation-publications';
import { pg0044PluginPackageAutomationStartGuardMigration } from './pg-0044-plugin-package-automation-start-guard';
import { pg0045PluginPackageWorkflowAdmissionsMigration } from './pg-0045-plugin-package-workflow-admissions';
import { pg0046PluginPackageWorkflowTaskAttemptAdmissionsMigration } from './pg-0046-plugin-package-workflow-task-attempt-admissions';
import { pg0047WorkerCredentialManagementPlansMigration } from './pg-0047-worker-credential-management-plans';
import { pg0048WorkerCredentialPreapprovedActivationMigration } from './pg-0048-worker-credential-preapproved-activation';
import { pg0049WorkerCredentialExecutionReceiptsMigration } from './pg-0049-worker-credential-execution-receipts';
import { pg0050WorkerCredentialManagementBoundaryMigration } from './pg-0050-worker-credential-management-boundary';
import { pg0051AutomationManagementBoundaryMigration } from './pg-0051-automation-management-boundary';
import { pg0052AutomationManagementIdentityKeysetLedgerMigration } from './pg-0052-automation-management-identity-keyset-ledger';
import { pg0053PluginPackageWorkflowRunListIndexMigration } from './pg-0053-plugin-package-workflow-run-list-index';
import { pg0054ApprovalManagementBoundaryMigration } from './pg-0054-approval-management-boundary';
export const postgresqlMainMigrationStream: MigrationStreamDefinition<PostgresMigrationContext> =
Object.freeze({
id: POSTGRESQL_MAIN_MIGRATION_STREAM_ID,
dialect: 'postgresql',
migrationIdScheme: 'postgres-prefixed',
checksumScheme: 'sha256',
migrations: Object.freeze([
pg0001SchemaCapabilityMigration,
pg0002RunCoreMigration,
pg0003RunRetryPolicyMigration,
pg0004ProjectPolicyMigration,
pg0005ApiCredentialSecurityAuditMigration,
pg0006IdentityCredentialAdministrationMigration,
pg0007ClusterRecoveryIndexesMigration,
pg0008RunRecoveryClaimsMigration,
pg0009WorkerSessionRunLeaseMigration,
pg0010WorkerIngressAttestationMigration,
pg0011ApiCredentialPepperBindingMigration,
pg0012TaskTriggerDefinitionsMigration,
pg0013TaskExecutionRevisionsMigration,
pg0014ClusterSchedulerAdmissionMigration,
pg0015WorkerCredentialDeliveryLedgerMigration,
pg0016WorkerCredentialStageDiscardLedgerMigration,
pg0017DatabaseRoleGrantsMigration,
pg0018PluginPackageInstallsMigration,
pg0019ApprovedActionsMigration,
pg0020PluginPackageAdmissionReceiptsMigration,
pg0021ApprovedActionExecutionsAndPackageProposalsMigration,
pg0022PluginPackageAuthoritySplitMigration,
pg0023PluginPackageManagementQuotaMigration,
pg0024PluginPackageIdentityKeysetLedgerMigration,
pg0025PluginPackageMaterializedRevisionsMigration,
pg0026PluginPackageTaskReconciliationsMigration,
pg0027ProjectToolDefinitionSnapshotsMigration,
pg0028StepRunsMigration,
pg0029ToolExecutionEvidenceMigration,
pg0030ToolExecutionStartBarriersMigration,
pg0031ToolInvocationArtifactsMigration,
pg0032ToolExecutionArtifactBindingsMigration,
pg0033ToolExecutionCompletionsMigration,
pg0034ToolExecutionFailureCompletionsMigration,
pg0035ToolResultKeyCatalogMigration,
pg0036ToolResultRekeyOverlaysMigration,
pg0037PluginPackageQuarantineMigration,
pg0038PluginPackagePublisherProvenanceMigration,
pg0039PluginPackagePublisherTrustAuthorityMigration,
pg0040PluginPackagePublisherTrustTransitionsMigration,
pg0041PluginPackageLifecycleMigration,
pg0042PluginPackageLifecyclePlansMigration,
pg0043PluginPackageAutomationPublicationsMigration,
pg0044PluginPackageAutomationStartGuardMigration,
pg0045PluginPackageWorkflowAdmissionsMigration,
pg0046PluginPackageWorkflowTaskAttemptAdmissionsMigration,
pg0047WorkerCredentialManagementPlansMigration,
pg0048WorkerCredentialPreapprovedActivationMigration,
pg0049WorkerCredentialExecutionReceiptsMigration,
pg0050WorkerCredentialManagementBoundaryMigration,
pg0051AutomationManagementBoundaryMigration,
pg0052AutomationManagementIdentityKeysetLedgerMigration,
pg0053PluginPackageWorkflowRunListIndexMigration,
pg0054ApprovalManagementBoundaryMigration,
]),
});
@@ -0,0 +1,28 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_SCHEMA_CAPABILITY_TABLE = 'schema_capabilities';
export const pg0001SchemaCapabilityMigration = definePostgresSqlMigration({
id: 'pg-0001-schema-capability',
statements: [
`
CREATE TABLE "ql3"."${POSTGRESQL_SCHEMA_CAPABILITY_TABLE}" (
contract_name varchar(64) PRIMARY KEY,
contract_version integer NOT NULL
CONSTRAINT ql3_schema_capabilities_version_check
CHECK (contract_version >= 0),
migration_id varchar(128) NOT NULL,
capabilities jsonb NOT NULL
CONSTRAINT ql3_schema_capabilities_payload_check
CHECK (jsonb_typeof(capabilities) = 'object'),
updated_at_ms bigint NOT NULL
CONSTRAINT ql3_schema_capabilities_updated_at_check
CHECK (updated_at_ms >= 0),
CONSTRAINT ql3_schema_capabilities_migration_fk
FOREIGN KEY (migration_id)
REFERENCES "ql3"."schema_migrations" (migration_id)
DEFERRABLE INITIALLY DEFERRED
)
`.trim(),
],
});
@@ -0,0 +1,224 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_RUN_TABLE = 'runs';
export const POSTGRESQL_RUN_ATTEMPT_TABLE = 'run_attempts';
export const POSTGRESQL_RUN_EVENT_TABLE = 'run_events';
export const pg0002RunCoreMigration = definePostgresSqlMigration({
id: 'pg-0002-run-core',
statements: [
`
CREATE TABLE "ql3"."${POSTGRESQL_RUN_TABLE}" (
id varchar(36) PRIMARY KEY,
project_id varchar(128) NOT NULL,
task_id varchar(255) NOT NULL,
task_revision varchar(128) NOT NULL,
task_name varchar(255),
task_snapshot_ref varchar(512),
parent_run_id varchar(36),
retry_of_run_id varchar(36),
trigger_id varchar(36),
trigger_type varchar(64) NOT NULL,
execution_origin varchar(64) NOT NULL,
execution_owner varchar(16) NOT NULL
CONSTRAINT ql3_runs_execution_owner_check
CHECK (execution_owner = 'runtime'),
triggered_by varchar(255),
request_id varchar(128),
scheduled_for_ms bigint
CONSTRAINT ql3_runs_scheduled_for_check
CHECK (scheduled_for_ms IS NULL OR scheduled_for_ms >= 0),
status varchar(32) NOT NULL
CONSTRAINT ql3_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_runs_version_check
CHECK (version >= 0),
event_sequence integer NOT NULL DEFAULT 0
CONSTRAINT ql3_runs_event_sequence_check
CHECK (event_sequence >= 0),
priority integer NOT NULL DEFAULT 0,
idempotency_key varchar(255),
input_ref varchar(512),
output_ref varchar(512),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_runs_created_at_check
CHECK (created_at_ms >= 0),
queued_at_ms bigint
CONSTRAINT ql3_runs_queued_at_check
CHECK (queued_at_ms IS NULL OR queued_at_ms >= 0),
started_at_ms bigint
CONSTRAINT ql3_runs_started_at_check
CHECK (started_at_ms IS NULL OR started_at_ms >= 0),
finished_at_ms bigint
CONSTRAINT ql3_runs_finished_at_check
CHECK (finished_at_ms IS NULL OR finished_at_ms >= 0),
cancel_requested_at_ms bigint
CONSTRAINT ql3_runs_cancel_requested_at_check
CHECK (cancel_requested_at_ms IS NULL OR cancel_requested_at_ms >= 0),
cancel_reason varchar(16)
CONSTRAINT ql3_runs_cancel_reason_check
CHECK (cancel_reason IS NULL OR cancel_reason IN (
'user', 'policy', 'shutdown', 'reconcile', 'timeout'
)),
error_code varchar(128),
error_summary varchar(1024),
CONSTRAINT ql3_runs_parent_fk
FOREIGN KEY (parent_run_id) REFERENCES "ql3"."${POSTGRESQL_RUN_TABLE}" (id),
CONSTRAINT ql3_runs_retry_of_fk
FOREIGN KEY (retry_of_run_id) REFERENCES "ql3"."${POSTGRESQL_RUN_TABLE}" (id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_runs_project_idempotency_uidx
ON "ql3"."${POSTGRESQL_RUN_TABLE}" (project_id, idempotency_key)
WHERE idempotency_key IS NOT NULL
`.trim(),
`
CREATE INDEX ql3_runs_project_created_idx
ON "ql3"."${POSTGRESQL_RUN_TABLE}" (project_id, created_at_ms, id)
`.trim(),
`
CREATE INDEX ql3_runs_task_created_idx
ON "ql3"."${POSTGRESQL_RUN_TABLE}" (task_id, created_at_ms, id)
`.trim(),
`
CREATE INDEX ql3_runs_dispatch_candidates_idx
ON "ql3"."${POSTGRESQL_RUN_TABLE}" (priority DESC, queued_at_ms, id)
WHERE execution_owner = 'runtime'
AND status IN ('queued', 'dispatching')
AND cancel_requested_at_ms IS NULL
AND queued_at_ms IS NOT NULL
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_RUN_ATTEMPT_TABLE}" (
id varchar(36) PRIMARY KEY,
run_id varchar(36) NOT NULL,
step_run_id varchar(36),
attempt integer NOT NULL
CONSTRAINT ql3_run_attempts_attempt_check
CHECK (attempt >= 1),
status varchar(32) NOT NULL
CONSTRAINT ql3_run_attempts_status_check
CHECK (status IN (
'claimed', 'starting', 'running', 'succeeded', 'failed',
'cancelled', 'timed_out', 'lost'
)),
executor_type varchar(64) NOT NULL,
worker_id varchar(128),
executor_handle varchar(2048),
pid integer
CONSTRAINT ql3_run_attempts_pid_check
CHECK (pid IS NULL OR pid >= 1),
log_artifact_id varchar(36),
lease_token varchar(128),
lease_expires_at_ms bigint
CONSTRAINT ql3_run_attempts_lease_expiry_check
CHECK (lease_expires_at_ms IS NULL OR lease_expires_at_ms >= 0),
deadline_at_ms bigint
CONSTRAINT ql3_run_attempts_deadline_check
CHECK (deadline_at_ms IS NULL OR deadline_at_ms >= 0),
callback_token_hash varchar(128),
callback_sequence integer NOT NULL DEFAULT 0
CONSTRAINT ql3_run_attempts_callback_sequence_check
CHECK (callback_sequence >= 0),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_run_attempts_created_at_check
CHECK (created_at_ms >= 0),
started_at_ms bigint
CONSTRAINT ql3_run_attempts_started_at_check
CHECK (started_at_ms IS NULL OR started_at_ms >= 0),
finished_at_ms bigint
CONSTRAINT ql3_run_attempts_finished_at_check
CHECK (finished_at_ms IS NULL OR finished_at_ms >= 0),
exit_code integer,
error_code varchar(128),
error_summary varchar(1024),
CONSTRAINT ql3_run_attempts_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."${POSTGRESQL_RUN_TABLE}" (id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_run_attempts_run_attempt_uidx
ON "ql3"."${POSTGRESQL_RUN_ATTEMPT_TABLE}" (run_id, attempt)
`.trim(),
`
CREATE INDEX ql3_run_attempts_dispatch_candidates_idx
ON "ql3"."${POSTGRESQL_RUN_ATTEMPT_TABLE}" (status, run_id, created_at_ms, id)
`.trim(),
`
CREATE INDEX ql3_run_attempts_lease_idx
ON "ql3"."${POSTGRESQL_RUN_ATTEMPT_TABLE}" (lease_expires_at_ms, id)
WHERE lease_expires_at_ms IS NOT NULL
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_RUN_EVENT_TABLE}" (
id varchar(36) PRIMARY KEY,
run_id varchar(36) NOT NULL,
sequence integer NOT NULL
CONSTRAINT ql3_run_events_sequence_check
CHECK (sequence >= 1),
type varchar(128) NOT NULL,
dedupe_key varchar(255),
actor_type varchar(64) NOT NULL
CONSTRAINT ql3_run_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 varchar(255),
attempt_id varchar(36),
step_run_id varchar(36),
payload jsonb NOT NULL
CONSTRAINT ql3_run_events_payload_check
CHECK (jsonb_typeof(payload) = 'object'),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_run_events_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT ql3_run_events_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."${POSTGRESQL_RUN_TABLE}" (id),
CONSTRAINT ql3_run_events_attempt_fk
FOREIGN KEY (attempt_id) REFERENCES "ql3"."${POSTGRESQL_RUN_ATTEMPT_TABLE}" (id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_run_events_run_sequence_uidx
ON "ql3"."${POSTGRESQL_RUN_EVENT_TABLE}" (run_id, sequence)
`.trim(),
`
CREATE UNIQUE INDEX ql3_run_events_run_dedupe_uidx
ON "ql3"."${POSTGRESQL_RUN_EVENT_TABLE}" (run_id, dedupe_key)
WHERE dedupe_key IS NOT NULL
`.trim(),
`
CREATE INDEX ql3_run_events_run_created_idx
ON "ql3"."${POSTGRESQL_RUN_EVENT_TABLE}" (run_id, created_at_ms, id)
`.trim(),
`
INSERT INTO "ql3"."schema_capabilities" (
contract_name,
contract_version,
migration_id,
capabilities,
updated_at_ms
)
VALUES (
'control-core',
1,
'pg-0002-run-core',
'{"run_core":1}'::jsonb,
floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
)
ON CONFLICT (contract_name) DO UPDATE
SET contract_version = EXCLUDED.contract_version,
migration_id = EXCLUDED.migration_id,
capabilities = EXCLUDED.capabilities,
updated_at_ms = EXCLUDED.updated_at_ms
WHERE "schema_capabilities".contract_version < EXCLUDED.contract_version
`.trim(),
],
});
@@ -0,0 +1,78 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_RUN_RETRY_POLICY_TABLE = 'run_retry_policies';
export const pg0003RunRetryPolicyMigration = definePostgresSqlMigration({
id: 'pg-0003-run-retry-policy',
statements: [
`
ALTER TABLE "ql3"."runs"
ADD COLUMN legacy_cron_id integer
CONSTRAINT ql3_runs_legacy_cron_id_check
CHECK (legacy_cron_id IS NULL OR legacy_cron_id >= 1)
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_RUN_RETRY_POLICY_TABLE}" (
run_id varchar(36) PRIMARY KEY,
max_attempts integer NOT NULL
CONSTRAINT ql3_run_retry_policies_max_attempts_check
CHECK (max_attempts BETWEEN 1 AND 16),
retry_on_lost boolean NOT NULL,
safety varchar(16) NOT NULL
CONSTRAINT ql3_run_retry_policies_safety_check
CHECK (safety IN ('unknown', 'idempotent', 'deduplicated')),
backoff_base_ms bigint NOT NULL
CONSTRAINT ql3_run_retry_policies_backoff_base_check
CHECK (backoff_base_ms BETWEEN 0 AND 86400000),
backoff_max_ms bigint NOT NULL
CONSTRAINT ql3_run_retry_policies_backoff_max_check
CHECK (backoff_max_ms BETWEEN backoff_base_ms AND 86400000),
next_attempt_at_ms bigint
CONSTRAINT ql3_run_retry_policies_next_attempt_check
CHECK (next_attempt_at_ms IS NULL OR next_attempt_at_ms >= 0),
version integer NOT NULL DEFAULT 0
CONSTRAINT ql3_run_retry_policies_version_check
CHECK (version >= 0),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_run_retry_policies_created_at_check
CHECK (created_at_ms >= 0),
updated_at_ms bigint NOT NULL
CONSTRAINT ql3_run_retry_policies_updated_at_check
CHECK (updated_at_ms >= created_at_ms),
CONSTRAINT ql3_run_retry_policies_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."runs" (id) ON DELETE CASCADE
)
`.trim(),
`
CREATE INDEX ql3_run_retry_policies_due_idx
ON "ql3"."${POSTGRESQL_RUN_RETRY_POLICY_TABLE}" (next_attempt_at_ms, run_id)
WHERE next_attempt_at_ms IS NOT NULL
`.trim(),
`
CREATE INDEX ql3_runs_lost_retry_idx
ON "ql3"."runs" (execution_owner, status, id)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 2,
migration_id = 'pg-0003-run-retry-policy',
capabilities = '{"run_core":1,"run_retry_policy":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 1
AND migration_id = 'pg-0002-run-core'
AND capabilities = '{"run_core":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 1'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,119 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_PROJECT_TABLE = 'projects';
export const POSTGRESQL_PROJECT_ROLE_BINDING_TABLE = 'project_role_bindings';
export const pg0004ProjectPolicyMigration = definePostgresSqlMigration({
id: 'pg-0004-project-policy',
statements: [
`
CREATE TABLE "ql3"."${POSTGRESQL_PROJECT_TABLE}" (
id varchar(128) PRIMARY KEY
CONSTRAINT ql3_projects_id_check CHECK (char_length(id) >= 1),
name varchar(255) NOT NULL
CONSTRAINT ql3_projects_name_check CHECK (char_length(name) >= 1),
slug varchar(128) NOT NULL
CONSTRAINT ql3_projects_slug_check
CHECK (slug ~ '^[a-z0-9](?:[a-z0-9-]{0,126}[a-z0-9])?$'),
status varchar(16) NOT NULL
CONSTRAINT ql3_projects_status_check
CHECK (status IN ('active', 'archived')),
version integer NOT NULL
CONSTRAINT ql3_projects_version_check
CHECK (version BETWEEN 1 AND 2147483647),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_projects_created_at_check CHECK (created_at_ms >= 0),
updated_at_ms bigint NOT NULL
CONSTRAINT ql3_projects_updated_at_check
CHECK (updated_at_ms >= created_at_ms)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_projects_slug_uidx
ON "ql3"."${POSTGRESQL_PROJECT_TABLE}" (slug)
`.trim(),
`
INSERT INTO "ql3"."${POSTGRESQL_PROJECT_TABLE}" (
id, name, slug, status, version, created_at_ms, updated_at_ms
)
VALUES ('default', 'Default', 'default', 'active', 1, 0, 0)
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_PROJECT_ROLE_BINDING_TABLE}" (
project_id varchar(128) NOT NULL,
subject_type varchar(32) NOT NULL
CONSTRAINT ql3_project_role_bindings_subject_type_check
CHECK (subject_type IN ('user', 'api_app', 'mcp_client', 'agent', 'system', 'worker')),
subject_id varchar(255) NOT NULL
CONSTRAINT ql3_project_role_bindings_subject_id_check
CHECK (char_length(subject_id) >= 1),
version integer NOT NULL
CONSTRAINT ql3_project_role_bindings_version_check
CHECK (version BETWEEN 1 AND 2147483647),
state varchar(16) NOT NULL
CONSTRAINT ql3_project_role_bindings_state_check
CHECK (state IN ('active', 'revoked')),
role varchar(16),
mutation_id varchar(64) NOT NULL
CONSTRAINT ql3_project_role_bindings_mutation_id_check
CHECK (mutation_id ~ '^[A-Za-z0-9._:-]{1,64}$'),
changed_by_type varchar(32) NOT NULL
CONSTRAINT ql3_project_role_bindings_changed_by_type_check
CHECK (changed_by_type IN ('user', 'api_app', 'mcp_client', 'agent', 'system', 'worker')),
changed_by_id varchar(255) NOT NULL
CONSTRAINT ql3_project_role_bindings_changed_by_id_check
CHECK (char_length(changed_by_id) >= 1),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_project_role_bindings_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT project_role_bindings_pkey
PRIMARY KEY (project_id, subject_type, subject_id, version),
CONSTRAINT ql3_project_role_bindings_role_state_check
CHECK (
(state = 'active' AND role IN ('owner', 'admin', 'operator', 'viewer'))
OR (state = 'revoked' AND role IS NULL)
),
CONSTRAINT ql3_project_role_bindings_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."${POSTGRESQL_PROJECT_TABLE}" (id)
ON DELETE CASCADE
)
`.trim(),
`
CREATE INDEX ql3_project_role_bindings_current_idx
ON "ql3"."${POSTGRESQL_PROJECT_ROLE_BINDING_TABLE}"
(project_id, subject_type, subject_id, version DESC)
`.trim(),
`
CREATE UNIQUE INDEX ql3_project_role_bindings_mutation_uidx
ON "ql3"."${POSTGRESQL_PROJECT_ROLE_BINDING_TABLE}"
(project_id, mutation_id)
`.trim(),
`
CREATE INDEX ql3_project_role_bindings_subject_idx
ON "ql3"."${POSTGRESQL_PROJECT_ROLE_BINDING_TABLE}"
(subject_type, subject_id, project_id, version DESC)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 3,
migration_id = 'pg-0004-project-policy',
capabilities = '{"project_policy":1,"run_core":1,"run_retry_policy":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 2
AND migration_id = 'pg-0003-run-retry-policy'
AND capabilities = '{"run_core":1,"run_retry_policy":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 2'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,205 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_IDENTITY_SUBJECT_TABLE = 'identity_subjects';
export const POSTGRESQL_API_CREDENTIAL_TABLE = 'api_credentials';
export const POSTGRESQL_SECURITY_AUDIT_EVENT_TABLE = 'security_audit_events';
export const pg0005ApiCredentialSecurityAuditMigration =
definePostgresSqlMigration({
id: 'pg-0005-api-credential-security-audit',
statements: [
`
CREATE TABLE "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_TABLE}" (
subject_type varchar(32) NOT NULL
CONSTRAINT ql3_identity_subjects_type_check
CHECK (subject_type IN ('user', 'api_app', 'mcp_client', 'agent', 'system', 'worker')),
subject_id varchar(255) NOT NULL
CONSTRAINT ql3_identity_subjects_id_check
CHECK (char_length(subject_id) >= 1),
status varchar(16) NOT NULL
CONSTRAINT ql3_identity_subjects_status_check
CHECK (status IN ('active', 'disabled')),
version integer NOT NULL
CONSTRAINT ql3_identity_subjects_version_check
CHECK (version BETWEEN 1 AND 2147483647),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_identity_subjects_created_at_check
CHECK (created_at_ms >= 0),
updated_at_ms bigint NOT NULL
CONSTRAINT ql3_identity_subjects_updated_at_check
CHECK (updated_at_ms >= created_at_ms),
CONSTRAINT identity_subjects_pkey
PRIMARY KEY (subject_type, subject_id)
)
`.trim(),
`
CREATE INDEX ql3_identity_subjects_status_idx
ON "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_TABLE}"
(status, subject_type, subject_id)
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_API_CREDENTIAL_TABLE}" (
credential_id varchar(64) NOT NULL
CONSTRAINT ql3_api_credentials_id_check
CHECK (credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'),
version integer NOT NULL
CONSTRAINT ql3_api_credentials_version_check
CHECK (version BETWEEN 1 AND 2147483647),
state varchar(16) NOT NULL
CONSTRAINT ql3_api_credentials_state_check
CHECK (state IN ('active', 'revoked')),
subject_type varchar(32) NOT NULL
CONSTRAINT ql3_api_credentials_subject_type_check
CHECK (subject_type IN ('user', 'api_app', 'mcp_client', 'agent')),
subject_id varchar(255) NOT NULL
CONSTRAINT ql3_api_credentials_subject_id_check
CHECK (char_length(subject_id) >= 1),
secret_digest char(64) NOT NULL
CONSTRAINT ql3_api_credentials_secret_digest_check
CHECK (secret_digest ~ '^[a-f0-9]{64}$'),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_api_credentials_created_at_check
CHECK (created_at_ms >= 0),
not_before_at_ms bigint NOT NULL
CONSTRAINT ql3_api_credentials_not_before_check
CHECK (not_before_at_ms >= created_at_ms),
expires_at_ms bigint NOT NULL
CONSTRAINT ql3_api_credentials_expires_at_check
CHECK (expires_at_ms > not_before_at_ms),
CONSTRAINT api_credentials_pkey
PRIMARY KEY (credential_id, version),
CONSTRAINT ql3_api_credentials_subject_fk
FOREIGN KEY (subject_type, subject_id)
REFERENCES "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_TABLE}"
(subject_type, subject_id)
ON DELETE RESTRICT
)
`.trim(),
`
CREATE INDEX ql3_api_credentials_current_idx
ON "ql3"."${POSTGRESQL_API_CREDENTIAL_TABLE}"
(credential_id, version DESC)
`.trim(),
`
CREATE INDEX ql3_api_credentials_subject_idx
ON "ql3"."${POSTGRESQL_API_CREDENTIAL_TABLE}"
(subject_type, subject_id, credential_id, version DESC)
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_SECURITY_AUDIT_EVENT_TABLE}" (
event_id uuid PRIMARY KEY,
request_id varchar(128) NOT NULL
CONSTRAINT ql3_security_audit_events_request_id_check
CHECK (request_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'),
operation_id varchar(128) NOT NULL
CONSTRAINT ql3_security_audit_events_operation_id_check
CHECK (operation_id ~ '^[a-z][a-z0-9_.:-]{0,127}$'),
project_id varchar(128)
CONSTRAINT ql3_security_audit_events_project_id_check
CHECK (
project_id IS NULL
OR project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
subject_type varchar(32)
CONSTRAINT ql3_security_audit_events_subject_type_check
CHECK (
subject_type IS NULL
OR subject_type IN ('user', 'api_app', 'mcp_client', 'agent', 'system', 'worker')
),
subject_id varchar(255)
CONSTRAINT ql3_security_audit_events_subject_id_check
CHECK (subject_id IS NULL OR char_length(subject_id) >= 1),
authentication_id varchar(128)
CONSTRAINT ql3_security_audit_events_authentication_id_check
CHECK (
authentication_id IS NULL
OR authentication_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
outcome varchar(32) NOT NULL
CONSTRAINT ql3_security_audit_events_outcome_check
CHECK (
outcome IN (
'authentication_rejected',
'authentication_unavailable',
'authorization_unavailable',
'denied',
'approval_required',
'allowed'
)
),
reasons jsonb NOT NULL
CONSTRAINT ql3_security_audit_events_reasons_check
CHECK (
jsonb_typeof(reasons) = 'array'
AND jsonb_array_length(reasons) BETWEEN 1 AND 8
AND octet_length(reasons::text) <= 1024
),
project_version integer
CONSTRAINT ql3_security_audit_events_project_version_check
CHECK (project_version IS NULL OR project_version >= 1),
binding_version integer
CONSTRAINT ql3_security_audit_events_binding_version_check
CHECK (binding_version IS NULL OR binding_version >= 1),
occurred_at_ms bigint NOT NULL
CONSTRAINT ql3_security_audit_events_occurred_at_check
CHECK (occurred_at_ms >= 0),
CONSTRAINT ql3_security_audit_events_identity_check
CHECK (
(
outcome IN ('authentication_rejected', 'authentication_unavailable')
AND subject_type IS NULL
AND subject_id IS NULL
AND authentication_id IS NULL
)
OR (
outcome NOT IN ('authentication_rejected', 'authentication_unavailable')
AND subject_type IS NOT NULL
AND subject_id IS NOT NULL
AND authentication_id IS NOT NULL
)
),
CONSTRAINT ql3_security_audit_events_fence_check
CHECK (project_version IS NOT NULL OR binding_version IS NULL)
)
`.trim(),
`
CREATE INDEX ql3_security_audit_events_occurred_idx
ON "ql3"."${POSTGRESQL_SECURITY_AUDIT_EVENT_TABLE}"
(occurred_at_ms DESC, event_id)
`.trim(),
`
CREATE INDEX ql3_security_audit_events_subject_idx
ON "ql3"."${POSTGRESQL_SECURITY_AUDIT_EVENT_TABLE}"
(subject_type, subject_id, occurred_at_ms DESC, event_id)
WHERE subject_type IS NOT NULL
`.trim(),
`
CREATE INDEX ql3_security_audit_events_project_idx
ON "ql3"."${POSTGRESQL_SECURITY_AUDIT_EVENT_TABLE}"
(project_id, occurred_at_ms DESC, event_id)
WHERE project_id IS NOT NULL
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 4,
migration_id = 'pg-0005-api-credential-security-audit',
capabilities = '{"api_credential":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 3
AND migration_id = 'pg-0004-project-policy'
AND capabilities = '{"project_policy":1,"run_core":1,"run_retry_policy":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 3'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,316 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const POSTGRESQL_IDENTITY_SUBJECT_MUTATION_TABLE =
'identity_subject_mutations';
export const POSTGRESQL_API_CREDENTIAL_MUTATION_TABLE =
'api_credential_mutations';
export const pg0006IdentityCredentialAdministrationMigration =
definePostgresSqlMigration({
id: 'pg-0006-identity-credential-administration',
statements: [
`
CREATE TABLE "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_MUTATION_TABLE}" (
mutation_id uuid PRIMARY KEY,
operation varchar(16) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_operation_check
CHECK (operation IN ('import', 'register', 'enable', 'disable')),
subject_type varchar(32) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_subject_type_check
CHECK (subject_type IN ('user', 'api_app', 'mcp_client', 'agent', 'system', 'worker')),
subject_id varchar(255) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_subject_id_check
CHECK (char_length(subject_id) >= 1),
subject_version integer NOT NULL
CONSTRAINT ql3_identity_subject_mutations_version_check
CHECK (subject_version BETWEEN 1 AND 2147483647),
expected_previous_version integer NOT NULL
CONSTRAINT ql3_identity_subject_mutations_previous_version_check
CHECK (expected_previous_version BETWEEN 0 AND 2147483646),
status varchar(16) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_status_check
CHECK (status IN ('active', 'disabled')),
changed_by_type varchar(32) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_changed_by_type_check
CHECK (changed_by_type IN ('user', 'system')),
changed_by_id varchar(255) NOT NULL
CONSTRAINT ql3_identity_subject_mutations_changed_by_id_check
CHECK (char_length(changed_by_id) >= 1),
audit_event_id uuid NOT NULL,
identity_created_at_ms bigint NOT NULL
CONSTRAINT ql3_identity_subject_mutations_identity_created_at_check
CHECK (identity_created_at_ms >= 0),
created_at_ms bigint NOT NULL
CONSTRAINT ql3_identity_subject_mutations_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT ql3_identity_subject_mutations_version_fence_check
CHECK (subject_version = expected_previous_version + 1),
CONSTRAINT ql3_identity_subject_mutations_transition_check
CHECK (
operation = 'import'
OR (operation = 'register' AND expected_previous_version = 0 AND status = 'active')
OR (operation = 'enable' AND expected_previous_version >= 1 AND status = 'active')
OR (operation = 'disable' AND expected_previous_version >= 1 AND status = 'disabled')
),
CONSTRAINT ql3_identity_subject_mutations_audit_identity_check
CHECK (mutation_id = audit_event_id),
CONSTRAINT ql3_identity_subject_mutations_subject_fk
FOREIGN KEY (subject_type, subject_id)
REFERENCES "ql3"."identity_subjects" (subject_type, subject_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_identity_subject_mutations_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ql3"."security_audit_events" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_identity_subject_mutations_subject_version_uidx
UNIQUE (subject_type, subject_id, subject_version)
)
`.trim(),
`
CREATE INDEX ql3_identity_subject_mutations_actor_idx
ON "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_MUTATION_TABLE}"
(changed_by_type, changed_by_id, created_at_ms DESC, mutation_id)
`.trim(),
`
WITH source AS (
SELECT
subject.*,
md5('ql3-identity-import:' || subject.subject_type || ':' || subject.subject_id) AS digest
FROM "ql3"."identity_subjects" AS subject
), imported AS (
SELECT
source.*,
(
substr(digest, 1, 8) || '-' || substr(digest, 9, 4) || '-4' ||
substr(digest, 14, 3) || '-8' || substr(digest, 18, 3) || '-' ||
substr(digest, 21, 12)
)::uuid AS mutation_id
FROM source
)
INSERT INTO "ql3"."security_audit_events" (
event_id, request_id, operation_id, project_id, subject_type, subject_id,
authentication_id, outcome, reasons, project_version, binding_version,
occurred_at_ms
)
SELECT
mutation_id,
'migration:' || mutation_id::text,
'identity.import',
NULL,
'system',
'pg-0006',
'migration:pg-0006',
'allowed',
'["identity_admin"]'::jsonb,
NULL,
NULL,
created_at_ms
FROM imported
`.trim(),
`
WITH source AS (
SELECT
subject.*,
md5('ql3-identity-import:' || subject.subject_type || ':' || subject.subject_id) AS digest
FROM "ql3"."identity_subjects" AS subject
), imported AS (
SELECT
source.*,
(
substr(digest, 1, 8) || '-' || substr(digest, 9, 4) || '-4' ||
substr(digest, 14, 3) || '-8' || substr(digest, 18, 3) || '-' ||
substr(digest, 21, 12)
)::uuid AS mutation_id
FROM source
)
INSERT INTO "ql3"."${POSTGRESQL_IDENTITY_SUBJECT_MUTATION_TABLE}" (
mutation_id, operation, subject_type, subject_id, subject_version,
expected_previous_version, status, changed_by_type, changed_by_id,
audit_event_id, identity_created_at_ms, created_at_ms
)
SELECT
mutation_id,
'import',
subject_type,
subject_id,
version,
version - 1,
status,
'system',
'pg-0006',
mutation_id,
created_at_ms,
created_at_ms
FROM imported
`.trim(),
`
CREATE TABLE "ql3"."${POSTGRESQL_API_CREDENTIAL_MUTATION_TABLE}" (
mutation_id uuid PRIMARY KEY,
operation varchar(16) NOT NULL
CONSTRAINT ql3_api_credential_mutations_operation_check
CHECK (operation IN ('import', 'issue', 'rotate', 'revoke')),
credential_id varchar(64) NOT NULL
CONSTRAINT ql3_api_credential_mutations_id_check
CHECK (credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'),
credential_version integer NOT NULL
CONSTRAINT ql3_api_credential_mutations_version_check
CHECK (credential_version BETWEEN 1 AND 2147483647),
expected_previous_version integer NOT NULL
CONSTRAINT ql3_api_credential_mutations_previous_version_check
CHECK (expected_previous_version BETWEEN 0 AND 2147483646),
state varchar(16) NOT NULL
CONSTRAINT ql3_api_credential_mutations_state_check
CHECK (state IN ('active', 'revoked')),
subject_type varchar(32) NOT NULL
CONSTRAINT ql3_api_credential_mutations_subject_type_check
CHECK (subject_type IN ('user', 'api_app', 'mcp_client', 'agent')),
subject_id varchar(255) NOT NULL
CONSTRAINT ql3_api_credential_mutations_subject_id_check
CHECK (char_length(subject_id) >= 1),
subject_status varchar(16) NOT NULL
CONSTRAINT ql3_api_credential_mutations_subject_status_check
CHECK (subject_status IN ('active', 'disabled')),
changed_by_type varchar(32) NOT NULL
CONSTRAINT ql3_api_credential_mutations_changed_by_type_check
CHECK (changed_by_type IN ('user', 'system')),
changed_by_id varchar(255) NOT NULL
CONSTRAINT ql3_api_credential_mutations_changed_by_id_check
CHECK (char_length(changed_by_id) >= 1),
audit_event_id uuid NOT NULL,
created_at_ms bigint NOT NULL
CONSTRAINT ql3_api_credential_mutations_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT ql3_api_credential_mutations_version_fence_check
CHECK (credential_version = expected_previous_version + 1),
CONSTRAINT ql3_api_credential_mutations_transition_check
CHECK (
operation = 'import'
OR (operation = 'issue' AND expected_previous_version = 0 AND state = 'active')
OR (operation = 'rotate' AND expected_previous_version >= 1 AND state = 'active')
OR (operation = 'revoke' AND expected_previous_version >= 1 AND state = 'revoked')
),
CONSTRAINT ql3_api_credential_mutations_audit_identity_check
CHECK (mutation_id = audit_event_id),
CONSTRAINT ql3_api_credential_mutations_credential_fk
FOREIGN KEY (credential_id, credential_version)
REFERENCES "ql3"."api_credentials" (credential_id, version)
ON DELETE RESTRICT,
CONSTRAINT ql3_api_credential_mutations_subject_fk
FOREIGN KEY (subject_type, subject_id)
REFERENCES "ql3"."identity_subjects" (subject_type, subject_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_api_credential_mutations_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ql3"."security_audit_events" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_api_credential_mutations_credential_version_uidx
UNIQUE (credential_id, credential_version)
)
`.trim(),
`
CREATE INDEX ql3_api_credential_mutations_actor_idx
ON "ql3"."${POSTGRESQL_API_CREDENTIAL_MUTATION_TABLE}"
(changed_by_type, changed_by_id, created_at_ms DESC, mutation_id)
`.trim(),
`
WITH source AS (
SELECT
credential.*,
md5('ql3-credential-import:' || credential.credential_id || ':' || credential.version::text) AS digest
FROM "ql3"."api_credentials" AS credential
), imported AS (
SELECT
source.*,
(
substr(digest, 1, 8) || '-' || substr(digest, 9, 4) || '-4' ||
substr(digest, 14, 3) || '-8' || substr(digest, 18, 3) || '-' ||
substr(digest, 21, 12)
)::uuid AS mutation_id
FROM source
)
INSERT INTO "ql3"."security_audit_events" (
event_id, request_id, operation_id, project_id, subject_type, subject_id,
authentication_id, outcome, reasons, project_version, binding_version,
occurred_at_ms
)
SELECT
mutation_id,
'migration:' || mutation_id::text,
'credential.import',
NULL,
'system',
'pg-0006',
'migration:pg-0006',
'allowed',
'["credential_admin"]'::jsonb,
NULL,
NULL,
created_at_ms
FROM imported
`.trim(),
`
WITH source AS (
SELECT
credential.*,
md5('ql3-credential-import:' || credential.credential_id || ':' || credential.version::text) AS digest
FROM "ql3"."api_credentials" AS credential
), imported AS (
SELECT
source.*,
(
substr(digest, 1, 8) || '-' || substr(digest, 9, 4) || '-4' ||
substr(digest, 14, 3) || '-8' || substr(digest, 18, 3) || '-' ||
substr(digest, 21, 12)
)::uuid AS mutation_id
FROM source
)
INSERT INTO "ql3"."${POSTGRESQL_API_CREDENTIAL_MUTATION_TABLE}" (
mutation_id, operation, credential_id, credential_version,
expected_previous_version, state, subject_type, subject_id,
subject_status, changed_by_type, changed_by_id, audit_event_id, created_at_ms
)
SELECT
mutation_id,
'import',
credential_id,
version,
version - 1,
state,
subject_type,
subject_id,
(
SELECT identity.status
FROM "ql3"."identity_subjects" AS identity
WHERE identity.subject_type = imported.subject_type
AND identity.subject_id = imported.subject_id
),
'system',
'pg-0006',
mutation_id,
created_at_ms
FROM imported
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 5,
migration_id = 'pg-0006-identity-credential-administration',
capabilities = '{"api_credential":1,"api_credential_admin":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 4
AND migration_id = 'pg-0005-api-credential-security-audit'
AND capabilities = '{"api_credential":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 4'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,42 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0007ClusterRecoveryIndexesMigration = definePostgresSqlMigration(
{
id: 'pg-0007-cluster-recovery-indexes',
statements: [
`
CREATE INDEX ql3_runs_runtime_recovery_idx
ON "ql3"."runs" (created_at_ms, id)
WHERE execution_owner = 'runtime'
AND status IN ('created', 'dispatching', 'running')
`.trim(),
`
CREATE INDEX ql3_run_attempts_recovery_idx
ON "ql3"."run_attempts" (lease_expires_at_ms, created_at_ms, id)
WHERE status IN ('claimed', 'starting', 'running')
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 6,
migration_id = 'pg-0007-cluster-recovery-indexes',
capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 5
AND migration_id = 'pg-0006-identity-credential-administration'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 5'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
},
);
@@ -0,0 +1,148 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0008RunRecoveryClaimsMigration = definePostgresSqlMigration({
id: 'pg-0008-run-recovery-claims',
statements: [
`
CREATE TABLE "ql3"."run_recovery_controls" (
target_kind varchar(16) NOT NULL,
target_id varchar(36) NOT NULL,
run_id varchar(36) NOT NULL,
attempt_id varchar(36),
target_status varchar(32) NOT NULL,
target_created_at_ms bigint NOT NULL,
observed_at_ms bigint NOT NULL,
state varchar(16) NOT NULL,
claim_owner varchar(128),
claim_token varchar(64),
claim_version integer NOT NULL DEFAULT 0,
claim_expires_at_ms bigint,
next_claim_at_ms bigint,
failure_count integer NOT NULL DEFAULT 0,
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT run_recovery_controls_pkey
PRIMARY KEY (target_kind, target_id),
CONSTRAINT ql3_run_recovery_controls_target_kind_check
CHECK (target_kind IN ('run', 'attempt')),
CONSTRAINT ql3_run_recovery_controls_target_id_check
CHECK (char_length(target_id) >= 1),
CONSTRAINT ql3_run_recovery_controls_target_shape_check
CHECK (
(
target_kind = 'run'
AND target_id = run_id
AND attempt_id IS NULL
AND target_status IN ('created', 'dispatching', 'running')
)
OR (
target_kind = 'attempt'
AND target_id = attempt_id
AND attempt_id IS NOT NULL
AND target_status IN ('claimed', 'starting', 'running')
)
),
CONSTRAINT ql3_run_recovery_controls_target_created_at_check
CHECK (target_created_at_ms >= 0),
CONSTRAINT ql3_run_recovery_controls_observed_at_check
CHECK (observed_at_ms >= 0),
CONSTRAINT ql3_run_recovery_controls_state_check
CHECK (state IN ('available', 'claimed', 'retry', 'manual', 'resolved')),
CONSTRAINT ql3_run_recovery_controls_claim_owner_check
CHECK (
claim_owner IS NULL
OR claim_owner ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_run_recovery_controls_claim_token_check
CHECK (
claim_token IS NULL
OR claim_token ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{15,63}$'
),
CONSTRAINT ql3_run_recovery_controls_claim_version_check
CHECK (claim_version BETWEEN 0 AND 2147483647),
CONSTRAINT ql3_run_recovery_controls_claim_expires_at_check
CHECK (claim_expires_at_ms IS NULL OR claim_expires_at_ms >= 0),
CONSTRAINT ql3_run_recovery_controls_next_claim_at_check
CHECK (next_claim_at_ms IS NULL OR next_claim_at_ms >= 0),
CONSTRAINT ql3_run_recovery_controls_failure_count_check
CHECK (failure_count BETWEEN 0 AND 2147483647),
CONSTRAINT ql3_run_recovery_controls_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT ql3_run_recovery_controls_updated_at_check
CHECK (updated_at_ms >= created_at_ms),
CONSTRAINT ql3_run_recovery_controls_state_shape_check
CHECK (
(
state = 'claimed'
AND claim_owner IS NOT NULL
AND claim_token IS NOT NULL
AND claim_expires_at_ms IS NOT NULL
AND next_claim_at_ms IS NULL
)
OR (
state = 'retry'
AND claim_owner IS NULL
AND claim_token IS NULL
AND claim_expires_at_ms IS NULL
AND next_claim_at_ms IS NOT NULL
)
OR (
state IN ('available', 'manual', 'resolved')
AND claim_owner IS NULL
AND claim_token IS NULL
AND claim_expires_at_ms IS NULL
AND next_claim_at_ms IS NULL
)
),
CONSTRAINT ql3_run_recovery_controls_run_fk
FOREIGN KEY (run_id)
REFERENCES "ql3"."runs" (id)
ON DELETE CASCADE,
CONSTRAINT ql3_run_recovery_controls_attempt_fk
FOREIGN KEY (attempt_id)
REFERENCES "ql3"."run_attempts" (id)
ON DELETE CASCADE
)
`.trim(),
`
CREATE INDEX ql3_run_recovery_controls_available_idx
ON "ql3"."run_recovery_controls"
(target_created_at_ms, target_kind, target_id)
WHERE state IN ('available', 'resolved')
`.trim(),
`
CREATE INDEX ql3_run_recovery_controls_retry_idx
ON "ql3"."run_recovery_controls"
(next_claim_at_ms, target_created_at_ms, target_kind, target_id)
WHERE state = 'retry'
`.trim(),
`
CREATE INDEX ql3_run_recovery_controls_claim_expiry_idx
ON "ql3"."run_recovery_controls"
(claim_expires_at_ms, target_created_at_ms, target_kind, target_id)
WHERE state = 'claimed'
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 7,
migration_id = 'pg-0008-run-recovery-claims',
capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 6
AND migration_id = 'pg-0007-cluster-recovery-indexes'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 6'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,210 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0009WorkerSessionRunLeaseMigration = definePostgresSqlMigration({
id: 'pg-0009-worker-session-run-lease',
statements: [
`
CREATE TABLE "ql3"."worker_sessions" (
worker_id varchar(128) PRIMARY KEY,
session_id varchar(36) NOT NULL,
generation integer NOT NULL,
status varchar(16) NOT NULL,
version integer NOT NULL,
capabilities_json varchar(16384) NOT NULL,
capabilities_hash char(64) NOT NULL,
max_concurrent_runs integer NOT NULL,
available_slots integer NOT NULL,
registered_at_ms bigint NOT NULL,
last_heartbeat_at_ms bigint NOT NULL,
lease_expires_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT ql3_worker_sessions_worker_id_check
CHECK (worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'),
CONSTRAINT ql3_worker_sessions_session_id_check
CHECK (session_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
CONSTRAINT ql3_worker_sessions_generation_check
CHECK (generation BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_worker_sessions_status_check
CHECK (status IN ('online', 'draining', 'offline')),
CONSTRAINT ql3_worker_sessions_version_check
CHECK (version BETWEEN 0 AND 2147483647),
CONSTRAINT ql3_worker_sessions_capabilities_check
CHECK (octet_length(capabilities_json) BETWEEN 2 AND 16384),
CONSTRAINT ql3_worker_sessions_capabilities_hash_check
CHECK (capabilities_hash ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_worker_sessions_concurrency_check
CHECK (
max_concurrent_runs BETWEEN 1 AND 1024
AND available_slots BETWEEN 0 AND max_concurrent_runs
),
CONSTRAINT ql3_worker_sessions_timestamps_check
CHECK (
registered_at_ms >= 0
AND last_heartbeat_at_ms >= registered_at_ms
AND updated_at_ms >= last_heartbeat_at_ms
AND (
(status = 'offline' AND lease_expires_at_ms >= last_heartbeat_at_ms)
OR (status <> 'offline' AND lease_expires_at_ms > last_heartbeat_at_ms)
)
),
CONSTRAINT ql3_worker_sessions_status_capacity_check
CHECK (status = 'online' OR available_slots = 0)
)
`.trim(),
`
CREATE INDEX ql3_worker_sessions_available_idx
ON "ql3"."worker_sessions" (worker_id)
WHERE status = 'online' AND available_slots > 0
`.trim(),
`
ALTER TABLE "ql3"."run_attempts"
ADD COLUMN worker_session_id varchar(36),
ADD COLUMN worker_generation integer,
ADD COLUMN lease_generation integer,
ADD COLUMN lease_version integer,
ADD COLUMN lease_token_digest char(64),
ADD COLUMN offer_id varchar(128),
ADD CONSTRAINT ql3_run_attempts_worker_session_id_check
CHECK (
worker_session_id IS NULL
OR worker_session_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
),
ADD CONSTRAINT ql3_run_attempts_worker_generation_check
CHECK (worker_generation IS NULL OR worker_generation BETWEEN 1 AND 2147483647),
ADD CONSTRAINT ql3_run_attempts_lease_generation_check
CHECK (lease_generation IS NULL OR lease_generation BETWEEN 1 AND 2147483647),
ADD CONSTRAINT ql3_run_attempts_lease_version_check
CHECK (lease_version IS NULL OR lease_version BETWEEN 0 AND 2147483647),
ADD CONSTRAINT ql3_run_attempts_lease_token_digest_check
CHECK (lease_token_digest IS NULL OR lease_token_digest ~ '^[0-9a-f]{64}$'),
ADD CONSTRAINT ql3_run_attempts_offer_id_check
CHECK (offer_id IS NULL OR char_length(offer_id) BETWEEN 1 AND 128),
ADD CONSTRAINT ql3_run_attempts_remote_fence_shape_check
CHECK (
(
worker_session_id IS NULL
AND worker_generation IS NULL
AND lease_generation IS NULL
AND lease_version IS NULL
AND lease_token_digest IS NULL
AND offer_id IS NULL
)
OR (
worker_id IS NOT NULL
AND worker_session_id IS NOT NULL
AND worker_generation IS NOT NULL
AND lease_generation IS NOT NULL
AND lease_version IS NOT NULL
AND lease_token_digest IS NOT NULL
AND offer_id IS NOT NULL
)
)
`.trim(),
`
CREATE TABLE "ql3"."run_dispatch_leases" (
attempt_id varchar(36) PRIMARY KEY,
run_id varchar(36) NOT NULL,
status varchar(16) NOT NULL,
version integer NOT NULL,
lease_generation integer NOT NULL,
worker_id varchar(128) NOT NULL,
worker_session_id varchar(36) NOT NULL,
worker_generation integer NOT NULL,
lease_token_digest char(64) NOT NULL,
offer_id varchar(128) NOT NULL,
acquired_at_ms bigint NOT NULL,
renewed_at_ms bigint NOT NULL,
expires_at_ms bigint NOT NULL,
released_at_ms bigint,
release_reason varchar(32),
completed_at_ms bigint,
updated_at_ms bigint NOT NULL,
CONSTRAINT ql3_run_dispatch_leases_status_check
CHECK (status IN ('leased', 'released', 'completed')),
CONSTRAINT ql3_run_dispatch_leases_version_check
CHECK (version BETWEEN 0 AND 2147483647),
CONSTRAINT ql3_run_dispatch_leases_generation_check
CHECK (lease_generation BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_run_dispatch_leases_worker_generation_check
CHECK (worker_generation BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_run_dispatch_leases_token_digest_check
CHECK (lease_token_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_run_dispatch_leases_offer_id_check
CHECK (char_length(offer_id) BETWEEN 1 AND 128),
CONSTRAINT ql3_run_dispatch_leases_timestamps_check
CHECK (
acquired_at_ms >= 0
AND renewed_at_ms >= acquired_at_ms
AND expires_at_ms > renewed_at_ms
AND updated_at_ms >= acquired_at_ms
),
CONSTRAINT ql3_run_dispatch_leases_state_shape_check
CHECK (
(
status = 'leased'
AND released_at_ms IS NULL
AND release_reason IS NULL
AND completed_at_ms IS NULL
)
OR (
status = 'released'
AND released_at_ms IS NOT NULL
AND release_reason IN (
'declined', 'shutdown', 'start_failed', 'capacity_changed', 'lease_expired'
)
AND completed_at_ms IS NULL
)
OR (
status = 'completed'
AND released_at_ms IS NULL
AND release_reason IS NULL
AND completed_at_ms IS NOT NULL
)
),
CONSTRAINT ql3_run_dispatch_leases_attempt_fk
FOREIGN KEY (attempt_id) REFERENCES "ql3"."run_attempts" (id) ON DELETE CASCADE,
CONSTRAINT ql3_run_dispatch_leases_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."runs" (id) ON DELETE CASCADE,
CONSTRAINT ql3_run_dispatch_leases_worker_fk
FOREIGN KEY (worker_id) REFERENCES "ql3"."worker_sessions" (worker_id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_run_dispatch_leases_offer_uidx
ON "ql3"."run_dispatch_leases" (offer_id)
`.trim(),
`
CREATE INDEX ql3_run_dispatch_leases_worker_active_idx
ON "ql3"."run_dispatch_leases"
(worker_id, worker_session_id, worker_generation, expires_at_ms, attempt_id)
WHERE status = 'leased'
`.trim(),
`
CREATE INDEX ql3_run_dispatch_leases_expiry_idx
ON "ql3"."run_dispatch_leases" (expires_at_ms, attempt_id)
WHERE status = 'leased'
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 8,
migration_id = 'pg-0009-worker-session-run-lease',
capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 7
AND migration_id = 'pg-0008-run-recovery-claims'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 7'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,167 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0010WorkerIngressAttestationMigration =
definePostgresSqlMigration({
id: 'pg-0010-worker-ingress-attestation',
statements: [
`
CREATE TABLE "ql3"."worker_credentials" (
credential_id varchar(64) NOT NULL,
version integer NOT NULL,
state varchar(16) NOT NULL,
worker_id varchar(128) NOT NULL,
secret_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
not_before_at_ms bigint NOT NULL,
expires_at_ms bigint NOT NULL,
PRIMARY KEY (credential_id, version),
CONSTRAINT ql3_worker_credentials_id_check
CHECK (credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'),
CONSTRAINT ql3_worker_credentials_version_check
CHECK (version BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_worker_credentials_state_check
CHECK (state IN ('active', 'revoked')),
CONSTRAINT ql3_worker_credentials_worker_id_check
CHECK (worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'),
CONSTRAINT ql3_worker_credentials_digest_check
CHECK (secret_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_worker_credentials_lifetime_check
CHECK (
created_at_ms >= 0
AND not_before_at_ms >= created_at_ms
AND expires_at_ms > not_before_at_ms
)
)
`.trim(),
`
CREATE INDEX ql3_worker_credentials_latest_idx
ON "ql3"."worker_credentials" (credential_id, version DESC)
`.trim(),
`
CREATE TABLE "ql3"."worker_credential_mutations" (
mutation_id varchar(36) PRIMARY KEY,
operation varchar(16) NOT NULL,
credential_id varchar(64) NOT NULL,
credential_version integer NOT NULL,
expected_previous_version integer NOT NULL,
changed_by_type varchar(32) NOT NULL,
changed_by_id varchar(255) NOT NULL,
audit_event_id uuid NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT ql3_worker_credential_mutations_id_check
CHECK (mutation_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
CONSTRAINT ql3_worker_credential_mutations_operation_check
CHECK (operation IN ('issue', 'rotate', 'revoke')),
CONSTRAINT ql3_worker_credential_mutations_version_check
CHECK (
credential_version BETWEEN 1 AND 2147483647
AND expected_previous_version BETWEEN 0 AND 2147483646
AND credential_version = expected_previous_version + 1
),
CONSTRAINT ql3_worker_credential_mutations_actor_check
CHECK (
changed_by_type IN ('user', 'system')
AND char_length(changed_by_id) BETWEEN 1 AND 255
),
CONSTRAINT ql3_worker_credential_mutations_created_at_check
CHECK (created_at_ms >= 0),
CONSTRAINT ql3_worker_credential_mutations_credential_fk
FOREIGN KEY (credential_id, credential_version)
REFERENCES "ql3"."worker_credentials" (credential_id, version),
CONSTRAINT ql3_worker_credential_mutations_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ql3"."security_audit_events" (event_id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_worker_credential_mutations_audit_uidx
ON "ql3"."worker_credential_mutations" (audit_event_id)
`.trim(),
`
CREATE TABLE "ql3"."worker_execution_attestations" (
attestation_id varchar(36) PRIMARY KEY,
run_id varchar(36) NOT NULL,
attempt_id varchar(36) NOT NULL,
sequence integer NOT NULL,
state varchar(16) NOT NULL,
worker_id varchar(128) NOT NULL,
worker_session_id varchar(36) NOT NULL,
worker_generation integer NOT NULL,
lease_token_digest char(64) NOT NULL,
lease_generation integer NOT NULL,
lease_version integer NOT NULL,
offer_id varchar(128) NOT NULL,
callback_sequence integer NOT NULL,
executor_handle varchar(512) NOT NULL,
journal_revision integer NOT NULL,
received_at_ms bigint NOT NULL,
CONSTRAINT ql3_worker_execution_attestations_id_check
CHECK (attestation_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
CONSTRAINT ql3_worker_execution_attestations_sequence_check
CHECK (sequence BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_worker_execution_attestations_state_check
CHECK (state IN ('running', 'stopped')),
CONSTRAINT ql3_worker_execution_attestations_worker_id_check
CHECK (worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'),
CONSTRAINT ql3_worker_execution_attestations_session_id_check
CHECK (worker_session_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
CONSTRAINT ql3_worker_execution_attestations_generation_check
CHECK (
worker_generation BETWEEN 1 AND 2147483647
AND lease_generation BETWEEN 1 AND 2147483647
AND lease_version BETWEEN 0 AND 2147483647
),
CONSTRAINT ql3_worker_execution_attestations_digest_check
CHECK (lease_token_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_worker_execution_attestations_offer_check
CHECK (char_length(offer_id) BETWEEN 1 AND 128),
CONSTRAINT ql3_worker_execution_attestations_callback_check
CHECK (callback_sequence BETWEEN 0 AND 2147483647),
CONSTRAINT ql3_worker_execution_attestations_handle_check
CHECK (char_length(executor_handle) BETWEEN 1 AND 512),
CONSTRAINT ql3_worker_execution_attestations_journal_check
CHECK (journal_revision BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_worker_execution_attestations_received_at_check
CHECK (received_at_ms >= 0),
CONSTRAINT ql3_worker_execution_attestations_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."runs" (id) ON DELETE CASCADE,
CONSTRAINT ql3_worker_execution_attestations_attempt_fk
FOREIGN KEY (attempt_id) REFERENCES "ql3"."run_attempts" (id) ON DELETE CASCADE,
CONSTRAINT ql3_worker_execution_attestations_worker_fk
FOREIGN KEY (worker_id) REFERENCES "ql3"."worker_sessions" (worker_id)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_worker_execution_attestations_sequence_uidx
ON "ql3"."worker_execution_attestations"
(attempt_id, lease_generation, sequence)
`.trim(),
`
CREATE INDEX ql3_worker_execution_attestations_exact_idx
ON "ql3"."worker_execution_attestations"
(attempt_id, lease_generation, sequence DESC)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 9,
migration_id = 'pg-0010-worker-ingress-attestation',
capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 8
AND migration_id = 'pg-0009-worker-session-run-lease'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 8'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,43 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0011ApiCredentialPepperBindingMigration =
definePostgresSqlMigration({
id: 'pg-0011-api-credential-pepper-binding',
statements: [
`
ALTER TABLE "ql3"."api_credentials"
ADD COLUMN pepper_key_id varchar(64) NOT NULL DEFAULT 'legacy-v1'
`.trim(),
`
ALTER TABLE "ql3"."api_credentials"
ADD CONSTRAINT ql3_api_credentials_pepper_key_id_check
CHECK (pepper_key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$')
`.trim(),
`
ALTER TABLE "ql3"."api_credentials"
ALTER COLUMN pepper_key_id DROP DEFAULT
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 10,
migration_id = 'pg-0011-api-credential-pepper-binding',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 9
AND migration_id = 'pg-0010-worker-ingress-attestation'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 9'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,189 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0012TaskTriggerDefinitionsMigration =
definePostgresSqlMigration({
id: 'pg-0012-task-trigger-definitions',
statements: [
`
CREATE TABLE "ql3"."task_definitions" (
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
current_revision integer NOT NULL,
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT task_definitions_pkey PRIMARY KEY (project_id, task_id),
CONSTRAINT ql3_task_definitions_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_task_definitions_id_check CHECK (
char_length(project_id) BETWEEN 1 AND 128
AND char_length(task_id) BETWEEN 1 AND 128
AND project_id !~ '[[:cntrl:]]'
AND task_id !~ '[[:cntrl:]]'
),
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)
)
`.trim(),
`
CREATE TABLE "ql3"."task_definition_revisions" (
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
revision integer NOT NULL,
mutation_id uuid NOT NULL,
name varchar(255) NOT NULL,
description varchar(4096),
kind varchar(16) NOT NULL,
spec_json jsonb NOT NULL,
labels_json jsonb NOT NULL,
enabled boolean NOT NULL,
content_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT task_definition_revisions_pkey
PRIMARY KEY (project_id, task_id, revision),
CONSTRAINT ql3_task_definition_revisions_head_fk
FOREIGN KEY (project_id, task_id)
REFERENCES "ql3"."task_definitions" (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_name_check CHECK (
char_length(name) BETWEEN 1 AND 255
AND (description IS NULL OR char_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 (
jsonb_typeof(spec_json) = 'object'
AND octet_length(spec_json::text) BETWEEN 2 AND 65536
),
CONSTRAINT ql3_task_definition_revisions_labels_check CHECK (
jsonb_typeof(labels_json) = 'object'
AND octet_length(labels_json::text) BETWEEN 2 AND 16384
),
CONSTRAINT ql3_task_definition_revisions_digest_check
CHECK (content_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_task_definition_revisions_created_check
CHECK (created_at_ms >= 0)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_task_definition_revisions_mutation_uidx
ON "ql3"."task_definition_revisions" (mutation_id)
`.trim(),
`
CREATE INDEX ql3_task_definition_revisions_project_kind_idx
ON "ql3"."task_definition_revisions"
(project_id, kind, enabled, task_id, revision)
`.trim(),
`
CREATE TABLE "ql3"."triggers" (
project_id varchar(128) NOT NULL,
trigger_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
current_revision integer NOT NULL,
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT triggers_pkey PRIMARY KEY (project_id, trigger_id),
CONSTRAINT ql3_triggers_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_triggers_task_fk
FOREIGN KEY (project_id, task_id)
REFERENCES "ql3"."task_definitions" (project_id, task_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_triggers_id_check CHECK (
char_length(project_id) BETWEEN 1 AND 128
AND char_length(trigger_id) BETWEEN 1 AND 128
AND char_length(task_id) BETWEEN 1 AND 128
AND project_id !~ '[[:cntrl:]]'
AND trigger_id !~ '[[:cntrl:]]'
AND task_id !~ '[[:cntrl:]]'
),
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)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_triggers_task_uidx
ON "ql3"."triggers" (project_id, trigger_id, task_id)
`.trim(),
`
CREATE TABLE "ql3"."trigger_revisions" (
project_id varchar(128) NOT NULL,
trigger_id varchar(128) NOT NULL,
revision integer NOT NULL,
mutation_id uuid NOT NULL,
task_id varchar(128) NOT NULL,
task_revision integer NOT NULL,
task_content_digest char(64) NOT NULL,
spec_json jsonb NOT NULL,
enabled boolean NOT NULL,
content_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT trigger_revisions_pkey
PRIMARY KEY (project_id, trigger_id, revision),
CONSTRAINT ql3_trigger_revisions_head_fk
FOREIGN KEY (project_id, trigger_id, task_id)
REFERENCES "ql3"."triggers" (project_id, trigger_id, task_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_trigger_revisions_task_revision_fk
FOREIGN KEY (project_id, task_id, task_revision)
REFERENCES "ql3"."task_definition_revisions" (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_task_digest_check
CHECK (task_content_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_trigger_revisions_spec_check CHECK (
jsonb_typeof(spec_json) = 'object'
AND octet_length(spec_json::text) BETWEEN 2 AND 16384
),
CONSTRAINT ql3_trigger_revisions_digest_check
CHECK (content_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_trigger_revisions_created_check
CHECK (created_at_ms >= 0)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_trigger_revisions_mutation_uidx
ON "ql3"."trigger_revisions" (mutation_id)
`.trim(),
`
CREATE INDEX ql3_trigger_revisions_project_enabled_idx
ON "ql3"."trigger_revisions"
(project_id, enabled, trigger_id, revision)
`.trim(),
`
CREATE INDEX ql3_trigger_revisions_task_idx
ON "ql3"."trigger_revisions"
(project_id, task_id, task_revision, trigger_id, revision)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 11,
migration_id = 'pg-0012-task-trigger-definitions',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 10
AND migration_id = 'pg-0011-api-credential-pepper-binding'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 10'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,73 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0013TaskExecutionRevisionsMigration =
definePostgresSqlMigration({
id: 'pg-0013-task-execution-revisions',
statements: [
`
CREATE TABLE "ql3"."task_execution_revisions" (
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
source_revision integer NOT NULL,
task_revision varchar(96) NOT NULL,
source_content_digest char(64) NOT NULL,
executor_type varchar(32) NOT NULL,
plan_schema varchar(64) NOT NULL,
plan_json jsonb NOT NULL,
content_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT task_execution_revisions_pkey
PRIMARY KEY (project_id, task_id, source_revision, executor_type),
CONSTRAINT ql3_task_execution_revisions_source_fk
FOREIGN KEY (project_id, task_id, source_revision)
REFERENCES "ql3"."task_definition_revisions"
(project_id, task_id, revision)
ON DELETE RESTRICT,
CONSTRAINT ql3_task_execution_revisions_identity_check CHECK (
task_revision = concat(
'qltd:v1:', source_revision::text, ':', source_content_digest
)
AND source_content_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_task_execution_revisions_executor_check
CHECK (executor_type = 'remote_worker'),
CONSTRAINT ql3_task_execution_revisions_plan_check CHECK (
plan_schema = 'qinglong/command-execution@v1'
AND jsonb_typeof(plan_json) = 'object'
AND octet_length(plan_json::text) BETWEEN 2 AND 98304
),
CONSTRAINT ql3_task_execution_revisions_digest_check
CHECK (content_digest ~ '^[0-9a-f]{64}$'),
CONSTRAINT ql3_task_execution_revisions_created_check
CHECK (created_at_ms >= 0)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_task_execution_revisions_ref_uidx
ON "ql3"."task_execution_revisions"
(project_id, task_id, task_revision, executor_type)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 12,
migration_id = 'pg-0013-task-execution-revisions',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 11
AND migration_id = 'pg-0012-task-trigger-definitions'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 11'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,110 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0014ClusterSchedulerAdmissionMigration =
definePostgresSqlMigration({
id: 'pg-0014-cluster-scheduler-admission',
statements: [
`
ALTER TABLE "ql3"."runs"
ALTER COLUMN trigger_id TYPE varchar(128)
`.trim(),
`
CREATE TABLE "ql3"."trigger_schedules" (
project_id varchar(128) NOT NULL,
trigger_id varchar(128) NOT NULL,
trigger_revision integer NOT NULL,
next_fire_at_ms bigint,
last_scheduled_at_ms bigint,
state_version integer NOT NULL,
claim_owner varchar(128),
claim_token uuid,
claim_version integer NOT NULL,
claim_expires_at_ms bigint,
updated_at_ms bigint NOT NULL,
CONSTRAINT trigger_schedules_pkey PRIMARY KEY (project_id, trigger_id),
CONSTRAINT ql3_trigger_schedules_revision_fk
FOREIGN KEY (project_id, trigger_id, trigger_revision)
REFERENCES "ql3"."trigger_revisions" (project_id, trigger_id, revision)
ON DELETE RESTRICT,
CONSTRAINT ql3_trigger_schedules_revision_check
CHECK (trigger_revision BETWEEN 1 AND 2147483647),
CONSTRAINT ql3_trigger_schedules_cursor_check CHECK (
next_fire_at_ms IS NULL OR next_fire_at_ms >= 0
),
CONSTRAINT ql3_trigger_schedules_last_check CHECK (
last_scheduled_at_ms IS NULL OR last_scheduled_at_ms >= 0
),
CONSTRAINT ql3_trigger_schedules_version_check CHECK (
state_version BETWEEN 0 AND 2147483647
AND claim_version BETWEEN 0 AND 2147483647
),
CONSTRAINT ql3_trigger_schedules_claim_owner_check CHECK (
claim_owner IS NULL
OR (
char_length(claim_owner) BETWEEN 1 AND 128
AND claim_owner ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
)
),
CONSTRAINT ql3_trigger_schedules_claim_shape_check CHECK (
(
claim_owner IS NULL
AND claim_token IS NULL
AND claim_expires_at_ms IS NULL
)
OR (
claim_owner IS NOT NULL
AND claim_token IS NOT NULL
AND claim_version >= 1
AND claim_expires_at_ms IS NOT NULL
AND claim_expires_at_ms > updated_at_ms
)
),
CONSTRAINT ql3_trigger_schedules_updated_check CHECK (updated_at_ms >= 0)
)
`.trim(),
`
INSERT INTO "ql3"."trigger_schedules" (
project_id, trigger_id, trigger_revision, next_fire_at_ms,
last_scheduled_at_ms, state_version, claim_owner, claim_token,
claim_version, claim_expires_at_ms, updated_at_ms
)
SELECT
project_id, trigger_id, current_revision, NULL, NULL, 0,
NULL, NULL, 0, NULL, updated_at_ms
FROM "ql3"."triggers"
`.trim(),
`
CREATE INDEX ql3_trigger_schedules_due_idx
ON "ql3"."trigger_schedules"
(next_fire_at_ms NULLS FIRST, claim_expires_at_ms, project_id, trigger_id)
`.trim(),
`
CREATE INDEX ql3_trigger_schedules_claim_expiry_idx
ON "ql3"."trigger_schedules"
(claim_expires_at_ms, project_id, trigger_id)
WHERE claim_token IS NOT NULL
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 13,
migration_id = 'pg-0014-cluster-scheduler-admission',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 12
AND migration_id = 'pg-0013-task-execution-revisions'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 12'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,177 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0015WorkerCredentialDeliveryLedgerMigration =
definePostgresSqlMigration({
id: 'pg-0015-worker-credential-delivery-ledger',
statements: [
`
CREATE TABLE "ql3"."worker_credential_deliveries" (
delivery_id varchar(36) NOT NULL,
version integer NOT NULL,
state varchar(32) NOT NULL,
worker_id varchar(128) NOT NULL,
credential_id varchar(64) NOT NULL,
credential_version integer NOT NULL,
previous_credential_id varchar(64),
secret_digest char(64) NOT NULL,
token_digest char(64) NOT NULL,
deployment_target_digest char(64) NOT NULL,
deployment_generation varchar(128) NOT NULL,
staged_at_ms bigint NOT NULL,
credential_committed_at_ms bigint NOT NULL,
published_at_ms bigint,
publication_digest char(64),
observed_at_ms bigint,
observed_session_id varchar(36),
observed_session_version integer,
previous_revoked_at_ms bigint,
CONSTRAINT worker_credential_deliveries_pkey
PRIMARY KEY (delivery_id, version),
CONSTRAINT ql3_worker_credential_deliveries_mutation_fk
FOREIGN KEY (delivery_id)
REFERENCES "ql3"."worker_credential_mutations" (mutation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_worker_credential_deliveries_credential_fk
FOREIGN KEY (credential_id, credential_version)
REFERENCES "ql3"."worker_credentials" (credential_id, version)
ON DELETE RESTRICT,
CONSTRAINT ql3_worker_credential_deliveries_version_check CHECK (
version BETWEEN 1 AND 4
AND credential_version = 1
),
CONSTRAINT ql3_worker_credential_deliveries_id_check CHECK (
delivery_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
),
CONSTRAINT ql3_worker_credential_deliveries_state_check CHECK (
state IN (
'credential_committed', 'published', 'observed', 'previous_revoked'
)
),
CONSTRAINT ql3_worker_credential_deliveries_worker_check CHECK (
char_length(worker_id) BETWEEN 1 AND 128
AND worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_worker_credential_deliveries_credential_check CHECK (
char_length(credential_id) BETWEEN 1 AND 64
AND credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'
AND (
previous_credential_id IS NULL
OR (
char_length(previous_credential_id) BETWEEN 1 AND 64
AND previous_credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'
AND previous_credential_id <> credential_id
)
)
),
CONSTRAINT ql3_worker_credential_deliveries_digest_check CHECK (
secret_digest ~ '^[0-9a-f]{64}$'
AND token_digest ~ '^[0-9a-f]{64}$'
AND deployment_target_digest ~ '^[0-9a-f]{64}$'
AND (
publication_digest IS NULL
OR publication_digest ~ '^[0-9a-f]{64}$'
)
),
CONSTRAINT ql3_worker_credential_deliveries_generation_check CHECK (
char_length(deployment_generation) BETWEEN 1 AND 128
AND deployment_generation ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_worker_credential_deliveries_session_check CHECK (
observed_session_id IS NULL
OR observed_session_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
),
CONSTRAINT ql3_worker_credential_deliveries_time_check CHECK (
staged_at_ms >= 0
AND credential_committed_at_ms >= staged_at_ms
AND (published_at_ms IS NULL OR published_at_ms >= credential_committed_at_ms)
AND (observed_at_ms IS NULL OR observed_at_ms >= published_at_ms)
AND (
previous_revoked_at_ms IS NULL
OR previous_revoked_at_ms >= observed_at_ms
)
),
CONSTRAINT ql3_worker_credential_deliveries_state_shape_check CHECK (
(
version = 1
AND state = 'credential_committed'
AND published_at_ms IS NULL
AND publication_digest IS NULL
AND observed_at_ms IS NULL
AND observed_session_id IS NULL
AND observed_session_version IS NULL
AND previous_revoked_at_ms IS NULL
)
OR (
version = 2
AND state = 'published'
AND published_at_ms IS NOT NULL
AND publication_digest IS NOT NULL
AND observed_at_ms IS NULL
AND observed_session_id IS NULL
AND observed_session_version IS NULL
AND previous_revoked_at_ms IS NULL
)
OR (
version = 3
AND state = 'observed'
AND published_at_ms IS NOT NULL
AND publication_digest IS NOT NULL
AND observed_at_ms IS NOT NULL
AND observed_session_id IS NOT NULL
AND observed_session_version BETWEEN 1 AND 2147483647
AND previous_revoked_at_ms IS NULL
)
OR (
version = 4
AND state = 'previous_revoked'
AND previous_credential_id IS NOT NULL
AND published_at_ms IS NOT NULL
AND publication_digest IS NOT NULL
AND observed_at_ms IS NOT NULL
AND observed_session_id IS NOT NULL
AND observed_session_version BETWEEN 1 AND 2147483647
AND previous_revoked_at_ms IS NOT NULL
)
)
)
`.trim(),
`
CREATE INDEX ql3_worker_credential_deliveries_recovery_idx
ON "ql3"."worker_credential_deliveries"
(state, delivery_id, version DESC)
`.trim(),
`
CREATE UNIQUE INDEX ql3_worker_credential_deliveries_credential_uidx
ON "ql3"."worker_credential_deliveries"
(credential_id, credential_version)
WHERE version = 1
`.trim(),
`
CREATE INDEX ql3_worker_credential_deliveries_credential_idx
ON "ql3"."worker_credential_deliveries"
(credential_id, credential_version, delivery_id, version)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 14,
migration_id = 'pg-0015-worker-credential-delivery-ledger',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 13
AND migration_id = 'pg-0014-cluster-scheduler-admission'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 13'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,107 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0016WorkerCredentialStageDiscardLedgerMigration =
definePostgresSqlMigration({
id: 'pg-0016-worker-credential-stage-discard-ledger',
statements: [
`
CREATE TABLE "ql3"."worker_credential_stage_discards" (
delivery_id varchar(36) NOT NULL,
version integer NOT NULL,
state varchar(32) NOT NULL,
worker_id varchar(128) NOT NULL,
credential_id varchar(64) NOT NULL,
credential_version integer NOT NULL,
previous_credential_id varchar(64),
secret_digest char(64) NOT NULL,
token_digest char(64) NOT NULL,
deployment_target_digest char(64) NOT NULL,
deployment_generation varchar(128) NOT NULL,
staged_at_ms bigint NOT NULL,
authorized_at_ms bigint NOT NULL,
discarded_at_ms bigint,
CONSTRAINT worker_credential_stage_discards_pkey
PRIMARY KEY (delivery_id, version),
CONSTRAINT ql3_worker_credential_stage_discards_version_check CHECK (
version BETWEEN 1 AND 2
AND credential_version = 1
),
CONSTRAINT ql3_worker_credential_stage_discards_id_check CHECK (
delivery_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
),
CONSTRAINT ql3_worker_credential_stage_discards_state_check CHECK (
state IN ('discard_authorized', 'discarded')
),
CONSTRAINT ql3_worker_credential_stage_discards_worker_check CHECK (
char_length(worker_id) BETWEEN 1 AND 128
AND worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_worker_credential_stage_discards_credential_check CHECK (
char_length(credential_id) BETWEEN 1 AND 64
AND credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'
AND (
previous_credential_id IS NULL
OR (
char_length(previous_credential_id) BETWEEN 1 AND 64
AND previous_credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$'
AND previous_credential_id <> credential_id
)
)
),
CONSTRAINT ql3_worker_credential_stage_discards_digest_check CHECK (
secret_digest ~ '^[0-9a-f]{64}$'
AND token_digest ~ '^[0-9a-f]{64}$'
AND deployment_target_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_worker_credential_stage_discards_generation_check CHECK (
char_length(deployment_generation) BETWEEN 1 AND 128
AND deployment_generation ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_worker_credential_stage_discards_time_check CHECK (
staged_at_ms >= 0
AND authorized_at_ms >= 0
AND (discarded_at_ms IS NULL OR discarded_at_ms >= authorized_at_ms)
),
CONSTRAINT ql3_worker_credential_stage_discards_state_shape_check CHECK (
(
version = 1
AND state = 'discard_authorized'
AND discarded_at_ms IS NULL
)
OR (
version = 2
AND state = 'discarded'
AND discarded_at_ms IS NOT NULL
)
)
)
`.trim(),
`
CREATE INDEX ql3_worker_credential_stage_discards_recovery_idx
ON "ql3"."worker_credential_stage_discards"
(state, delivery_id, version DESC)
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 15,
migration_id = 'pg-0016-worker-credential-stage-discard-ledger',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 14
AND migration_id = 'pg-0015-worker-credential-delivery-ledger'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 14'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,102 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0017DatabaseRoleGrantsMigration = definePostgresSqlMigration({
id: 'pg-0017-database-role-grants',
statements: [
`
DO $ql3$
DECLARE
invalid_roles text[];
BEGIN
SELECT array_agg(expected.role_name ORDER BY expected.role_name)
INTO invalid_roles
FROM (
VALUES
('ql3_migration'),
('ql3_runtime'),
('ql3_admin'),
('ql3_worker_ingress')
) AS expected(role_name)
LEFT JOIN pg_catalog.pg_roles roles
ON roles.rolname = expected.role_name
WHERE roles.rolname IS NULL
OR roles.rolcanlogin IS NOT TRUE
OR roles.rolsuper IS NOT FALSE
OR roles.rolcreatedb IS NOT FALSE
OR roles.rolcreaterole IS NOT FALSE
OR roles.rolreplication IS NOT FALSE
OR roles.rolbypassrls IS NOT FALSE;
IF invalid_roles IS NOT NULL THEN
RAISE EXCEPTION 'required QingLong database roles are missing or privileged: %',
invalid_roles
USING ERRCODE = 'insufficient_privilege';
END IF;
END
$ql3$
`.trim(),
'REVOKE ALL ON SCHEMA "ql3" FROM PUBLIC',
'REVOKE ALL ON ALL TABLES IN SCHEMA "ql3" FROM PUBLIC',
`
DO $ql3$
BEGIN
EXECUTE format(
'REVOKE CONNECT ON DATABASE %I FROM PUBLIC',
current_database()
);
EXECUTE format(
'GRANT CONNECT ON DATABASE %I TO ql3_migration, ql3_runtime, ql3_admin, ql3_worker_ingress',
current_database()
);
END
$ql3$
`.trim(),
'GRANT USAGE ON SCHEMA "ql3" TO ql3_runtime',
'GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities" TO ql3_runtime',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."runs", "ql3"."run_attempts", "ql3"."worker_sessions", "ql3"."run_dispatch_leases", "ql3"."run_recovery_controls", "ql3"."run_retry_policies" TO ql3_runtime',
'GRANT SELECT, INSERT ON "ql3"."run_events" TO ql3_runtime',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."projects" TO ql3_runtime',
'GRANT SELECT, INSERT ON "ql3"."project_role_bindings" TO ql3_runtime',
'GRANT SELECT ON "ql3"."identity_subjects", "ql3"."api_credentials", "ql3"."worker_execution_attestations", "ql3"."task_definitions", "ql3"."task_definition_revisions", "ql3"."task_execution_revisions", "ql3"."triggers", "ql3"."trigger_revisions" TO ql3_runtime',
'GRANT SELECT, UPDATE ON "ql3"."trigger_schedules" TO ql3_runtime',
'GRANT INSERT ON "ql3"."security_audit_events" TO ql3_runtime',
'GRANT USAGE ON SCHEMA "ql3" TO ql3_admin',
'GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities" TO ql3_admin',
'GRANT SELECT ON "ql3"."projects" TO ql3_admin',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."identity_subjects" TO ql3_admin',
'GRANT SELECT, INSERT ON "ql3"."api_credentials", "ql3"."security_audit_events", "ql3"."identity_subject_mutations", "ql3"."api_credential_mutations" TO ql3_admin',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."worker_credentials" TO ql3_admin',
'GRANT SELECT, INSERT ON "ql3"."worker_credential_mutations" TO ql3_admin',
'GRANT SELECT, INSERT ON "ql3"."worker_credential_deliveries", "ql3"."worker_credential_stage_discards" TO ql3_admin',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."task_definitions", "ql3"."triggers", "ql3"."trigger_schedules" TO ql3_admin',
'GRANT SELECT, INSERT ON "ql3"."task_definition_revisions", "ql3"."task_execution_revisions", "ql3"."trigger_revisions" TO ql3_admin',
'GRANT USAGE ON SCHEMA "ql3" TO ql3_worker_ingress',
'GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities", "ql3"."run_attempts", "ql3"."run_dispatch_leases", "ql3"."worker_credentials" TO ql3_worker_ingress',
'GRANT SELECT, INSERT, UPDATE ON "ql3"."worker_sessions" TO ql3_worker_ingress',
'GRANT SELECT, INSERT ON "ql3"."worker_credential_deliveries" TO ql3_worker_ingress',
'GRANT SELECT, INSERT ON "ql3"."worker_execution_attestations" TO ql3_worker_ingress',
'GRANT INSERT ON "ql3"."security_audit_events" TO ql3_worker_ingress',
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 16,
migration_id = 'pg-0017-database-role-grants',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 15
AND migration_id = 'pg-0016-worker-credential-stage-discard-ledger'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 15'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,212 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0018PluginPackageInstallsMigration = definePostgresSqlMigration({
id: 'pg-0018-plugin-package-installs',
statements: [
`
CREATE TABLE "ql3"."plugin_package_installs" (
installation_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
package_version varchar(128) NOT NULL,
operation varchar(16) NOT NULL,
lock_digest char(64) NOT NULL,
target_generation integer NOT NULL,
previous_active_lock_digest char(64),
active_lock_digest char(64),
state varchar(16) NOT NULL,
version integer NOT NULL,
last_mutation_id varchar(128) NOT NULL,
last_mutation_digest char(64) NOT NULL,
lock_json jsonb NOT NULL,
record_json jsonb NOT NULL,
record_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT ql3_plugin_package_installs_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_installs_identity_check CHECK (
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
AND char_length(package_version) BETWEEN 1 AND 128
AND last_mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
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 (
lock_digest ~ '^[0-9a-f]{64}$'
AND (
previous_active_lock_digest IS NULL
OR previous_active_lock_digest ~ '^[0-9a-f]{64}$'
)
AND (
active_lock_digest IS NULL
OR active_lock_digest ~ '^[0-9a-f]{64}$'
)
AND last_mutation_digest ~ '^[0-9a-f]{64}$'
AND record_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_installs_record_check CHECK (
jsonb_typeof(lock_json) = 'object'
AND octet_length(lock_json::text) BETWEEN 2 AND 262144
AND lock_json @> jsonb_build_object(
'lockDigest', lock_digest,
'projectId', project_id,
'packageName', package_name
)
AND jsonb_typeof(record_json) = 'object'
AND octet_length(record_json::text) BETWEEN 2 AND 262144
AND record_json @> jsonb_build_object(
'installationId', installation_id,
'projectId', project_id,
'packageName', package_name,
'lockDigest', lock_digest,
'state', state,
'version', version,
'recordDigest', record_digest
)
),
CONSTRAINT ql3_plugin_package_installs_time_check CHECK (
created_at_ms >= 0
AND updated_at_ms >= created_at_ms
)
)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_install_heads" (
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
CONSTRAINT plugin_package_install_heads_pkey
PRIMARY KEY (project_id, package_name),
CONSTRAINT ql3_plugin_package_install_heads_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_heads_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_heads_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
AND installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_install_heads_install_uidx
ON "ql3"."plugin_package_install_heads" (installation_id)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_install_mutations" (
installation_id varchar(128) NOT NULL,
mutation_id varchar(128) NOT NULL,
mutation_digest char(64) NOT NULL,
resulting_record_digest char(64) NOT NULL,
occurred_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_install_mutations_pkey
PRIMARY KEY (installation_id, mutation_id),
CONSTRAINT ql3_plugin_package_install_mutations_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_install_mutations_identity_check CHECK (
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_plugin_package_install_mutations_digest_check CHECK (
mutation_digest ~ '^[0-9a-f]{64}$'
AND resulting_record_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_install_mutations_time_check CHECK (
occurred_at_ms >= 0
)
)
`.trim(),
`
CREATE INDEX ql3_plugin_package_installs_recovery_idx
ON "ql3"."plugin_package_installs" (state, package_name, installation_id)
WHERE state IN ('queued', 'staged', 'activating')
`.trim(),
`
CREATE INDEX ql3_plugin_package_installs_project_history_idx
ON "ql3"."plugin_package_installs"
(project_id, package_name, created_at_ms, installation_id)
`.trim(),
`
CREATE INDEX ql3_plugin_package_install_mutations_result_idx
ON "ql3"."plugin_package_install_mutations"
(installation_id, resulting_record_digest)
`.trim(),
`
CREATE FUNCTION "ql3"."lock_active_plugin_package_project"(varchar)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_is_active boolean;
BEGIN
SELECT projects.status = 'active'
INTO project_is_active
FROM "ql3"."projects" AS projects
WHERE projects.id = $1
FOR SHARE;
RETURN COALESCE(project_is_active, false);
END
$ql3$
`.trim(),
`
REVOKE ALL
ON FUNCTION "ql3"."lock_active_plugin_package_project"(varchar)
FROM PUBLIC
`.trim(),
`
GRANT EXECUTE
ON FUNCTION "ql3"."lock_active_plugin_package_project"(varchar)
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."plugin_package_installs", "ql3"."plugin_package_install_heads"
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_install_mutations"
TO ql3_admin
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 17,
migration_id = 'pg-0018-plugin-package-installs',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 16
AND migration_id = 'pg-0017-database-role-grants'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 16'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,253 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0019ApprovedActionsMigration = definePostgresSqlMigration({
id: 'pg-0019-approved-actions',
statements: [
`
CREATE TABLE "ql3"."approval_requests" (
request_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
version integer NOT NULL,
state varchar(16) NOT NULL,
action_type varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
requested_by_type varchar(32) NOT NULL,
requested_by_id varchar(255) NOT NULL,
decision_id varchar(128),
consumption_id varchar(128),
dispatch_id varchar(128),
expires_at_ms bigint NOT NULL,
request_json jsonb NOT NULL,
request_digest char(64) NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT ql3_approval_requests_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approval_requests_identity_check CHECK (
request_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND action_type ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
),
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 (
action_digest ~ '^[0-9a-f]{64}$'
AND preview_digest ~ '^[0-9a-f]{64}$'
AND request_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_approval_requests_subject_check CHECK (
requested_by_type IN
('user','api_app','mcp_client','agent','system','worker')
AND char_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 (
jsonb_typeof(request_json) = 'object'
AND octet_length(request_json::text) BETWEEN 2 AND 65536
AND request_json @> jsonb_build_object(
'id', request_id,
'projectId', project_id,
'version', version,
'state', state,
'action', jsonb_build_object(
'actionType', action_type,
'actionRef', action_ref,
'actionDigest', action_digest,
'previewDigest', preview_digest
)
)
),
CONSTRAINT ql3_approval_requests_time_check CHECK (
expires_at_ms > 0 AND updated_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_approval_requests_decision_uidx
ON "ql3"."approval_requests" (decision_id)
WHERE decision_id IS NOT NULL
`.trim(),
`
CREATE UNIQUE INDEX ql3_approval_requests_consumption_uidx
ON "ql3"."approval_requests" (consumption_id)
WHERE consumption_id IS NOT NULL
`.trim(),
`
CREATE UNIQUE INDEX ql3_approval_requests_dispatch_uidx
ON "ql3"."approval_requests" (dispatch_id)
WHERE dispatch_id IS NOT NULL
`.trim(),
`
CREATE INDEX ql3_approval_requests_pending_idx
ON "ql3"."approval_requests" (expires_at_ms, request_id)
WHERE state = 'pending'
`.trim(),
`
CREATE INDEX ql3_approval_requests_project_idx
ON "ql3"."approval_requests" (project_id, updated_at_ms, request_id)
`.trim(),
`
CREATE TABLE "ql3"."approved_action_dispatches" (
dispatch_id varchar(128) PRIMARY KEY,
approval_request_id varchar(128) NOT NULL,
project_id varchar(128) NOT NULL,
action_type varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
dispatch_json jsonb NOT NULL,
dispatch_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT ql3_approved_action_dispatch_request_fk
FOREIGN KEY (approval_request_id)
REFERENCES "ql3"."approval_requests" (request_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_dispatch_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_dispatch_identity_check CHECK (
dispatch_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND action_type ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
),
CONSTRAINT ql3_approved_action_dispatch_digest_check CHECK (
action_digest ~ '^[0-9a-f]{64}$'
AND preview_digest ~ '^[0-9a-f]{64}$'
AND dispatch_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_approved_action_dispatch_json_check CHECK (
jsonb_typeof(dispatch_json) = 'object'
AND octet_length(dispatch_json::text) BETWEEN 2 AND 65536
AND dispatch_json @> jsonb_build_object(
'id', dispatch_id,
'approvalRequestId', approval_request_id,
'projectId', project_id,
'action', jsonb_build_object(
'actionType', action_type,
'actionRef', action_ref,
'actionDigest', action_digest,
'previewDigest', preview_digest
)
)
),
CONSTRAINT ql3_approved_action_dispatch_time_check CHECK (
created_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_approved_action_dispatch_request_uidx
ON "ql3"."approved_action_dispatches" (approval_request_id)
`.trim(),
`
CREATE INDEX ql3_approved_action_dispatch_project_idx
ON "ql3"."approved_action_dispatches"
(project_id, created_at_ms, dispatch_id)
`.trim(),
`
CREATE FUNCTION "ql3"."lock_approval_policy_fence"(
varchar,
varchar,
varchar,
integer,
integer
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
current_project_version integer;
current_project_status varchar;
current_binding_version integer;
BEGIN
SELECT project.version, project.status
INTO current_project_version, current_project_status
FROM "ql3"."projects" AS project
WHERE project.id = $1
FOR SHARE;
SELECT binding.version
INTO current_binding_version
FROM "ql3"."project_role_bindings" AS binding
WHERE binding.project_id = $1
AND binding.subject_type = $2
AND binding.subject_id = $3
ORDER BY binding.version DESC
LIMIT 1
FOR SHARE;
RETURN current_project_status = 'active'
AND current_project_version = $4
AND current_binding_version IS NOT DISTINCT FROM $5;
END
$ql3$
`.trim(),
`
REVOKE ALL
ON FUNCTION "ql3"."lock_approval_policy_fence"(
varchar, varchar, varchar, integer, integer
)
FROM PUBLIC
`.trim(),
`
GRANT EXECUTE
ON FUNCTION "ql3"."lock_approval_policy_fence"(
varchar, varchar, varchar, integer, integer
)
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."approval_requests"
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."approved_action_dispatches"
TO ql3_admin
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 18,
migration_id = 'pg-0019-approved-actions',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 17
AND migration_id = 'pg-0018-plugin-package-installs'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 17'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,126 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0020PluginPackageAdmissionReceiptsMigration =
definePostgresSqlMigration({
id: 'pg-0020-plugin-package-admission-receipts',
statements: [
`
CREATE TABLE "ql3"."plugin_package_admission_receipts" (
dispatch_id varchar(128) PRIMARY KEY,
dispatch_digest char(64) NOT NULL,
approval_request_id varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(64) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
record_digest char(64) NOT NULL,
mutation_id varchar(128) NOT NULL,
mutation_digest char(64) NOT NULL,
audit_event_id uuid NOT NULL,
admitted_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
receipt_digest char(64) NOT NULL,
CONSTRAINT ql3_plugin_package_admission_dispatch_fk
FOREIGN KEY (dispatch_id)
REFERENCES "ql3"."approved_action_dispatches" (dispatch_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_request_fk
FOREIGN KEY (approval_request_id)
REFERENCES "ql3"."approval_requests" (request_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ql3"."security_audit_events" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_admission_identity_check CHECK (
dispatch_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND approval_request_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
AND project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
AND installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
AND mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_plugin_package_admission_digest_check CHECK (
dispatch_digest ~ '^[0-9a-f]{64}$'
AND lock_digest ~ '^[0-9a-f]{64}$'
AND record_digest ~ '^[0-9a-f]{64}$'
AND mutation_digest ~ '^[0-9a-f]{64}$'
AND receipt_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_admission_json_check CHECK (
jsonb_typeof(receipt_json) = 'object'
AND octet_length(receipt_json::text) BETWEEN 2 AND 65536
AND receipt_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-admission-receipt@v1',
'dispatchId', dispatch_id,
'dispatchDigest', dispatch_digest,
'approvalRequestId', approval_request_id,
'actionRef', action_ref,
'projectId', project_id,
'packageName', package_name,
'installationId', installation_id,
'lockDigest', lock_digest,
'recordDigest', record_digest,
'mutationId', mutation_id,
'mutationDigest', mutation_digest,
'auditEventId', audit_event_id::text,
'admittedAtMs', admitted_at_ms,
'receiptDigest', receipt_digest
)
),
CONSTRAINT ql3_plugin_package_admission_time_check CHECK (
admitted_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_admission_install_uidx
ON "ql3"."plugin_package_admission_receipts" (installation_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_admission_audit_uidx
ON "ql3"."plugin_package_admission_receipts" (audit_event_id)
`.trim(),
`
CREATE INDEX ql3_plugin_package_admission_project_idx
ON "ql3"."plugin_package_admission_receipts"
(project_id, admitted_at_ms, dispatch_id)
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_admission_receipts"
TO ql3_admin
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 19,
migration_id = 'pg-0020-plugin-package-admission-receipts',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 18
AND migration_id = 'pg-0019-approved-actions'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 18'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,205 @@
import { definePostgresSqlMigration } from './sqlMigration';
export const pg0021ApprovedActionExecutionsAndPackageProposalsMigration =
definePostgresSqlMigration({
id: 'pg-0021-approved-action-executions-and-package-proposals',
statements: [
`
CREATE TABLE "ql3"."plugin_package_install_proposals" (
action_ref varchar(255) PRIMARY KEY,
project_id varchar(128) NOT NULL,
action_type varchar(128) NOT NULL,
permission varchar(128) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
proposed_by_type varchar(32) NOT NULL,
proposed_by_id varchar(255) NOT NULL,
fence_project_version integer NOT NULL,
fence_binding_version integer,
created_at_ms bigint NOT NULL,
proposal_json jsonb NOT NULL,
proposal_digest char(64) NOT NULL,
CONSTRAINT ql3_plugin_package_proposal_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_proposal_identity_check CHECK (
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
AND action_type = 'plugin_package.install'
AND permission = 'package.manage'
AND proposed_by_type IN
('user','api_app','mcp_client','agent','system','worker')
AND char_length(proposed_by_id) BETWEEN 1 AND 255
),
CONSTRAINT ql3_plugin_package_proposal_digest_check CHECK (
action_digest ~ '^[0-9a-f]{64}$'
AND preview_digest ~ '^[0-9a-f]{64}$'
AND proposal_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_proposal_json_check CHECK (
jsonb_typeof(proposal_json) = 'object'
AND octet_length(proposal_json::text) BETWEEN 2 AND 262144
AND proposal_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-install-proposal@v1',
'actionRef', action_ref,
'projectId', project_id,
'actionType', action_type,
'permission', permission,
'actionDigest', action_digest,
'previewDigest', preview_digest,
'proposedBy', jsonb_build_object(
'type', proposed_by_type,
'id', proposed_by_id
),
'proposalFence', jsonb_build_object(
'projectVersion', fence_project_version,
'bindingVersion', fence_binding_version
),
'createdAtMs', created_at_ms,
'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
)
)
`.trim(),
`
CREATE INDEX ql3_plugin_package_proposal_project_idx
ON "ql3"."plugin_package_install_proposals"
(project_id, created_at_ms, action_ref)
`.trim(),
`
CREATE TABLE "ql3"."approved_action_executions" (
dispatch_id varchar(128) PRIMARY KEY,
dispatch_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
status varchar(16) NOT NULL,
version integer NOT NULL,
attempt_count integer NOT NULL,
max_attempts integer NOT NULL,
eligible_at_ms bigint,
next_attempt_at_ms bigint,
lease_owner varchar(128),
lease_token varchar(128),
lease_expires_at_ms bigint,
started_at_ms bigint,
result_mutation_id varchar(128),
result_code varchar(64),
result_digest char(64),
completed_at_ms bigint,
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
execution_json jsonb NOT NULL,
execution_digest char(64) NOT NULL,
CONSTRAINT ql3_approved_action_execution_dispatch_fk
FOREIGN KEY (dispatch_id)
REFERENCES "ql3"."approved_action_dispatches" (dispatch_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_approved_action_execution_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (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 (
char_length(lease_owner) BETWEEN 1 AND 128
AND char_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 (
char_length(result_mutation_id) BETWEEN 1 AND 128
AND char_length(result_code) BETWEEN 1 AND 64
)
),
CONSTRAINT ql3_approved_action_execution_digest_check CHECK (
dispatch_digest ~ '^[0-9a-f]{64}$'
AND (result_digest IS NULL OR result_digest ~ '^[0-9a-f]{64}$')
AND execution_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_approved_action_execution_json_check CHECK (
jsonb_typeof(execution_json) = 'object'
AND octet_length(execution_json::text) BETWEEN 2 AND 65536
AND execution_json @> jsonb_build_object(
'schema', 'qinglong/approved-action-execution@v1',
'dispatchId', dispatch_id,
'dispatchDigest', dispatch_digest,
'projectId', project_id,
'status', status,
'version', version,
'attemptCount', attempt_count,
'maxAttempts', max_attempts,
'executionDigest', execution_digest
)
),
CONSTRAINT ql3_approved_action_execution_time_check CHECK (
created_at_ms >= 0 AND updated_at_ms >= created_at_ms
)
)
`.trim(),
`
CREATE INDEX ql3_approved_action_execution_due_idx
ON "ql3"."approved_action_executions" (eligible_at_ms, dispatch_id)
WHERE status IN ('pending','leased','retry_wait')
`.trim(),
`
CREATE INDEX ql3_approved_action_execution_recovery_idx
ON "ql3"."approved_action_executions" (lease_expires_at_ms, dispatch_id)
WHERE status = 'executing'
`.trim(),
`
CREATE INDEX ql3_approved_action_execution_project_idx
ON "ql3"."approved_action_executions"
(project_id, updated_at_ms, dispatch_id)
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_install_proposals"
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."approved_action_executions"
TO ql3_admin
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 20,
migration_id =
'pg-0021-approved-action-executions-and-package-proposals',
capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_install":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 19
AND migration_id = 'pg-0020-plugin-package-admission-receipts'
AND capabilities = '{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_install":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 19'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,163 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V20 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_install":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V21 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_install":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0022PluginPackageAuthoritySplitMigration =
definePostgresSqlMigration({
id: 'pg-0022-plugin-package-authority-split',
statements: [
`
DO $ql3$
DECLARE
invalid_roles text[];
BEGIN
SELECT array_agg(expected.role_name ORDER BY expected.role_name)
INTO invalid_roles
FROM (
VALUES
('ql3_package_manager'),
('ql3_package_executor')
) AS expected(role_name)
LEFT JOIN pg_catalog.pg_roles roles
ON roles.rolname = expected.role_name
WHERE roles.rolname IS NULL
OR roles.rolcanlogin IS NOT TRUE
OR roles.rolsuper IS NOT FALSE
OR roles.rolcreatedb IS NOT FALSE
OR roles.rolcreaterole IS NOT FALSE
OR roles.rolreplication IS NOT FALSE
OR roles.rolbypassrls IS NOT FALSE;
IF invalid_roles IS NOT NULL THEN
RAISE EXCEPTION
'required QingLong Package database roles are missing or privileged: %',
invalid_roles
USING ERRCODE = 'insufficient_privilege';
END IF;
END
$ql3$
`.trim(),
`
DO $ql3$
BEGIN
EXECUTE format(
'GRANT CONNECT ON DATABASE %I TO ql3_package_manager, ql3_package_executor',
current_database()
);
END
$ql3$
`.trim(),
'GRANT USAGE ON SCHEMA "ql3" TO ql3_package_manager, ql3_package_executor',
'GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities" TO ql3_package_manager, ql3_package_executor',
`
REVOKE ALL
ON "ql3"."plugin_package_install_proposals",
"ql3"."approval_requests",
"ql3"."approved_action_dispatches",
"ql3"."approved_action_executions",
"ql3"."plugin_package_installs",
"ql3"."plugin_package_install_heads",
"ql3"."plugin_package_install_mutations",
"ql3"."plugin_package_admission_receipts"
FROM ql3_admin
`.trim(),
`
REVOKE EXECUTE
ON FUNCTION "ql3"."lock_approval_policy_fence"(
varchar, varchar, varchar, integer, integer
)
FROM ql3_admin
`.trim(),
`
REVOKE EXECUTE
ON FUNCTION "ql3"."lock_active_plugin_package_project"(varchar)
FROM ql3_admin
`.trim(),
`
GRANT SELECT
ON "ql3"."projects", "ql3"."project_role_bindings"
TO ql3_package_manager, ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."security_audit_events"
TO ql3_package_manager, ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_install_proposals"
TO ql3_package_manager
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."approval_requests"
TO ql3_package_manager
`.trim(),
`
GRANT EXECUTE
ON FUNCTION "ql3"."lock_approval_policy_fence"(
varchar, varchar, varchar, integer, integer
)
TO ql3_package_manager, ql3_package_executor
`.trim(),
`
GRANT SELECT
ON "ql3"."plugin_package_install_proposals"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, UPDATE
ON "ql3"."approval_requests"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."approved_action_dispatches"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."approved_action_executions",
"ql3"."plugin_package_installs",
"ql3"."plugin_package_install_heads"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_install_mutations",
"ql3"."plugin_package_admission_receipts"
TO ql3_package_executor
`.trim(),
`
GRANT EXECUTE
ON FUNCTION "ql3"."lock_active_plugin_package_project"(varchar)
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 21,
migration_id = 'pg-0022-plugin-package-authority-split',
capabilities = '${CAPABILITIES_V21}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 20
AND migration_id =
'pg-0021-approved-action-executions-and-package-proposals'
AND capabilities = '${CAPABILITIES_V20}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 20'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,89 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V21 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_install":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V22 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0023PluginPackageManagementQuotaMigration =
definePostgresSqlMigration({
id: 'pg-0023-plugin-package-management-quota',
statements: [
`
CREATE TABLE "ql3"."plugin_package_management_quota_buckets" (
project_id varchar(128) NOT NULL,
subject_type varchar(32) NOT NULL,
subject_id varchar(255) NOT NULL,
operation varchar(64) NOT NULL,
window_started_at_ms bigint NOT NULL,
consumed_count integer NOT NULL,
receipt_ids jsonb NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_management_quota_buckets_pkey
PRIMARY KEY (project_id, subject_type, subject_id, operation),
CONSTRAINT ql3_plugin_package_management_quota_project_fk
FOREIGN KEY (project_id)
REFERENCES "ql3"."projects"(id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_management_quota_identity_check
CHECK (
subject_type = 'user'
AND char_length(subject_id) BETWEEN 1 AND 255
AND subject_id !~ '[[:cntrl:]]'
),
CONSTRAINT ql3_plugin_package_management_quota_operation_check
CHECK (
operation IN (
'plugin-package.propose',
'plugin-package.decide',
'plugin-package.inspect'
)
),
CONSTRAINT ql3_plugin_package_management_quota_window_check
CHECK (
window_started_at_ms >= 0
AND consumed_count BETWEEN 1 AND 1000
AND updated_at_ms >= window_started_at_ms
),
CONSTRAINT ql3_plugin_package_management_quota_receipts_check
CHECK (
jsonb_typeof(receipt_ids) = 'array'
AND jsonb_array_length(receipt_ids) = consumed_count
AND octet_length(receipt_ids::text) BETWEEN 3 AND 262144
)
)
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_management_quota_buckets"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."plugin_package_management_quota_buckets"
TO ql3_package_manager
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 22,
migration_id = 'pg-0023-plugin-package-management-quota',
capabilities = '${CAPABILITIES_V22}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 21
AND migration_id = 'pg-0022-plugin-package-authority-split'
AND capabilities = '${CAPABILITIES_V21}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 21'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,81 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V22 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V23 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0024PluginPackageIdentityKeysetLedgerMigration =
definePostgresSqlMigration({
id: 'pg-0024-plugin-package-identity-keyset-ledger',
statements: [
`
CREATE TABLE "ql3"."plugin_package_identity_keyset_ledger" (
authority varchar(64) NOT NULL,
generation bigint NOT NULL,
digest varchar(43) NOT NULL,
issuer varchar(512) NOT NULL,
audience varchar(256) NOT NULL,
active_key_ids jsonb NOT NULL,
revoked_key_ids jsonb NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_identity_keyset_ledger_pkey
PRIMARY KEY (authority),
CONSTRAINT ql3_plugin_package_identity_keyset_authority_check
CHECK (authority = 'plugin-package-management'),
CONSTRAINT ql3_plugin_package_identity_keyset_generation_check
CHECK (generation >= 1 AND updated_at_ms >= 0),
CONSTRAINT ql3_plugin_package_identity_keyset_digest_check
CHECK (digest ~ '^[A-Za-z0-9_-]{43}$'),
CONSTRAINT ql3_plugin_package_identity_keyset_trust_domain_check
CHECK (
char_length(issuer) BETWEEN 1 AND 512
AND issuer !~ '[[:cntrl:]]'
AND char_length(audience) BETWEEN 1 AND 256
AND audience !~ '[[:cntrl:]]'
),
CONSTRAINT ql3_plugin_package_identity_keyset_keys_check
CHECK (
jsonb_typeof(active_key_ids) = 'array'
AND jsonb_array_length(active_key_ids) BETWEEN 1 AND 8
AND octet_length(active_key_ids::text) BETWEEN 3 AND 8192
AND jsonb_typeof(revoked_key_ids) = 'array'
AND jsonb_array_length(revoked_key_ids) BETWEEN 0 AND 64
AND octet_length(revoked_key_ids::text) BETWEEN 2 AND 16384
)
)
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_identity_keyset_ledger"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."plugin_package_identity_keyset_ledger"
TO ql3_package_manager
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 23,
migration_id = 'pg-0024-plugin-package-identity-keyset-ledger',
capabilities = '${CAPABILITIES_V23}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 22
AND migration_id = 'pg-0023-plugin-package-management-quota'
AND capabilities = '${CAPABILITIES_V22}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 22'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,103 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V23 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V24 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0025PluginPackageMaterializedRevisionsMigration =
definePostgresSqlMigration({
id: 'pg-0025-plugin-package-materialized-revisions',
statements: [
`
CREATE TABLE "ql3"."plugin_package_materialized_revisions" (
generation_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
generation integer NOT NULL,
lock_digest char(64) NOT NULL,
manifest_digest char(64) NOT NULL,
revision_digest char(64) NOT NULL,
revision_json jsonb NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_materialized_revisions_pkey
PRIMARY KEY (generation_digest),
CONSTRAINT ql3_plugin_package_materialized_revision_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_materialized_revision_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_materialized_revision_digest_check CHECK (
generation_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
manifest_digest ~ '^[0-9a-f]{64}$' AND
revision_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_materialized_revision_json_check CHECK (
jsonb_typeof(revision_json) = 'object' AND
octet_length(revision_json::text) BETWEEN 2 AND 25165824 AND
revision_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-materialized-revision@v1',
'generation', jsonb_build_object(
'generationDigest', generation_digest,
'projectId', project_id,
'packageName', package_name,
'generation', generation,
'lockDigest', lock_digest
),
'manifestDigest', manifest_digest,
'revisionDigest', revision_digest
)
),
CONSTRAINT ql3_plugin_package_materialized_revision_time_check CHECK (
created_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_materialized_revision_generation_uidx
ON "ql3"."plugin_package_materialized_revisions"
(project_id, package_name, generation)
`.trim(),
`
CREATE INDEX ql3_plugin_package_materialized_revision_lock_idx
ON "ql3"."plugin_package_materialized_revisions"
(lock_digest, generation_digest)
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_materialized_revisions"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_materialized_revisions"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 24,
migration_id = 'pg-0025-plugin-package-materialized-revisions',
capabilities = '${CAPABILITIES_V24}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 23
AND migration_id = 'pg-0024-plugin-package-identity-keyset-ledger'
AND capabilities = '${CAPABILITIES_V23}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 23'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,622 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V24 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V25 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0026PluginPackageTaskReconciliationsMigration =
definePostgresSqlMigration({
id: 'pg-0026-plugin-package-task-reconciliations',
statements: [
`
CREATE TABLE "ql3"."plugin_package_task_ownerships" (
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
claimed_generation_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_task_ownerships_pkey
PRIMARY KEY (project_id, task_id),
CONSTRAINT ql3_plugin_package_task_ownership_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_ownership_task_fk
FOREIGN KEY (project_id, task_id)
REFERENCES "ql3"."task_definitions" (project_id, task_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_ownership_identity_check CHECK (
char_length(task_id) BETWEEN 1 AND 128 AND
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
),
CONSTRAINT ql3_plugin_package_task_ownership_digest_check CHECK (
claimed_generation_digest ~ '^[0-9a-f]{64}$'
),
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
)
)
`.trim(),
`
CREATE INDEX ql3_plugin_package_task_ownership_package_idx
ON "ql3"."plugin_package_task_ownerships"
(project_id, package_name, task_id)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_task_reconciliations" (
generation_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
generation integer NOT NULL,
materialized_revision_digest char(64) NOT NULL,
lock_digest char(64) NOT NULL,
previous_lock_digest char(64),
receipt_digest char(64) NOT NULL,
receipt_json jsonb NOT NULL,
committed_at_ms bigint NOT NULL,
CONSTRAINT plugin_package_task_reconciliations_pkey
PRIMARY KEY (generation_digest),
CONSTRAINT ql3_plugin_package_task_reconciliation_materialized_fk
FOREIGN KEY (generation_digest)
REFERENCES "ql3"."plugin_package_materialized_revisions"
(generation_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_reconciliation_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_task_reconciliation_digest_check CHECK (
generation_digest ~ '^[0-9a-f]{64}$' AND
materialized_revision_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
(previous_lock_digest IS NULL OR
previous_lock_digest ~ '^[0-9a-f]{64}$') AND
receipt_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_task_reconciliation_json_check CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 8388608 AND
receipt_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-task-reconciliation@v1',
'generationDigest', generation_digest,
'projectId', project_id,
'packageName', package_name,
'generation', generation,
'materializedRevisionDigest', materialized_revision_digest,
'lockDigest', lock_digest,
'receiptDigest', receipt_digest
)
),
CONSTRAINT ql3_plugin_package_task_reconciliation_time_check CHECK (
committed_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_task_reconciliation_generation_uidx
ON "ql3"."plugin_package_task_reconciliations"
(project_id, package_name, generation)
`.trim(),
`
CREATE INDEX ql3_plugin_package_task_reconciliation_lock_idx
ON "ql3"."plugin_package_task_reconciliations"
(lock_digest, generation_digest)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_task_reconciliation_items" (
generation_digest char(64) NOT NULL,
task_id varchar(128) NOT NULL,
revision integer NOT NULL,
disposition varchar(24) NOT NULL,
content_digest char(64) NOT NULL,
CONSTRAINT plugin_package_task_reconciliation_items_pkey
PRIMARY KEY (generation_digest, task_id),
CONSTRAINT ql3_plugin_package_task_reconciliation_item_reconciliation_fk
FOREIGN KEY (generation_digest)
REFERENCES "ql3"."plugin_package_task_reconciliations"
(generation_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_task_reconciliation_item_identity_check CHECK (
char_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 (
content_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`
CREATE INDEX ql3_plugin_package_task_reconciliation_item_task_idx
ON "ql3"."plugin_package_task_reconciliation_items"
(task_id, generation_digest)
`.trim(),
`
CREATE FUNCTION "ql3"."commit_plugin_package_task_reconciliation"(
p_generation_digest char(64),
p_materialized_revision_digest char(64),
p_receipt jsonb,
p_writes jsonb,
p_execution_revisions jsonb
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
materialized "ql3"."plugin_package_materialized_revisions"%ROWTYPE;
install_record "ql3"."plugin_package_installs"%ROWTYPE;
previous_receipt jsonb;
expected_ids text[];
receipt_ids text[];
write_ids text[];
execution_ids text[];
task_id_value text;
item jsonb;
write_value jsonb;
definition jsonb;
execution_value jsonb;
resource_value jsonb;
current_head "ql3"."task_definitions"%ROWTYPE;
current_revision "ql3"."task_definition_revisions"%ROWTYPE;
owner_package varchar(63);
now_ms bigint;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_package_executor', 'member') THEN
RAISE EXCEPTION 'Package Task reconciliation authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
IF p_generation_digest !~ '^[0-9a-f]{64}$'
OR p_materialized_revision_digest !~ '^[0-9a-f]{64}$'
OR jsonb_typeof(p_receipt) <> 'object'
OR jsonb_typeof(p_writes) <> 'array'
OR jsonb_typeof(p_execution_revisions) <> 'array'
OR jsonb_array_length(p_writes) > 512
OR jsonb_array_length(p_execution_revisions) > 512 THEN
RAISE EXCEPTION 'invalid Package Task reconciliation input'
USING ERRCODE = 'check_violation';
END IF;
SELECT * INTO materialized
FROM "ql3"."plugin_package_materialized_revisions"
WHERE generation_digest = p_generation_digest
FOR KEY SHARE;
IF NOT FOUND
OR materialized.revision_digest <> p_materialized_revision_digest THEN
RAISE EXCEPTION 'materialized revision fence changed'
USING ERRCODE = 'serialization_failure';
END IF;
SELECT install.* INTO install_record
FROM "ql3"."plugin_package_install_heads" AS head
JOIN "ql3"."plugin_package_installs" AS install
ON install.installation_id = head.installation_id
WHERE head.project_id = materialized.project_id
AND head.package_name = materialized.package_name
FOR UPDATE OF install;
IF NOT FOUND
OR install_record.state <> 'active'
OR install_record.installation_id <>
materialized.revision_json #>> '{generation,installationId}'
OR install_record.target_generation <> materialized.generation
OR install_record.lock_digest <> materialized.lock_digest
OR install_record.previous_active_lock_digest IS DISTINCT FROM
NULLIF(materialized.revision_json #>> '{generation,previousActiveLockDigest}', '')
THEN
RAISE EXCEPTION 'active Package install fence changed'
USING ERRCODE = 'serialization_failure';
END IF;
IF EXISTS (
SELECT 1 FROM "ql3"."plugin_package_task_reconciliations"
WHERE generation_digest = p_generation_digest
AND receipt_json = p_receipt
) THEN
RETURN false;
ELSIF EXISTS (
SELECT 1 FROM "ql3"."plugin_package_task_reconciliations"
WHERE generation_digest = p_generation_digest
) THEN
RAISE EXCEPTION 'generation receipt identity is already bound'
USING ERRCODE = 'unique_violation';
END IF;
IF materialized.generation = 1 THEN
IF materialized.revision_json #>> '{generation,previousActiveLockDigest}'
IS NOT NULL THEN
RAISE EXCEPTION 'first generation has a previous lock'
USING ERRCODE = 'check_violation';
END IF;
previous_receipt := NULL;
ELSE
SELECT receipt_json INTO previous_receipt
FROM "ql3"."plugin_package_task_reconciliations"
WHERE project_id = materialized.project_id
AND package_name = materialized.package_name
AND generation = materialized.generation - 1
FOR KEY SHARE;
IF NOT FOUND
OR previous_receipt ->> 'lockDigest' <>
materialized.revision_json #>>
'{generation,previousActiveLockDigest}' THEN
RAISE EXCEPTION 'previous generation receipt is missing'
USING ERRCODE = 'serialization_failure';
END IF;
END IF;
IF p_receipt ->> 'schema' <>
'qinglong/plugin-package-task-reconciliation@v1'
OR p_receipt ->> 'generationDigest' <> p_generation_digest
OR p_receipt ->> 'materializedRevisionDigest' <>
p_materialized_revision_digest
OR p_receipt ->> 'projectId' <> materialized.project_id
OR p_receipt ->> 'packageName' <> materialized.package_name
OR (p_receipt ->> 'generation')::integer <> materialized.generation
OR p_receipt ->> 'lockDigest' <> materialized.lock_digest
OR jsonb_typeof(p_receipt -> 'items') <> 'array'
OR jsonb_array_length(p_receipt -> 'items') > 512 THEN
RAISE EXCEPTION 'receipt does not match materialized generation'
USING ERRCODE = 'check_violation';
END IF;
SELECT array_agg(value ORDER BY value) INTO expected_ids
FROM (
SELECT 'pkg:' || materialized.package_name || ':' ||
(resource_json -> 'value' ->> 'id') AS value
FROM jsonb_array_elements(materialized.revision_json -> 'resources')
AS resources(resource_json)
WHERE resource_json ->> 'kind' = 'task'
UNION
SELECT previous_item_json ->> 'taskId'
FROM jsonb_array_elements(COALESCE(previous_receipt -> 'items', '[]'::jsonb))
AS previous_items(previous_item_json)
) AS expected;
expected_ids := COALESCE(expected_ids, ARRAY[]::text[]);
SELECT array_agg(value ORDER BY value), count(DISTINCT value)
INTO receipt_ids, now_ms
FROM (
SELECT receipt_item_json ->> 'taskId' AS value
FROM jsonb_array_elements(p_receipt -> 'items')
AS receipt_items(receipt_item_json)
) AS receipt_values;
receipt_ids := COALESCE(receipt_ids, ARRAY[]::text[]);
IF receipt_ids <> expected_ids
OR now_ms <> cardinality(receipt_ids) THEN
RAISE EXCEPTION 'receipt does not exactly cover the generation task set'
USING ERRCODE = 'check_violation';
END IF;
SELECT array_agg(value ORDER BY value), count(DISTINCT value)
INTO write_ids, now_ms
FROM (
SELECT write_entry_json -> 'definition' ->> 'taskId' AS value
FROM jsonb_array_elements(p_writes) AS writes(write_entry_json)
) AS write_values;
write_ids := COALESCE(write_ids, ARRAY[]::text[]);
IF now_ms <> cardinality(write_ids)
OR NOT write_ids <@ expected_ids THEN
RAISE EXCEPTION 'writes are duplicated or outside the generation task set'
USING ERRCODE = 'check_violation';
END IF;
SELECT array_agg(value ORDER BY value), count(DISTINCT value)
INTO execution_ids, now_ms
FROM (
SELECT execution_entry_json ->> 'taskId' AS value
FROM jsonb_array_elements(p_execution_revisions)
AS executions(execution_entry_json)
) AS execution_values;
execution_ids := COALESCE(execution_ids, ARRAY[]::text[]);
IF now_ms <> cardinality(execution_ids)
OR NOT execution_ids <@ write_ids THEN
RAISE EXCEPTION 'execution revisions are duplicated or unbound'
USING ERRCODE = 'check_violation';
END IF;
FOREACH task_id_value IN ARRAY expected_ids LOOP
SELECT receipt_item_json INTO item
FROM jsonb_array_elements(p_receipt -> 'items')
AS receipt_items(receipt_item_json)
WHERE receipt_item_json ->> 'taskId' = task_id_value;
SELECT write_entry_json INTO write_value
FROM jsonb_array_elements(p_writes) AS writes(write_entry_json)
WHERE write_entry_json -> 'definition' ->> 'taskId' = task_id_value;
definition := write_value -> 'definition';
SELECT resource_json -> 'value' INTO resource_value
FROM jsonb_array_elements(materialized.revision_json -> 'resources')
AS resources(resource_json)
WHERE resource_json ->> 'kind' = 'task'
AND 'pkg:' || materialized.package_name || ':' ||
(resource_json -> 'value' ->> 'id') = task_id_value;
SELECT * INTO current_head
FROM "ql3"."task_definitions"
WHERE project_id = materialized.project_id AND task_id = task_id_value
FOR UPDATE;
IF FOUND THEN
SELECT * INTO current_revision
FROM "ql3"."task_definition_revisions"
WHERE project_id = current_head.project_id
AND task_id = current_head.task_id
AND revision = current_head.current_revision;
SELECT package_name INTO owner_package
FROM "ql3"."plugin_package_task_ownerships"
WHERE project_id = current_head.project_id
AND task_id = current_head.task_id;
IF owner_package IS DISTINCT FROM materialized.package_name THEN
RAISE EXCEPTION 'TaskDefinition ownership collision'
USING ERRCODE = 'unique_violation';
END IF;
ELSE
current_revision := NULL;
owner_package := NULL;
END IF;
IF item ->> 'disposition' IN ('created','updated','disabled') THEN
IF write_value IS NULL
OR item ->> 'contentDigest' <> definition ->> 'contentDigest'
OR (item ->> 'revision')::integer <>
(definition ->> 'revision')::integer
OR write_value -> 'command' ->> 'projectId' <>
materialized.project_id
OR write_value -> 'command' ->> 'taskId' <> task_id_value
OR write_value -> 'command' ->> 'mutationId' <>
definition ->> 'mutationId' THEN
RAISE EXCEPTION 'receipt write binding is invalid'
USING ERRCODE = 'check_violation';
END IF;
ELSIF write_value IS NOT NULL THEN
RAISE EXCEPTION 'non-mutating receipt item has a write'
USING ERRCODE = 'check_violation';
END IF;
IF resource_value IS NOT NULL THEN
IF item ->> 'disposition' NOT IN ('created','retained','updated') THEN
RAISE EXCEPTION 'active materialized Task has an invalid disposition'
USING ERRCODE = 'check_violation';
END IF;
IF write_value IS NOT NULL AND (
definition ->> 'projectId' <> materialized.project_id OR
definition ->> 'taskId' <> task_id_value OR
definition ->> 'name' <> resource_value ->> 'name' OR
definition -> 'description' IS DISTINCT FROM
resource_value -> 'description' OR
definition ->> 'kind' <> resource_value ->> 'kind' OR
definition -> 'spec' IS DISTINCT FROM resource_value -> 'spec' OR
definition -> 'labels' IS DISTINCT FROM resource_value -> 'labels' OR
definition -> 'enabled' IS DISTINCT FROM resource_value -> 'enabled'
) THEN
RAISE EXCEPTION 'Task write differs from materialized resource'
USING ERRCODE = 'check_violation';
END IF;
ELSE
IF item ->> 'disposition' NOT IN ('already_disabled','disabled') THEN
RAISE EXCEPTION 'removed Task has an invalid disposition'
USING ERRCODE = 'check_violation';
END IF;
IF item ->> 'disposition' = 'disabled' AND (
current_revision IS NULL OR
definition ->> 'name' <> current_revision.name OR
definition -> 'description' IS DISTINCT FROM
to_jsonb(current_revision.description) OR
definition ->> 'kind' <> current_revision.kind OR
definition -> 'spec' IS DISTINCT FROM current_revision.spec_json OR
definition -> 'labels' IS DISTINCT FROM current_revision.labels_json OR
definition -> 'enabled' <> 'false'
) THEN
RAISE EXCEPTION 'removed Task disable write is invalid'
USING ERRCODE = 'check_violation';
END IF;
END IF;
IF write_value IS NULL THEN
IF current_revision IS NULL
OR (item ->> 'revision')::integer <> current_revision.revision
OR item ->> 'contentDigest' <> current_revision.content_digest THEN
RAISE EXCEPTION 'retained Task head changed'
USING ERRCODE = 'serialization_failure';
END IF;
ELSIF current_revision IS NULL THEN
IF item ->> 'disposition' <> 'created'
OR write_value -> 'command' -> 'expectedRevision' <> 'null'::jsonb
OR (definition ->> 'revision')::integer <> 1 THEN
RAISE EXCEPTION 'Task create CAS is invalid'
USING ERRCODE = 'serialization_failure';
END IF;
ELSIF item ->> 'disposition' = 'created'
OR (write_value -> 'command' ->> 'expectedRevision')::integer <>
current_revision.revision
OR (definition ->> 'revision')::integer <>
current_revision.revision + 1 THEN
RAISE EXCEPTION 'Task update CAS is invalid'
USING ERRCODE = 'serialization_failure';
END IF;
execution_value := NULL;
SELECT execution_entry_json INTO execution_value
FROM jsonb_array_elements(p_execution_revisions)
AS executions(execution_entry_json)
WHERE execution_entry_json ->> 'taskId' = task_id_value;
IF write_value IS NOT NULL
AND definition -> 'enabled' = 'true'::jsonb
AND definition ->> 'kind' = 'command'
AND definition #>> '{spec,schema}' = 'qinglong/command@v1' THEN
IF execution_value IS NULL
OR (execution_value ->> 'sourceRevision')::integer <>
(definition ->> 'revision')::integer
OR execution_value ->> 'sourceContentDigest' <>
definition ->> 'contentDigest' THEN
RAISE EXCEPTION 'required execution revision is missing'
USING ERRCODE = 'check_violation';
END IF;
ELSIF execution_value IS NOT NULL THEN
RAISE EXCEPTION 'unexpected execution revision'
USING ERRCODE = 'check_violation';
END IF;
END LOOP;
now_ms := floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint;
FOREACH task_id_value IN ARRAY write_ids LOOP
SELECT write_entry_json INTO write_value
FROM jsonb_array_elements(p_writes) AS writes(write_entry_json)
WHERE write_entry_json -> 'definition' ->> 'taskId' = task_id_value;
definition := write_value -> 'definition';
IF write_value -> 'command' -> 'expectedRevision' = 'null'::jsonb THEN
INSERT INTO "ql3"."task_definitions" (
project_id, task_id, current_revision, created_at_ms, updated_at_ms
) VALUES (
definition ->> 'projectId', definition ->> 'taskId', 1,
(definition ->> 'createdAtMs')::bigint,
(definition ->> 'updatedAtMs')::bigint
);
INSERT INTO "ql3"."plugin_package_task_ownerships" (
project_id, task_id, package_name,
claimed_generation_digest, created_at_ms
) VALUES (
materialized.project_id, task_id_value, materialized.package_name,
p_generation_digest, now_ms
);
END IF;
INSERT INTO "ql3"."task_definition_revisions" (
project_id, task_id, revision, mutation_id, name, description, kind,
spec_json, labels_json, enabled, content_digest, created_at_ms
) VALUES (
definition ->> 'projectId', definition ->> 'taskId',
(definition ->> 'revision')::integer,
(definition ->> 'mutationId')::uuid,
definition ->> 'name', definition ->> 'description',
definition ->> 'kind', definition -> 'spec', definition -> 'labels',
(definition ->> 'enabled')::boolean, definition ->> 'contentDigest',
(definition ->> 'updatedAtMs')::bigint
);
SELECT execution_entry_json INTO execution_value
FROM jsonb_array_elements(p_execution_revisions)
AS executions(execution_entry_json)
WHERE execution_entry_json ->> 'taskId' = task_id_value;
IF execution_value IS NOT NULL THEN
INSERT INTO "ql3"."task_execution_revisions" (
project_id, task_id, source_revision, task_revision,
source_content_digest, executor_type, plan_schema, plan_json,
content_digest, created_at_ms
) VALUES (
execution_value ->> 'projectId', execution_value ->> 'taskId',
(execution_value ->> 'sourceRevision')::integer,
execution_value ->> 'taskRevision',
execution_value ->> 'sourceContentDigest',
execution_value ->> 'executorType',
execution_value ->> 'planSchema',
execution_value -> 'planJson',
execution_value ->> 'contentDigest',
(execution_value ->> 'createdAtMs')::bigint
);
END IF;
IF write_value -> 'command' -> 'expectedRevision' <> 'null'::jsonb THEN
UPDATE "ql3"."task_definitions" AS task_head
SET current_revision = (definition ->> 'revision')::integer,
updated_at_ms = (definition ->> 'updatedAtMs')::bigint
WHERE task_head.project_id = materialized.project_id
AND task_head.task_id = task_id_value
AND task_head.current_revision =
(write_value -> 'command' ->> 'expectedRevision')::integer;
IF NOT FOUND THEN
RAISE EXCEPTION 'Task head changed while committing'
USING ERRCODE = 'serialization_failure';
END IF;
END IF;
END LOOP;
INSERT INTO "ql3"."plugin_package_task_reconciliations" (
generation_digest, project_id, package_name, generation,
materialized_revision_digest, lock_digest, previous_lock_digest,
receipt_digest, receipt_json, committed_at_ms
) VALUES (
p_generation_digest, materialized.project_id, materialized.package_name,
materialized.generation, p_materialized_revision_digest,
materialized.lock_digest,
NULLIF(p_receipt ->> 'previousLockDigest', ''),
p_receipt ->> 'receiptDigest', p_receipt,
(p_receipt ->> 'committedAtMs')::bigint
);
INSERT INTO "ql3"."plugin_package_task_reconciliation_items" (
generation_digest, task_id, revision, disposition, content_digest
)
SELECT p_generation_digest, receipt_item_json ->> 'taskId',
(receipt_item_json ->> 'revision')::integer,
receipt_item_json ->> 'disposition',
receipt_item_json ->> 'contentDigest'
FROM jsonb_array_elements(p_receipt -> 'items')
AS receipt_items(receipt_item_json);
RETURN true;
END
$ql3$
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_task_ownerships",
"ql3"."plugin_package_task_reconciliations",
"ql3"."plugin_package_task_reconciliation_items"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT
ON "ql3"."plugin_package_task_ownerships"
TO ql3_admin, ql3_package_executor
`.trim(),
`
GRANT SELECT
ON "ql3"."plugin_package_task_reconciliations",
"ql3"."plugin_package_task_reconciliation_items",
"ql3"."task_definitions",
"ql3"."task_definition_revisions",
"ql3"."task_execution_revisions"
TO ql3_package_executor
`.trim(),
`
REVOKE ALL
ON FUNCTION "ql3"."commit_plugin_package_task_reconciliation"(
char(64), char(64), jsonb, jsonb, jsonb
)
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_worker_ingress
`.trim(),
`
GRANT EXECUTE
ON FUNCTION "ql3"."commit_plugin_package_task_reconciliation"(
char(64), char(64), jsonb, jsonb, jsonb
)
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 25,
migration_id = 'pg-0026-plugin-package-task-reconciliations',
capabilities = '${CAPABILITIES_V25}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 24
AND migration_id = 'pg-0025-plugin-package-materialized-revisions'
AND capabilities = '${CAPABILITIES_V24}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 24'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,163 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V25 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V26 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0027ProjectToolDefinitionSnapshotsMigration =
definePostgresSqlMigration({
id: 'pg-0027-project-tool-definition-snapshots',
statements: [
`
CREATE UNIQUE INDEX ql3_plugin_package_installs_snapshot_source_uidx
ON "ql3"."plugin_package_installs"
(project_id, package_name, installation_id, target_generation, lock_digest)
`.trim(),
`
CREATE UNIQUE INDEX ql3_plugin_package_materialized_revision_snapshot_source_uidx
ON "ql3"."plugin_package_materialized_revisions"
(project_id, package_name, generation, generation_digest,
lock_digest, revision_digest)
`.trim(),
`
CREATE TABLE "ql3"."project_tool_definition_snapshots" (
project_id varchar(128) NOT NULL,
active_vector_digest char(64) NOT NULL,
definitions_digest char(64) NOT NULL,
snapshot_digest char(64) NOT NULL,
snapshot_json jsonb NOT NULL,
committed_at_ms bigint NOT NULL,
CONSTRAINT project_tool_definition_snapshots_pkey
PRIMARY KEY (project_id, active_vector_digest),
CONSTRAINT ql3_project_tool_definition_snapshot_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_identity_check CHECK (
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_project_tool_definition_snapshot_digest_check CHECK (
active_vector_digest ~ '^[0-9a-f]{64}$' AND
definitions_digest ~ '^[0-9a-f]{64}$' AND
snapshot_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_project_tool_definition_snapshot_json_check CHECK (
jsonb_typeof(snapshot_json) = 'object' AND
octet_length(snapshot_json::text) BETWEEN 2 AND 8388608 AND
snapshot_json @> jsonb_build_object(
'schema', 'qinglong/project-tool-definition-snapshot@v1',
'projectId', project_id,
'activeVectorDigest', active_vector_digest,
'definitionsDigest', definitions_digest,
'snapshotDigest', snapshot_digest
)
),
CONSTRAINT ql3_project_tool_definition_snapshot_time_check CHECK (
committed_at_ms >= 0
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_project_tool_definition_snapshot_digest_uidx
ON "ql3"."project_tool_definition_snapshots" (snapshot_digest)
`.trim(),
`
CREATE INDEX ql3_project_tool_definition_snapshot_current_idx
ON "ql3"."project_tool_definition_snapshots"
(project_id, committed_at_ms DESC, active_vector_digest)
`.trim(),
`
CREATE TABLE "ql3"."project_tool_definition_snapshot_sources" (
project_id varchar(128) NOT NULL,
active_vector_digest char(64) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
generation integer NOT NULL,
generation_digest char(64) NOT NULL,
lock_digest char(64) NOT NULL,
revision_digest char(64) NOT NULL,
CONSTRAINT project_tool_definition_snapshot_sources_pkey
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 "ql3"."project_tool_definition_snapshots"
(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 "ql3"."plugin_package_installs" (
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 "ql3"."plugin_package_materialized_revisions" (
project_id, package_name, generation, generation_digest,
lock_digest, revision_digest
)
ON DELETE RESTRICT,
CONSTRAINT ql3_project_tool_definition_snapshot_source_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_project_tool_definition_snapshot_source_digest_check CHECK (
active_vector_digest ~ '^[0-9a-f]{64}$' AND
generation_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
revision_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`
CREATE INDEX ql3_project_tool_definition_snapshot_source_generation_idx
ON "ql3"."project_tool_definition_snapshot_sources"
(generation_digest, project_id, package_name)
`.trim(),
`
CREATE INDEX ql3_project_tool_definition_snapshot_source_install_idx
ON "ql3"."project_tool_definition_snapshot_sources"
(installation_id, active_vector_digest)
`.trim(),
`
REVOKE ALL
ON "ql3"."project_tool_definition_snapshots",
"ql3"."project_tool_definition_snapshot_sources"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."project_tool_definition_snapshots",
"ql3"."project_tool_definition_snapshot_sources"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 26,
migration_id = 'pg-0027-project-tool-definition-snapshots',
capabilities = '${CAPABILITIES_V26}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 25
AND migration_id = 'pg-0026-plugin-package-task-reconciliations'
AND capabilities = '${CAPABILITIES_V25}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 25'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,299 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V26 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V27 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0028StepRunsMigration = definePostgresSqlMigration({
id: 'pg-0028-step-runs',
statements: [
`
DO $ql3$
BEGIN
IF EXISTS (
SELECT 1 FROM "ql3"."run_attempts" WHERE step_run_id IS NOT NULL
UNION ALL
SELECT 1 FROM "ql3"."run_events" WHERE step_run_id IS NOT NULL
) THEN
RAISE EXCEPTION
'legacy step_run_id cannot be upgraded without StepRun authority'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
`
ALTER TABLE "ql3"."run_attempts"
ALTER COLUMN step_run_id TYPE varchar(128)
`.trim(),
`
ALTER TABLE "ql3"."run_events"
ALTER COLUMN step_run_id TYPE varchar(128)
`.trim(),
`
CREATE TABLE "ql3"."step_runs" (
id varchar(128) PRIMARY KEY,
run_id varchar(36) NOT NULL,
parent_step_run_id varchar(128),
step_key varchar(128) NOT NULL,
kind varchar(32) NOT NULL,
definition_ref varchar(512) NOT NULL,
definition_digest char(64) NOT NULL,
required boolean NOT NULL,
status varchar(32) NOT NULL,
version integer NOT NULL,
attempt_count integer NOT NULL,
input_ref varchar(512),
output_ref varchar(512),
approval_request_id varchar(128),
ready_at_ms bigint,
started_at_ms bigint,
finished_at_ms bigint,
result_code varchar(64),
error_summary varchar(2048),
created_at_ms bigint NOT NULL,
updated_at_ms bigint NOT NULL,
last_mutation_id varchar(128) NOT NULL,
step_run_digest char(64) NOT NULL,
step_run_json jsonb NOT NULL,
CONSTRAINT ql3_step_runs_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."runs" (id) ON DELETE CASCADE,
CONSTRAINT ql3_step_runs_identity_check CHECK (
id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
(parent_step_run_id IS NULL OR
(parent_step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
parent_step_run_id <> id)) AND
step_key ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
octet_length(definition_ref) 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 (
definition_digest ~ '^[0-9a-f]{64}$' AND
step_run_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_step_runs_counter_check CHECK (
version BETWEEN 1 AND 2147483647 AND
attempt_count BETWEEN 0 AND 64
),
CONSTRAINT ql3_step_runs_reference_check CHECK (
(input_ref IS NULL OR octet_length(input_ref) BETWEEN 1 AND 512) AND
(output_ref IS NULL OR octet_length(output_ref) BETWEEN 1 AND 512) AND
(approval_request_id IS NULL OR
approval_request_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$')
),
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_approval_shape_check CHECK (
status <> 'waiting_approval' OR approval_request_id IS NOT NULL
),
CONSTRAINT ql3_step_runs_result_shape_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 result_code ~ '^[a-z][a-z0-9_]{0,63}$') AND
(error_summary IS NULL OR octet_length(error_summary) BETWEEN 1 AND 2048)
),
CONSTRAINT ql3_step_runs_mutation_identity_check CHECK (
last_mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_step_runs_json_check CHECK (
jsonb_typeof(step_run_json) = 'object' AND
octet_length(step_run_json::text) BETWEEN 2 AND 16384 AND
step_run_json @> jsonb_build_object(
'schema', 'qinglong/step-run@v1',
'id', id,
'runId', run_id,
'parentStepRunId', parent_step_run_id,
'stepKey', step_key,
'kind', kind,
'definitionRef', definition_ref,
'definitionDigest', definition_digest,
'required', required,
'status', status,
'version', version,
'attemptCount', attempt_count,
'inputRef', input_ref,
'outputRef', output_ref,
'approvalRequestId', approval_request_id,
'readyAtMs', ready_at_ms,
'startedAtMs', started_at_ms,
'finishedAtMs', finished_at_ms,
'resultCode', result_code,
'errorSummary', error_summary,
'createdAtMs', created_at_ms,
'updatedAtMs', updated_at_ms,
'lastMutationId', last_mutation_id,
'stepRunDigest', step_run_digest
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_step_runs_run_id_uidx
ON "ql3"."step_runs" (run_id, id)
`.trim(),
`
ALTER TABLE "ql3"."step_runs"
ADD CONSTRAINT ql3_step_runs_parent_fk
FOREIGN KEY (run_id, parent_step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id)
ON DELETE RESTRICT
`.trim(),
`
CREATE UNIQUE INDEX ql3_step_runs_run_step_uidx
ON "ql3"."step_runs" (run_id, step_key)
`.trim(),
`
CREATE INDEX ql3_step_runs_run_status_idx
ON "ql3"."step_runs" (run_id, status, id)
`.trim(),
`
CREATE INDEX ql3_step_runs_recovery_idx
ON "ql3"."step_runs" (status, updated_at_ms, id)
WHERE status IN ('waiting_approval', 'running', 'lost')
`.trim(),
`
CREATE TABLE "ql3"."step_run_mutations" (
mutation_id varchar(128) PRIMARY KEY,
mutation_digest char(64) NOT NULL,
run_id varchar(36) NOT NULL,
step_run_id varchar(128) NOT NULL,
step_run_digest char(64) NOT NULL,
event_id varchar(36) NOT NULL,
event_sequence integer NOT NULL,
run_version integer NOT NULL,
step_run_json jsonb NOT NULL,
committed_at_ms bigint NOT NULL,
CONSTRAINT ql3_step_run_mutations_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_step_run_mutations_event_fk
FOREIGN KEY (event_id) REFERENCES "ql3"."run_events" (id)
ON DELETE CASCADE,
CONSTRAINT ql3_step_run_mutations_identity_check CHECK (
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_step_run_mutations_digest_check CHECK (
mutation_digest ~ '^[0-9a-f]{64}$' AND
step_run_digest ~ '^[0-9a-f]{64}$'
),
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 (
jsonb_typeof(step_run_json) = 'object' AND
octet_length(step_run_json::text) BETWEEN 2 AND 16384 AND
step_run_json @> jsonb_build_object(
'schema', 'qinglong/step-run@v1',
'id', step_run_id,
'runId', run_id,
'lastMutationId', mutation_id,
'stepRunDigest', step_run_digest
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_step_run_mutations_event_uidx
ON "ql3"."step_run_mutations" (event_id)
`.trim(),
`
CREATE INDEX ql3_step_run_mutations_step_idx
ON "ql3"."step_run_mutations"
(run_id, step_run_id, event_sequence, mutation_id)
`.trim(),
`
ALTER TABLE "ql3"."run_attempts"
ADD CONSTRAINT ql3_run_attempts_step_run_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id)
ON DELETE RESTRICT
`.trim(),
`
ALTER TABLE "ql3"."run_events"
ADD CONSTRAINT ql3_run_events_step_run_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id)
ON DELETE RESTRICT
`.trim(),
`
REVOKE ALL
ON "ql3"."step_runs", "ql3"."step_run_mutations"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT, UPDATE
ON "ql3"."step_runs"
TO ql3_runtime
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."step_run_mutations"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 27,
migration_id = 'pg-0028-step-runs',
capabilities = '${CAPABILITIES_V27}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 26
AND migration_id = 'pg-0027-project-tool-definition-snapshots'
AND capabilities = '${CAPABILITIES_V26}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 26'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,213 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V27 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V28 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0029ToolExecutionEvidenceMigration =
definePostgresSqlMigration({
id: 'pg-0029-tool-execution-evidence',
statements: [
`
CREATE TABLE "ql3"."tool_execution_trace_anchors" (
trace_id char(32) NOT NULL,
span_id char(16) NOT NULL,
parent_span_id char(16),
project_id varchar(128) NOT NULL,
run_id varchar(36) NOT NULL,
step_run_id varchar(128) NOT NULL,
invocation_plan_digest char(64) NOT NULL,
binding_digest char(64) NOT NULL,
adapter_digest char(64) NOT NULL,
redaction_contract_digest char(64) NOT NULL,
audit_contract_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
trace_digest char(64) NOT NULL,
trace_json jsonb 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 "ql3"."step_runs" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_trace_identity_check CHECK (
trace_id ~ '^[0-9a-f]{32}$' AND
span_id ~ '^[0-9a-f]{16}$' AND
(parent_span_id IS NULL OR (
parent_span_id ~ '^[0-9a-f]{16}$' AND parent_span_id <> span_id
)) AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_tool_execution_trace_digest_check CHECK (
invocation_plan_digest ~ '^[0-9a-f]{64}$' AND
binding_digest ~ '^[0-9a-f]{64}$' AND
adapter_digest ~ '^[0-9a-f]{64}$' AND
redaction_contract_digest ~ '^[0-9a-f]{64}$' AND
audit_contract_digest ~ '^[0-9a-f]{64}$' AND
trace_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_execution_trace_time_check CHECK (
created_at_ms >= 0
),
CONSTRAINT ql3_tool_execution_trace_json_check CHECK (
jsonb_typeof(trace_json) = 'object' AND
octet_length(trace_json::text) BETWEEN 2 AND 16384 AND
trace_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-trace-anchor@v1',
'traceId', trace_id,
'spanId', span_id,
'parentSpanId', parent_span_id,
'projectId', project_id,
'runId', run_id,
'stepRunId', step_run_id,
'invocationPlanDigest', invocation_plan_digest,
'bindingDigest', binding_digest,
'adapterDigest', adapter_digest,
'redactionContractDigest', redaction_contract_digest,
'auditContractDigest', audit_contract_digest,
'createdAtMs', created_at_ms,
'traceDigest', trace_digest
)
)
)
`.trim(),
`
CREATE INDEX ql3_tool_execution_trace_run_idx
ON "ql3"."tool_execution_trace_anchors"
(run_id, created_at_ms, trace_id, span_id)
`.trim(),
`
CREATE INDEX ql3_tool_execution_trace_step_idx
ON "ql3"."tool_execution_trace_anchors"
(run_id, step_run_id, created_at_ms, trace_id, span_id)
`.trim(),
`
CREATE TABLE "ql3"."tool_execution_audit_receipts" (
event_id uuid PRIMARY KEY,
project_id varchar(128) NOT NULL,
run_id varchar(36) NOT NULL,
step_run_id varchar(128) NOT NULL,
trace_id char(32) NOT NULL,
span_id char(16) NOT NULL,
trace_digest char(64) NOT NULL,
invocation_plan_digest char(64) NOT NULL,
binding_digest char(64) NOT NULL,
audit_record_digest char(64) NOT NULL,
created_at_ms bigint NOT NULL,
receipt_digest char(64) NOT NULL,
audit_json jsonb NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT ql3_tool_execution_audit_event_fk
FOREIGN KEY (event_id)
REFERENCES "ql3"."security_audit_events" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_execution_audit_trace_fk
FOREIGN KEY (trace_id, span_id)
REFERENCES "ql3"."tool_execution_trace_anchors" (trace_id, span_id)
ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_audit_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id) ON DELETE CASCADE,
CONSTRAINT ql3_tool_execution_audit_identity_check CHECK (
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
trace_id ~ '^[0-9a-f]{32}$' AND
span_id ~ '^[0-9a-f]{16}$'
),
CONSTRAINT ql3_tool_execution_audit_digest_check CHECK (
trace_digest ~ '^[0-9a-f]{64}$' AND
invocation_plan_digest ~ '^[0-9a-f]{64}$' AND
binding_digest ~ '^[0-9a-f]{64}$' AND
audit_record_digest ~ '^[0-9a-f]{64}$' AND
receipt_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_execution_audit_time_check CHECK (
created_at_ms >= 0
),
CONSTRAINT ql3_tool_execution_audit_json_check CHECK (
jsonb_typeof(audit_json) = 'object' AND
octet_length(audit_json::text) BETWEEN 2 AND 8192 AND
audit_json @> jsonb_build_object(
'eventId', event_id,
'projectId', project_id,
'operationId', 'tool.invoke.start',
'outcome', 'allowed',
'occurredAtMs', created_at_ms
) AND
jsonb_typeof(audit_json -> 'fence') = 'object'
),
CONSTRAINT ql3_tool_execution_audit_receipt_json_check CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 16384 AND
receipt_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-audit-receipt@v1',
'eventId', event_id,
'projectId', project_id,
'runId', run_id,
'stepRunId', step_run_id,
'traceId', trace_id,
'spanId', span_id,
'traceDigest', trace_digest,
'invocationPlanDigest', invocation_plan_digest,
'bindingDigest', binding_digest,
'auditRecordDigest', audit_record_digest,
'createdAtMs', created_at_ms,
'receiptDigest', receipt_digest
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_execution_audit_trace_uidx
ON "ql3"."tool_execution_audit_receipts" (trace_id, span_id)
`.trim(),
`
CREATE INDEX ql3_tool_execution_audit_run_idx
ON "ql3"."tool_execution_audit_receipts"
(run_id, created_at_ms, trace_id, span_id)
`.trim(),
`
CREATE INDEX ql3_tool_execution_audit_step_idx
ON "ql3"."tool_execution_audit_receipts"
(run_id, step_run_id, created_at_ms, event_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_execution_trace_anchors",
"ql3"."tool_execution_audit_receipts"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_trace_anchors",
"ql3"."tool_execution_audit_receipts"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 28,
migration_id = 'pg-0029-tool-execution-evidence',
capabilities = '${CAPABILITIES_V28}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 27
AND migration_id = 'pg-0028-step-runs'
AND capabilities = '${CAPABILITIES_V27}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 27'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,145 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V28 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V29 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0030ToolExecutionStartBarriersMigration =
definePostgresSqlMigration({
id: 'pg-0030-tool-execution-start-barriers',
statements: [
`
CREATE TABLE "ql3"."tool_execution_start_barriers" (
start_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
run_id varchar(36) NOT NULL,
step_run_id varchar(128) NOT NULL,
started_step_run_version integer NOT NULL,
step_run_mutation_id varchar(128) NOT NULL,
run_event_id varchar(128) NOT NULL,
trace_id char(32) NOT NULL,
span_id char(16) NOT NULL,
audit_event_id uuid NOT NULL,
command_digest char(64) NOT NULL,
barrier_digest char(64) NOT NULL,
started_at_ms bigint NOT NULL,
barrier_json jsonb NOT NULL,
CONSTRAINT ql3_tool_start_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "ql3"."step_run_mutations" (mutation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "ql3"."run_events" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_trace_fk
FOREIGN KEY (trace_id, span_id)
REFERENCES "ql3"."tool_execution_trace_anchors" (trace_id, span_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_audit_fk
FOREIGN KEY (audit_event_id)
REFERENCES "ql3"."tool_execution_audit_receipts" (event_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_start_identity_check CHECK (
start_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_event_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
trace_id ~ '^[0-9a-f]{32}$' AND span_id ~ '^[0-9a-f]{16}$'
),
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 (
command_digest ~ '^[0-9a-f]{64}$' AND
barrier_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_start_json_check CHECK (
jsonb_typeof(barrier_json) = 'object' AND
octet_length(barrier_json::text) BETWEEN 2 AND 16384 AND
barrier_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-start-barrier@v1',
'startId', start_id,
'projectId', project_id,
'runId', run_id,
'stepRunId', step_run_id,
'startedStepRunVersion', started_step_run_version,
'stepRunMutationId', step_run_mutation_id,
'runEventId', run_event_id,
'traceId', trace_id,
'spanId', span_id,
'auditEventId', audit_event_id,
'commandDigest', command_digest,
'barrierDigest', barrier_digest,
'startedAtMs', started_at_ms
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_start_step_version_uidx
ON "ql3"."tool_execution_start_barriers"
(run_id, step_run_id, started_step_run_version)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_start_mutation_uidx
ON "ql3"."tool_execution_start_barriers" (step_run_mutation_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_start_event_uidx
ON "ql3"."tool_execution_start_barriers" (run_event_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_start_trace_uidx
ON "ql3"."tool_execution_start_barriers" (trace_id, span_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_start_audit_uidx
ON "ql3"."tool_execution_start_barriers" (audit_event_id)
`.trim(),
`
CREATE INDEX ql3_tool_start_run_time_idx
ON "ql3"."tool_execution_start_barriers"
(run_id, started_at_ms, start_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_execution_start_barriers"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_start_barriers"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 29,
migration_id = 'pg-0030-tool-execution-start-barriers',
capabilities = '${CAPABILITIES_V29}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 28
AND migration_id = 'pg-0029-tool-execution-evidence'
AND capabilities = '${CAPABILITIES_V28}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 28'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,167 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V29 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V30 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0031ToolInvocationArtifactsMigration =
definePostgresSqlMigration({
id: 'pg-0031-tool-invocation-artifacts',
statements: [
`
CREATE TABLE "ql3"."tool_invocation_input_artifacts" (
artifact_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
input_digest char(64) NOT NULL,
invocation_action_digest char(64) NOT NULL,
artifact_digest char(64) NOT NULL,
key_id varchar(128) NOT NULL,
algorithm varchar(32) NOT NULL,
plaintext_bytes integer NOT NULL,
sealed_at_ms bigint NOT NULL,
artifact_json jsonb NOT NULL,
CONSTRAINT ql3_tool_input_artifact_project_fk
FOREIGN KEY (project_id)
REFERENCES "ql3"."projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_input_artifact_identity_check CHECK (
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
algorithm = 'aes-256-gcm'
),
CONSTRAINT ql3_tool_input_artifact_digest_check CHECK (
input_digest ~ '^[0-9a-f]{64}$' AND
invocation_action_digest ~ '^[0-9a-f]{64}$' AND
artifact_digest ~ '^[0-9a-f]{64}$'
),
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 (
jsonb_typeof(artifact_json) = 'object' AND
octet_length(artifact_json::text) BETWEEN 2 AND 98304 AND
artifact_json @> jsonb_build_object(
'schema', 'qinglong/tool-invocation-input-artifact@v1',
'artifactId', artifact_id,
'projectId', project_id,
'actionRef', action_ref,
'inputDigest', input_digest,
'invocationActionDigest', invocation_action_digest,
'artifactDigest', artifact_digest,
'keyId', key_id,
'algorithm', algorithm,
'plaintextBytes', plaintext_bytes,
'sealedAtMs', sealed_at_ms
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_input_artifact_action_uidx
ON "ql3"."tool_invocation_input_artifacts" (project_id, action_ref)
`.trim(),
`
CREATE INDEX ql3_tool_input_artifact_project_time_idx
ON "ql3"."tool_invocation_input_artifacts"
(project_id, sealed_at_ms, artifact_id)
`.trim(),
`
CREATE TABLE "ql3"."tool_invocation_preview_artifacts" (
artifact_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
redaction_contract_digest char(64) NOT NULL,
artifact_digest char(64) NOT NULL,
byte_length integer NOT NULL,
sealed_at_ms bigint NOT NULL,
artifact_json jsonb NOT NULL,
CONSTRAINT ql3_tool_preview_artifact_project_fk
FOREIGN KEY (project_id)
REFERENCES "ql3"."projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_tool_preview_artifact_identity_check CHECK (
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
),
CONSTRAINT ql3_tool_preview_artifact_digest_check CHECK (
action_digest ~ '^[0-9a-f]{64}$' AND
preview_digest ~ '^[0-9a-f]{64}$' AND
redaction_contract_digest ~ '^[0-9a-f]{64}$' AND
artifact_digest ~ '^[0-9a-f]{64}$'
),
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 (
jsonb_typeof(artifact_json) = 'object' AND
octet_length(artifact_json::text) BETWEEN 2 AND 16384 AND
artifact_json @> jsonb_build_object(
'schema', 'qinglong/tool-invocation-preview-artifact@v1',
'artifactId', artifact_id,
'projectId', project_id,
'actionRef', action_ref,
'actionDigest', action_digest,
'previewDigest', preview_digest,
'redactionContractDigest', redaction_contract_digest,
'artifactDigest', artifact_digest,
'byteLength', byte_length,
'sealedAtMs', sealed_at_ms
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_preview_artifact_action_uidx
ON "ql3"."tool_invocation_preview_artifacts" (project_id, action_ref)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_preview_artifact_action_digest_uidx
ON "ql3"."tool_invocation_preview_artifacts" (action_digest)
`.trim(),
`
CREATE INDEX ql3_tool_preview_artifact_project_time_idx
ON "ql3"."tool_invocation_preview_artifacts"
(project_id, sealed_at_ms, artifact_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_invocation_input_artifacts",
"ql3"."tool_invocation_preview_artifacts"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_invocation_input_artifacts",
"ql3"."tool_invocation_preview_artifacts"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 30,
migration_id = 'pg-0031-tool-invocation-artifacts',
capabilities = '${CAPABILITIES_V30}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 29
AND migration_id = 'pg-0030-tool-execution-start-barriers'
AND capabilities = '${CAPABILITIES_V29}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 29'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,122 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V30 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V31 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0032ToolExecutionArtifactBindingsMigration =
definePostgresSqlMigration({
id: 'pg-0032-tool-execution-artifact-bindings',
statements: [
`
CREATE UNIQUE INDEX ql3_tool_input_artifact_start_binding_uidx
ON "ql3"."tool_invocation_input_artifacts" (
artifact_id, artifact_digest, project_id, action_ref, input_digest
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_preview_artifact_start_binding_uidx
ON "ql3"."tool_invocation_preview_artifacts" (
artifact_id, artifact_digest, project_id, action_ref, action_digest,
preview_digest, redaction_contract_digest
)
`.trim(),
`
CREATE TABLE "ql3"."tool_execution_start_artifact_bindings" (
start_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
action_ref varchar(255) NOT NULL,
input_artifact_id varchar(128) NOT NULL,
input_artifact_digest char(64) NOT NULL,
input_digest char(64) NOT NULL,
preview_artifact_id varchar(128) NOT NULL,
preview_artifact_digest char(64) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
redaction_contract_digest char(64) NOT NULL,
bound_at_ms bigint NOT NULL,
CONSTRAINT ql3_tool_start_artifact_barrier_fk
FOREIGN KEY (start_id)
REFERENCES "ql3"."tool_execution_start_barriers" (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 "ql3"."tool_invocation_input_artifacts" (
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 "ql3"."tool_invocation_preview_artifacts" (
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 (
start_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
input_artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
preview_artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_tool_start_artifact_digest_check CHECK (
input_artifact_digest ~ '^[0-9a-f]{64}$' AND
input_digest ~ '^[0-9a-f]{64}$' AND
preview_artifact_digest ~ '^[0-9a-f]{64}$' AND
action_digest ~ '^[0-9a-f]{64}$' AND
preview_digest ~ '^[0-9a-f]{64}$' AND
redaction_contract_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_start_artifact_time_check CHECK (bound_at_ms >= 0)
)
`.trim(),
`
CREATE INDEX ql3_tool_start_artifact_input_idx
ON "ql3"."tool_execution_start_artifact_bindings"
(input_artifact_id, start_id)
`.trim(),
`
CREATE INDEX ql3_tool_start_artifact_preview_idx
ON "ql3"."tool_execution_start_artifact_bindings"
(preview_artifact_id, start_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_execution_start_artifact_bindings"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_start_artifact_bindings"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 31,
migration_id = 'pg-0032-tool-execution-artifact-bindings',
capabilities = '${CAPABILITIES_V31}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 30
AND migration_id = 'pg-0031-tool-invocation-artifacts'
AND capabilities = '${CAPABILITIES_V30}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 30'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,187 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V31 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V32 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0033ToolExecutionCompletionsMigration =
definePostgresSqlMigration({
id: 'pg-0033-tool-execution-completions',
statements: [
`
CREATE TABLE "ql3"."tool_execution_completions" (
start_id varchar(128) PRIMARY KEY,
artifact_id varchar(128) NOT NULL,
project_id varchar(128) NOT NULL,
run_id varchar(128) NOT NULL,
step_run_id varchar(128) NOT NULL,
started_step_run_version integer NOT NULL,
completed_step_run_version integer NOT NULL,
barrier_digest char(64) NOT NULL,
adapter_digest char(64) NOT NULL,
output_digest char(64) NOT NULL,
execution_result_digest char(64) NOT NULL,
artifact_digest char(64) NOT NULL,
key_id varchar(128) NOT NULL,
algorithm varchar(32) NOT NULL,
plaintext_bytes integer NOT NULL,
step_run_mutation_id varchar(128) NOT NULL,
step_run_mutation_digest char(64) NOT NULL,
completed_step_run_digest char(64) NOT NULL,
run_event_id varchar(128) NOT NULL,
completed_at_ms bigint NOT NULL,
completion_digest char(64) NOT NULL,
artifact_json jsonb NOT NULL,
completion_json jsonb NOT NULL,
CONSTRAINT ql3_tool_completion_start_fk
FOREIGN KEY (start_id)
REFERENCES "ql3"."tool_execution_start_barriers" (start_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "ql3"."step_run_mutations" (mutation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "ql3"."run_events" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_completion_identity_check CHECK (
start_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
step_run_mutation_id ~
'^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_event_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
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 (
barrier_digest ~ '^[0-9a-f]{64}$' AND
adapter_digest ~ '^[0-9a-f]{64}$' AND
output_digest ~ '^[0-9a-f]{64}$' AND
execution_result_digest ~ '^[0-9a-f]{64}$' AND
artifact_digest ~ '^[0-9a-f]{64}$' AND
step_run_mutation_digest ~ '^[0-9a-f]{64}$' AND
completed_step_run_digest ~ '^[0-9a-f]{64}$' AND
completion_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_completion_budget_check CHECK (
algorithm = 'aes-256-gcm' AND
plaintext_bytes BETWEEN 0 AND 262144 AND
completed_at_ms >= 0 AND
octet_length(artifact_json::text) BETWEEN 2 AND 393216 AND
octet_length(completion_json::text) BETWEEN 2 AND 24576
),
CONSTRAINT ql3_tool_completion_json_check CHECK (
jsonb_typeof(artifact_json) = 'object' AND
artifact_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-result-artifact@v1',
'artifactId', artifact_id,
'projectId', project_id,
'startId', start_id,
'runId', run_id,
'stepRunId', step_run_id,
'barrierDigest', barrier_digest,
'adapterDigest', adapter_digest,
'outputDigest', output_digest,
'executionResultDigest', execution_result_digest,
'artifactDigest', artifact_digest,
'keyId', key_id,
'algorithm', algorithm,
'plaintextBytes', plaintext_bytes,
'sealedAtMs', completed_at_ms
) AND
jsonb_typeof(completion_json) = 'object' AND
completion_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-completion@v1',
'startId', start_id,
'projectId', project_id,
'runId', run_id,
'stepRunId', step_run_id,
'startedStepRunVersion', started_step_run_version,
'completedStepRunVersion', completed_step_run_version,
'barrierDigest', barrier_digest,
'adapterDigest', adapter_digest,
'resultArtifact', jsonb_build_object(
'artifactId', artifact_id,
'artifactDigest', artifact_digest,
'outputDigest', output_digest,
'executionResultDigest', execution_result_digest
),
'stepRunMutationId', step_run_mutation_id,
'stepRunMutationDigest', step_run_mutation_digest,
'completedStepRunDigest', completed_step_run_digest,
'runEventId', run_event_id,
'completedAtMs', completed_at_ms,
'completionDigest', completion_digest
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_completion_artifact_uidx
ON "ql3"."tool_execution_completions" (artifact_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_completion_mutation_uidx
ON "ql3"."tool_execution_completions" (step_run_mutation_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_completion_event_uidx
ON "ql3"."tool_execution_completions" (run_event_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_completion_step_version_uidx
ON "ql3"."tool_execution_completions"
(run_id, step_run_id, completed_step_run_version)
`.trim(),
`
CREATE INDEX ql3_tool_completion_project_time_idx
ON "ql3"."tool_execution_completions"
(project_id, completed_at_ms, start_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_execution_completions"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_completions"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 32,
migration_id = 'pg-0033-tool-execution-completions',
capabilities = '${CAPABILITIES_V32}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 31
AND migration_id = 'pg-0032-tool-execution-artifact-bindings'
AND capabilities = '${CAPABILITIES_V31}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 31'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,160 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V32 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V33 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0034ToolExecutionFailureCompletionsMigration =
definePostgresSqlMigration({
id: 'pg-0034-tool-execution-failure-completions',
statements: [
`
CREATE TABLE "ql3"."tool_execution_failure_completions" (
start_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
run_id varchar(128) NOT NULL,
step_run_id varchar(128) NOT NULL,
started_step_run_version integer NOT NULL,
completed_step_run_version integer NOT NULL,
barrier_digest char(64) NOT NULL,
adapter_digest char(64) NOT NULL,
outcome varchar(16) NOT NULL,
result_code varchar(64) NOT NULL,
error_summary varchar(128) NOT NULL,
step_run_mutation_id varchar(128) NOT NULL,
step_run_mutation_digest char(64) NOT NULL,
completed_step_run_digest char(64) NOT NULL,
run_event_id varchar(128) NOT NULL,
completed_at_ms bigint NOT NULL,
completion_digest char(64) NOT NULL,
completion_json jsonb NOT NULL,
CONSTRAINT ql3_tool_failure_completion_start_fk
FOREIGN KEY (start_id)
REFERENCES "ql3"."tool_execution_start_barriers" (start_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_mutation_fk
FOREIGN KEY (step_run_mutation_id)
REFERENCES "ql3"."step_run_mutations" (mutation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_event_fk
FOREIGN KEY (run_event_id)
REFERENCES "ql3"."run_events" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_failure_completion_identity_check CHECK (
start_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
step_run_mutation_id ~
'^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_event_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
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 (
barrier_digest ~ '^[0-9a-f]{64}$' AND
adapter_digest ~ '^[0-9a-f]{64}$' AND
step_run_mutation_digest ~ '^[0-9a-f]{64}$' AND
completed_step_run_digest ~ '^[0-9a-f]{64}$' AND
completion_digest ~ '^[0-9a-f]{64}$'
),
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
octet_length(completion_json::text) BETWEEN 2 AND 24576
),
CONSTRAINT ql3_tool_failure_completion_json_check CHECK (
jsonb_typeof(completion_json) = 'object' AND
completion_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-failure-completion@v1',
'startId', start_id,
'projectId', project_id,
'runId', run_id,
'stepRunId', step_run_id,
'startedStepRunVersion', started_step_run_version,
'completedStepRunVersion', completed_step_run_version,
'barrierDigest', barrier_digest,
'adapterDigest', adapter_digest,
'outcome', outcome,
'resultCode', result_code,
'errorSummary', error_summary,
'stepRunMutationId', step_run_mutation_id,
'stepRunMutationDigest', step_run_mutation_digest,
'completedStepRunDigest', completed_step_run_digest,
'runEventId', run_event_id,
'completedAtMs', completed_at_ms,
'completionDigest', completion_digest
)
)
)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_failure_completion_mutation_uidx
ON "ql3"."tool_execution_failure_completions" (step_run_mutation_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_failure_completion_event_uidx
ON "ql3"."tool_execution_failure_completions" (run_event_id)
`.trim(),
`
CREATE UNIQUE INDEX ql3_tool_failure_completion_step_version_uidx
ON "ql3"."tool_execution_failure_completions"
(run_id, step_run_id, completed_step_run_version)
`.trim(),
`
CREATE INDEX ql3_tool_failure_completion_project_time_idx
ON "ql3"."tool_execution_failure_completions"
(project_id, completed_at_ms, start_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_execution_failure_completions"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_failure_completions"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 33,
migration_id = 'pg-0034-tool-execution-failure-completions',
capabilities = '${CAPABILITIES_V33}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 32
AND migration_id = 'pg-0033-tool-execution-completions'
AND capabilities = '${CAPABILITIES_V32}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 32'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,195 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V33 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V34 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0035ToolResultKeyCatalogMigration = definePostgresSqlMigration({
id: 'pg-0035-tool-result-key-catalog',
statements: [
`
CREATE TABLE "ql3"."tool_result_key_catalog_generations" (
authority varchar(64) NOT NULL,
generation integer NOT NULL,
previous_generation integer,
previous_catalog_digest char(64),
active_key_id varchar(128),
mutation_kind varchar(16) NOT NULL,
mutation_id varchar(128) NOT NULL,
catalog_digest char(64) NOT NULL,
command_digest char(64) NOT NULL,
committed_at_ms bigint NOT NULL,
catalog_json jsonb NOT NULL,
PRIMARY KEY (authority, generation),
CONSTRAINT ql3_tool_result_key_catalog_generation_digest_key
UNIQUE (authority, generation, catalog_digest),
CONSTRAINT ql3_tool_result_key_catalog_mutation_key
UNIQUE (mutation_id),
CONSTRAINT ql3_tool_result_key_catalog_digest_key
UNIQUE (catalog_digest),
CONSTRAINT ql3_tool_result_key_catalog_previous_fk
FOREIGN KEY (
authority, previous_generation, previous_catalog_digest
)
REFERENCES "ql3"."tool_result_key_catalog_generations" (
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
active_key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$'
),
CONSTRAINT ql3_tool_result_key_catalog_digest_check CHECK (
(
previous_catalog_digest IS NULL OR
previous_catalog_digest ~ '^[0-9a-f]{64}$'
) AND
catalog_digest ~ '^[0-9a-f]{64}$' AND
command_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_tool_result_key_catalog_budget_check CHECK (
committed_at_ms >= 0 AND
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
octet_length(catalog_json::text) BETWEEN 2 AND 65536
),
CONSTRAINT ql3_tool_result_key_catalog_json_check CHECK (
jsonb_typeof(catalog_json) = 'object' AND
catalog_json @> jsonb_build_object(
'schema', 'qinglong/tool-result-key-catalog@v1',
'generation', generation,
'previousCatalogDigest', previous_catalog_digest,
'activeKeyId', active_key_id,
'mutationKind', mutation_kind,
'mutationId', mutation_id,
'catalogDigest', catalog_digest,
'committedAtMs', committed_at_ms
) AND
jsonb_typeof(catalog_json -> 'keys') = 'array' AND
jsonb_array_length(catalog_json -> 'keys') BETWEEN 1 AND 64
)
)
`.trim(),
`
CREATE INDEX ql3_tool_result_key_catalog_current_idx
ON "ql3"."tool_result_key_catalog_generations"
(authority, generation DESC)
`.trim(),
`
CREATE TABLE "ql3"."tool_execution_result_key_bindings" (
start_id varchar(128) PRIMARY KEY,
artifact_id varchar(128) NOT NULL,
artifact_digest char(64) NOT NULL,
catalog_authority varchar(64) NOT NULL,
catalog_generation integer NOT NULL,
catalog_digest char(64) NOT NULL,
key_id varchar(128) NOT NULL,
material_proof char(64) NOT NULL,
binding_digest char(64) NOT NULL,
CONSTRAINT ql3_tool_result_key_binding_artifact_key
UNIQUE (artifact_id),
CONSTRAINT ql3_tool_result_key_binding_digest_key
UNIQUE (binding_digest),
CONSTRAINT ql3_tool_result_key_binding_completion_fk
FOREIGN KEY (start_id)
REFERENCES "ql3"."tool_execution_completions" (start_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_binding_artifact_fk
FOREIGN KEY (artifact_id)
REFERENCES "ql3"."tool_execution_completions" (artifact_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_tool_result_key_binding_catalog_fk
FOREIGN KEY (
catalog_authority, catalog_generation, catalog_digest
)
REFERENCES "ql3"."tool_result_key_catalog_generations" (
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 (
start_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
catalog_generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_tool_result_key_binding_digest_check CHECK (
artifact_digest ~ '^[0-9a-f]{64}$' AND
catalog_digest ~ '^[0-9a-f]{64}$' AND
material_proof ~ '^[0-9a-f]{64}$' AND
binding_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`
CREATE INDEX ql3_tool_result_key_binding_catalog_idx
ON "ql3"."tool_execution_result_key_bindings"
(catalog_generation, key_id, start_id)
`.trim(),
`
REVOKE ALL
ON "ql3"."tool_result_key_catalog_generations",
"ql3"."tool_execution_result_key_bindings"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT
ON "ql3"."tool_result_key_catalog_generations"
TO ql3_runtime
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_result_key_catalog_generations"
TO ql3_admin
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."tool_execution_result_key_bindings"
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 34,
migration_id = 'pg-0035-tool-result-key-catalog',
capabilities = '${CAPABILITIES_V34}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 33
AND migration_id = 'pg-0034-tool-execution-failure-completions'
AND capabilities = '${CAPABILITIES_V33}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 33'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,234 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V34 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V35 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0036ToolResultRekeyOverlaysMigration =
definePostgresSqlMigration({
id: 'pg-0036-tool-result-rekey-overlays',
statements: [
`
CREATE TABLE "ql3"."tool_execution_result_rekey_overlays" (
overlay_id varchar(128) PRIMARY KEY,
artifact_id varchar(128) NOT NULL,
source_binding_digest char(64) NOT NULL,
revision integer NOT NULL,
previous_overlay_digest char(64),
from_key_id varchar(128) NOT NULL,
target_catalog_authority varchar(64) NOT NULL,
target_catalog_generation integer NOT NULL,
target_catalog_digest char(64) NOT NULL,
target_key_id varchar(128) NOT NULL,
target_material_proof char(64) NOT NULL,
mutation_id varchar(128) NOT NULL,
command_digest char(64) NOT NULL,
overlay_digest char(64) NOT NULL,
rekeyed_at_ms bigint NOT NULL,
overlay_json jsonb NOT NULL,
CONSTRAINT ql3_result_rekey_digest_key UNIQUE (overlay_digest),
CONSTRAINT ql3_result_rekey_artifact_fk FOREIGN KEY (artifact_id)
REFERENCES "ql3"."tool_execution_result_key_bindings" (artifact_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_result_rekey_binding_fk FOREIGN KEY (source_binding_digest)
REFERENCES "ql3"."tool_execution_result_key_bindings" (binding_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_result_rekey_previous_fk FOREIGN KEY (previous_overlay_digest)
REFERENCES "ql3"."tool_execution_result_rekey_overlays" (overlay_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_result_rekey_catalog_fk FOREIGN KEY (
target_catalog_authority, target_catalog_generation,
target_catalog_digest
) REFERENCES "ql3"."tool_result_key_catalog_generations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_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_result_rekey_authority_check CHECK (
target_catalog_authority = 'trusted-tool-results'
),
CONSTRAINT ql3_result_rekey_identity_check CHECK (
overlay_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
from_key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
target_key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
from_key_id <> target_key_id AND
target_catalog_generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_result_rekey_digest_check CHECK (
(previous_overlay_digest IS NULL OR
previous_overlay_digest ~ '^[0-9a-f]{64}$') AND
source_binding_digest ~ '^[0-9a-f]{64}$' AND
target_catalog_digest ~ '^[0-9a-f]{64}$' AND
target_material_proof ~ '^[0-9a-f]{64}$' AND
command_digest ~ '^[0-9a-f]{64}$' AND
overlay_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_result_rekey_budget_check CHECK (
rekeyed_at_ms >= 0 AND
octet_length(overlay_json::text) BETWEEN 2 AND 393216
),
CONSTRAINT ql3_result_rekey_json_check CHECK (
jsonb_typeof(overlay_json) = 'object' AND
overlay_json @> jsonb_build_object(
'schema', 'qinglong/tool-execution-result-rekey-overlay@v1',
'overlayId', overlay_id,
'sourceBindingDigest', source_binding_digest,
'revision', revision,
'previousOverlayDigest', previous_overlay_digest,
'fromKeyId', from_key_id,
'rekeyedAtMs', rekeyed_at_ms,
'overlayDigest', overlay_digest
) AND
overlay_json -> 'sourceArtifact' ->> 'artifactId' = artifact_id AND
overlay_json -> 'targetCatalogFence' @> jsonb_build_object(
'generation', target_catalog_generation,
'catalogDigest', target_catalog_digest,
'keyId', target_key_id,
'materialProof', target_material_proof
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_result_rekey_mutation_key ON "ql3"."tool_execution_result_rekey_overlays" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_result_rekey_artifact_revision_key ON "ql3"."tool_execution_result_rekey_overlays" (artifact_id, revision)`,
`CREATE UNIQUE INDEX ql3_result_rekey_artifact_revision_digest_key ON "ql3"."tool_execution_result_rekey_overlays" (artifact_id, revision, overlay_digest)`,
`CREATE INDEX ql3_result_rekey_artifact_idx ON "ql3"."tool_execution_result_rekey_overlays" (artifact_id, revision DESC)`,
`CREATE INDEX ql3_result_rekey_target_idx ON "ql3"."tool_execution_result_rekey_overlays" (target_key_id, artifact_id, revision DESC)`,
`
CREATE TABLE "ql3"."tool_execution_result_rekey_heads" (
artifact_id varchar(128) PRIMARY KEY,
revision integer NOT NULL,
overlay_id varchar(128) NOT NULL,
overlay_digest char(64) NOT NULL,
target_catalog_generation integer NOT NULL,
target_catalog_digest char(64) NOT NULL,
target_key_id varchar(128) NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT ql3_result_rekey_head_overlay_fk FOREIGN KEY (
artifact_id, revision, overlay_digest
) REFERENCES "ql3"."tool_execution_result_rekey_overlays" (
artifact_id, revision, overlay_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_result_rekey_head_identity_check CHECK (
revision BETWEEN 1 AND 2147483647 AND
artifact_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
overlay_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
target_key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
target_catalog_generation BETWEEN 1 AND 2147483647 AND
updated_at_ms >= 0
),
CONSTRAINT ql3_result_rekey_head_digest_check CHECK (
overlay_digest ~ '^[0-9a-f]{64}$' AND
target_catalog_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_result_rekey_head_overlay_key ON "ql3"."tool_execution_result_rekey_heads" (overlay_id)`,
`CREATE UNIQUE INDEX ql3_result_rekey_head_digest_key ON "ql3"."tool_execution_result_rekey_heads" (overlay_digest)`,
`CREATE INDEX ql3_result_rekey_head_target_idx ON "ql3"."tool_execution_result_rekey_heads" (target_key_id, artifact_id)`,
`
CREATE TABLE "ql3"."tool_result_key_retirement_receipts" (
receipt_digest char(64) PRIMARY KEY,
catalog_authority varchar(64) NOT NULL,
catalog_generation integer NOT NULL,
catalog_digest char(64) NOT NULL,
key_id varchar(128) NOT NULL,
material_proof char(64) NOT NULL,
mutation_id varchar(128) NOT NULL,
command_digest char(64) 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 char(64) NOT NULL,
created_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT ql3_result_retirement_catalog_fk FOREIGN KEY (
catalog_authority, catalog_generation, catalog_digest
) REFERENCES "ql3"."tool_result_key_catalog_generations" (
authority, generation, catalog_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_result_retirement_authority_check CHECK (
catalog_authority = 'trusted-tool-results'
),
CONSTRAINT ql3_result_retirement_identity_check CHECK (
catalog_generation BETWEEN 1 AND 2147483647 AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$' AND
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_result_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_result_retirement_digest_check CHECK (
receipt_digest ~ '^[0-9a-f]{64}$' AND
catalog_digest ~ '^[0-9a-f]{64}$' AND
material_proof ~ '^[0-9a-f]{64}$' AND
command_digest ~ '^[0-9a-f]{64}$' AND
coverage_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_result_retirement_json_check CHECK (
jsonb_typeof(receipt_json) = 'object' AND
receipt_json @> jsonb_build_object(
'schema', 'qinglong/tool-result-key-retirement-receipt@v1',
'catalogGeneration', catalog_generation,
'catalogDigest', catalog_digest,
'keyId', key_id,
'materialProof', material_proof,
'mutationId', mutation_id,
'bindingCount', binding_count,
'overlayHeadCount', overlay_head_count,
'uncoveredBindingCount', 0,
'uncoveredOverlayHeadCount', 0,
'coverageDigest', coverage_digest,
'createdAtMs', created_at_ms,
'receiptDigest', receipt_digest
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_result_retirement_mutation_key ON "ql3"."tool_result_key_retirement_receipts" (mutation_id)`,
`CREATE INDEX ql3_result_retirement_catalog_idx ON "ql3"."tool_result_key_retirement_receipts" (catalog_generation, key_id)`,
`
REVOKE ALL ON
"ql3"."tool_execution_result_rekey_overlays",
"ql3"."tool_execution_result_rekey_heads",
"ql3"."tool_result_key_retirement_receipts"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`GRANT SELECT ON "ql3"."tool_execution_result_rekey_overlays", "ql3"."tool_execution_result_rekey_heads" TO ql3_runtime`,
`GRANT SELECT, INSERT ON "ql3"."tool_execution_result_rekey_overlays", "ql3"."tool_result_key_retirement_receipts" TO ql3_admin`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."tool_execution_result_rekey_heads" TO ql3_admin`,
`GRANT SELECT ON "ql3"."tool_execution_completions", "ql3"."tool_execution_result_key_bindings" TO ql3_admin`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 35,
migration_id = 'pg-0036-tool-result-rekey-overlays',
capabilities = '${CAPABILITIES_V35}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 34
AND migration_id = 'pg-0035-tool-result-key-catalog'
AND capabilities = '${CAPABILITIES_V34}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 34'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,779 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V35 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V36 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0037PluginPackageQuarantineMigration =
definePostgresSqlMigration({
id: 'pg-0037-plugin-package-quarantine',
statements: [
`
ALTER TABLE "ql3"."plugin_package_installs"
ADD CONSTRAINT ql3_plugin_package_installs_quarantine_target_key
UNIQUE (
project_id, package_name, installation_id, lock_digest, record_digest
)
`.trim(),
`
ALTER TABLE "ql3"."project_tool_definition_snapshots"
ADD CONSTRAINT ql3_project_tool_snapshot_withdrawal_key
UNIQUE (project_id, active_vector_digest, snapshot_digest)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_quarantine_events" (
event_digest char(64) PRIMARY KEY,
mutation_id varchar(128) NOT NULL,
revocation_receipt_digest char(64) NOT NULL,
impact_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
install_state varchar(16) NOT NULL,
install_version integer NOT NULL,
install_record_digest char(64) NOT NULL,
active_lock_digest char(64),
proposer_type varchar(16) NOT NULL,
proposer_id varchar(255) NOT NULL,
confirmer_type varchar(16) NOT NULL,
confirmer_id varchar(255) NOT NULL,
authorization_mode varchar(16) NOT NULL,
reason_code varchar(32) NOT NULL,
occurred_at_ms bigint NOT NULL,
event_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_quarantine_install_fk FOREIGN KEY (
project_id, package_name, installation_id, lock_digest,
install_record_digest
) REFERENCES "ql3"."plugin_package_installs" (
project_id, package_name, installation_id, lock_digest, record_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_quarantine_identity_check CHECK (
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' 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
octet_length(proposer_id) BETWEEN 1 AND 255 AND
octet_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 (
event_digest ~ '^[0-9a-f]{64}$' AND
revocation_receipt_digest ~ '^[0-9a-f]{64}$' AND
impact_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
install_record_digest ~ '^[0-9a-f]{64}$' AND
(active_lock_digest IS NULL OR
active_lock_digest ~ '^[0-9a-f]{64}$')
),
CONSTRAINT ql3_plugin_package_quarantine_json_check CHECK (
jsonb_typeof(event_json) = 'object' AND
octet_length(event_json::text) BETWEEN 2 AND 262144 AND
event_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-quarantine-event@v1',
'mutationId', mutation_id,
'revocationReceiptDigest', revocation_receipt_digest,
'impactDigest', impact_digest,
'authorizationMode', authorization_mode,
'reasonCode', reason_code,
'occurredAtMs', occurred_at_ms,
'eventDigest', event_digest
) AND
event_json -> 'target' @> jsonb_build_object(
'projectId', project_id,
'packageName', package_name,
'installationId', installation_id,
'lockDigest', lock_digest,
'installState', install_state,
'installVersion', install_version,
'installRecordDigest', install_record_digest,
'activeLockDigest', active_lock_digest
) AND
event_json -> 'proposer' @> jsonb_build_object(
'type', proposer_type, 'id', proposer_id
) AND
event_json -> 'confirmer' @> jsonb_build_object(
'type', confirmer_type, 'id', confirmer_id
)
),
CONSTRAINT ql3_plugin_package_quarantine_time_check CHECK (
occurred_at_ms >= 0
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_quarantine_mutation_key ON "ql3"."plugin_package_quarantine_events" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_quarantine_target_key ON "ql3"."plugin_package_quarantine_events" (project_id, package_name, installation_id, lock_digest)`,
`CREATE INDEX ql3_plugin_package_quarantine_lock_idx ON "ql3"."plugin_package_quarantine_events" (lock_digest, project_id, package_name)`,
`CREATE INDEX ql3_plugin_package_quarantine_project_idx ON "ql3"."plugin_package_quarantine_events" (project_id, package_name, occurred_at_ms, event_digest)`,
`
CREATE TABLE "ql3"."plugin_package_withdrawal_receipts" (
event_digest char(64) PRIMARY KEY,
receipt_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
capability_status varchar(16) NOT NULL,
task_count integer NOT NULL,
previous_active_vector_digest char(64),
current_active_vector_digest char(64),
current_tool_snapshot_digest char(64),
retained_source_count integer NOT NULL,
committed_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_withdrawal_event_fk FOREIGN KEY (
event_digest
) REFERENCES "ql3"."plugin_package_quarantine_events" (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 "ql3"."project_tool_definition_snapshots" (
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 (
event_digest ~ '^[0-9a-f]{64}$' AND
receipt_digest ~ '^[0-9a-f]{64}$' AND
(previous_active_vector_digest IS NULL OR
previous_active_vector_digest ~ '^[0-9a-f]{64}$') AND
(current_active_vector_digest IS NULL OR
current_active_vector_digest ~ '^[0-9a-f]{64}$') AND
(current_tool_snapshot_digest IS NULL OR
current_tool_snapshot_digest ~ '^[0-9a-f]{64}$')
),
CONSTRAINT ql3_plugin_package_withdrawal_json_check CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 8388608 AND
receipt_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-withdrawal-receipt@v1',
'eventDigest', event_digest,
'committedAtMs', committed_at_ms,
'receiptDigest', receipt_digest
) AND
receipt_json -> 'target' ->> 'projectId' = project_id AND
receipt_json -> 'capability' @> jsonb_build_object(
'status', capability_status,
'previousActiveVectorDigest', previous_active_vector_digest,
'currentActiveVectorDigest', current_active_vector_digest,
'currentToolSnapshotDigest', current_tool_snapshot_digest,
'retainedSourceCount', retained_source_count
) AND
jsonb_array_length(
receipt_json -> 'capability' -> 'taskWithdrawals'
) = task_count
),
CONSTRAINT ql3_plugin_package_withdrawal_time_check CHECK (
committed_at_ms >= 0
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_withdrawal_receipt_key ON "ql3"."plugin_package_withdrawal_receipts" (receipt_digest)`,
`CREATE INDEX ql3_plugin_package_withdrawal_snapshot_idx ON "ql3"."plugin_package_withdrawal_receipts" (current_tool_snapshot_digest, event_digest)`,
`
CREATE TABLE "ql3"."plugin_package_withdrawal_tasks" (
event_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
previous_revision integer NOT NULL,
disabled_revision integer NOT NULL,
previous_content_digest char(64) NOT NULL,
disabled_content_digest char(64) NOT NULL,
PRIMARY KEY (event_digest, task_id),
CONSTRAINT ql3_plugin_package_withdrawal_task_receipt_fk FOREIGN KEY (
event_digest
) REFERENCES "ql3"."plugin_package_withdrawal_receipts" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_task_previous_fk FOREIGN KEY (
project_id, task_id, previous_revision
) REFERENCES "ql3"."task_definition_revisions" (
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 "ql3"."task_definition_revisions" (
project_id, task_id, revision
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_withdrawal_task_identity_check CHECK (
task_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
previous_revision BETWEEN 1 AND 2147483646 AND
disabled_revision = previous_revision + 1
),
CONSTRAINT ql3_plugin_package_withdrawal_task_digest_check CHECK (
event_digest ~ '^[0-9a-f]{64}$' AND
previous_content_digest ~ '^[0-9a-f]{64}$' AND
disabled_content_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`CREATE INDEX ql3_plugin_package_withdrawal_task_idx ON "ql3"."plugin_package_withdrawal_tasks" (project_id, task_id, event_digest)`,
`
CREATE FUNCTION "ql3"."plugin_package_run_start_allowed"(
p_project_id varchar,
p_task_id varchar,
p_task_revision varchar
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_exists boolean;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
SELECT true INTO project_exists
FROM "ql3"."projects"
WHERE id = p_project_id
FOR SHARE;
IF NOT COALESCE(project_exists, false) THEN
RETURN false;
END IF;
RETURN NOT EXISTS (
SELECT 1
FROM "ql3"."plugin_package_quarantine_events" AS quarantine
JOIN "ql3"."plugin_package_task_reconciliations" AS reconciliation
ON reconciliation.project_id = quarantine.project_id
AND reconciliation.package_name = quarantine.package_name
AND reconciliation.lock_digest = quarantine.lock_digest
JOIN "ql3"."plugin_package_task_reconciliation_items" AS item
ON item.generation_digest = reconciliation.generation_digest
AND item.task_id = p_task_id
AND 'qltd:v1:' || item.revision || ':' || item.content_digest =
p_task_revision
WHERE quarantine.project_id = p_project_id
);
END
$ql3$
`.trim(),
`
CREATE FUNCTION "ql3"."plugin_package_tool_start_allowed"(
p_project_id varchar,
p_definition_ref varchar,
p_definition_digest char(64)
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_exists boolean;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
SELECT true INTO project_exists
FROM "ql3"."projects"
WHERE id = p_project_id
FOR SHARE;
IF NOT COALESCE(project_exists, false) THEN
RETURN false;
END IF;
RETURN NOT EXISTS (
SELECT 1
FROM "ql3"."plugin_package_quarantine_events" AS quarantine
JOIN "ql3"."project_tool_definition_snapshot_sources" AS source
ON source.project_id = quarantine.project_id
AND source.package_name = quarantine.package_name
AND source.installation_id = quarantine.installation_id
AND source.lock_digest = quarantine.lock_digest
JOIN "ql3"."project_tool_definition_snapshots" AS snapshot
ON snapshot.project_id = source.project_id
AND snapshot.active_vector_digest = source.active_vector_digest
CROSS JOIN LATERAL jsonb_array_elements(
snapshot.snapshot_json -> 'definitions'
) AS definition(item)
WHERE quarantine.project_id = p_project_id
AND definition.item ->> 'packageName' = quarantine.package_name
AND 'tool:' ||
(definition.item -> 'definition' ->> 'name') || '@' ||
(definition.item -> 'definition' ->> 'version') = p_definition_ref
AND definition.item ->> 'definitionDigest' = p_definition_digest
);
END
$ql3$
`.trim(),
`
CREATE FUNCTION "ql3"."commit_plugin_package_quarantine"(
p_event jsonb,
p_receipt jsonb,
p_task_writes jsonb,
p_snapshot jsonb
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
event_digest_value char(64);
project_id_value varchar(128);
package_name_value varchar(63);
installation_id_value varchar(128);
lock_digest_value char(64);
install_record "ql3"."plugin_package_installs"%ROWTYPE;
existing_event jsonb;
existing_receipt jsonb;
task_write jsonb;
previous_task "ql3"."task_definition_revisions"%ROWTYPE;
disabled_task jsonb;
withdrawal jsonb;
enabled_task_count integer;
source_count integer;
inserted_snapshot integer;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_package_executor', 'member') THEN
RAISE EXCEPTION 'Package executor authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
IF jsonb_typeof(p_event) <> 'object'
OR jsonb_typeof(p_receipt) <> 'object'
OR jsonb_typeof(p_task_writes) <> 'array'
OR jsonb_array_length(p_task_writes) > 128
OR (p_snapshot <> 'null'::jsonb AND
jsonb_typeof(p_snapshot) <> 'object') THEN
RAISE EXCEPTION 'invalid Package quarantine input'
USING ERRCODE = 'check_violation';
END IF;
event_digest_value := p_event ->> 'eventDigest';
project_id_value := p_event -> 'target' ->> 'projectId';
package_name_value := p_event -> 'target' ->> 'packageName';
installation_id_value := p_event -> 'target' ->> 'installationId';
lock_digest_value := p_event -> 'target' ->> 'lockDigest';
IF p_receipt ->> 'eventDigest' IS DISTINCT FROM event_digest_value
OR p_receipt -> 'target' IS DISTINCT FROM p_event -> 'target'
OR (p_receipt ->> 'committedAtMs')::bigint <
(p_event ->> 'occurredAtMs')::bigint THEN
RAISE EXCEPTION 'Package quarantine receipt does not bind the event'
USING ERRCODE = 'check_violation';
END IF;
PERFORM 1 FROM "ql3"."projects"
WHERE id = project_id_value
FOR UPDATE;
IF NOT FOUND THEN
RAISE EXCEPTION 'Package quarantine Project is absent'
USING ERRCODE = 'check_violation';
END IF;
SELECT event_json INTO existing_event
FROM "ql3"."plugin_package_quarantine_events"
WHERE event_digest = event_digest_value;
IF FOUND THEN
SELECT receipt_json INTO existing_receipt
FROM "ql3"."plugin_package_withdrawal_receipts"
WHERE event_digest = event_digest_value;
IF NOT FOUND
OR existing_event IS DISTINCT FROM p_event
OR existing_receipt IS DISTINCT FROM p_receipt THEN
RAISE EXCEPTION 'Package quarantine replay conflicts'
USING ERRCODE = 'unique_violation';
END IF;
RETURN false;
END IF;
SELECT * INTO install_record
FROM "ql3"."plugin_package_installs"
WHERE installation_id = installation_id_value
FOR UPDATE;
IF NOT FOUND
OR install_record.project_id <> project_id_value
OR install_record.package_name <> package_name_value
OR install_record.lock_digest <> lock_digest_value
OR install_record.state <> p_event -> 'target' ->> 'installState'
OR install_record.version <>
(p_event -> 'target' ->> 'installVersion')::integer
OR install_record.record_digest <>
p_event -> 'target' ->> 'installRecordDigest'
OR install_record.active_lock_digest IS DISTINCT FROM
p_event -> 'target' ->> 'activeLockDigest' THEN
RAISE EXCEPTION 'Package quarantine target drifted'
USING ERRCODE = 'check_violation';
END IF;
IF install_record.state = 'active' AND NOT EXISTS (
SELECT 1
FROM "ql3"."plugin_package_install_heads" AS head
JOIN "ql3"."plugin_package_installs" AS head_install
ON head_install.installation_id = head.installation_id
JOIN "ql3"."plugin_package_materialized_revisions" AS revision
ON revision.project_id = install_record.project_id
AND revision.package_name = install_record.package_name
AND revision.generation = install_record.target_generation
AND revision.lock_digest = install_record.lock_digest
WHERE head.project_id = install_record.project_id
AND head.package_name = install_record.package_name
AND head.installation_id = install_record.installation_id
AND head_install.active_lock_digest = install_record.lock_digest
) THEN
RAISE EXCEPTION 'active Package quarantine target is not materialized'
USING ERRCODE = 'check_violation';
END IF;
INSERT INTO "ql3"."plugin_package_quarantine_events" (
event_digest, mutation_id, revocation_receipt_digest, impact_digest,
project_id, package_name, installation_id, lock_digest,
install_state, install_version, install_record_digest,
active_lock_digest, proposer_type, proposer_id, confirmer_type,
confirmer_id, authorization_mode, reason_code, occurred_at_ms, event_json
) VALUES (
event_digest_value,
p_event ->> 'mutationId',
p_event ->> 'revocationReceiptDigest',
p_event ->> 'impactDigest',
project_id_value,
package_name_value,
installation_id_value,
lock_digest_value,
p_event -> 'target' ->> 'installState',
(p_event -> 'target' ->> 'installVersion')::integer,
p_event -> 'target' ->> 'installRecordDigest',
p_event -> 'target' ->> 'activeLockDigest',
p_event -> 'proposer' ->> 'type',
p_event -> 'proposer' ->> 'id',
p_event -> 'confirmer' ->> 'type',
p_event -> 'confirmer' ->> 'id',
p_event ->> 'authorizationMode',
p_event ->> 'reasonCode',
(p_event ->> 'occurredAtMs')::bigint,
p_event
);
IF install_record.state <> 'active' THEN
IF p_snapshot <> 'null'::jsonb OR jsonb_array_length(p_task_writes) <> 0
OR p_receipt -> 'capability' ->> 'status' <> 'not_active' THEN
RAISE EXCEPTION 'inactive Package quarantine disposition is invalid'
USING ERRCODE = 'check_violation';
END IF;
ELSE
IF p_snapshot = 'null'::jsonb
OR p_receipt -> 'capability' ->> 'status' <> 'withdrawn' THEN
RAISE EXCEPTION 'active Package quarantine disposition is invalid'
USING ERRCODE = 'check_violation';
END IF;
SELECT count(*)::integer INTO source_count
FROM "ql3"."plugin_package_install_heads" AS head
JOIN "ql3"."plugin_package_installs" AS head_install
ON head_install.installation_id = head.installation_id
JOIN "ql3"."plugin_package_installs" AS active_install
ON active_install.project_id = head.project_id
AND active_install.package_name = head.package_name
AND active_install.lock_digest = head_install.active_lock_digest
JOIN "ql3"."plugin_package_materialized_revisions" AS revision
ON revision.project_id = active_install.project_id
AND revision.package_name = active_install.package_name
AND revision.generation = active_install.target_generation
AND revision.lock_digest = active_install.lock_digest
LEFT JOIN "ql3"."plugin_package_quarantine_events" AS quarantine
ON quarantine.project_id = active_install.project_id
AND quarantine.package_name = active_install.package_name
AND quarantine.installation_id = active_install.installation_id
AND quarantine.lock_digest = active_install.lock_digest
WHERE head.project_id = project_id_value
AND head_install.active_lock_digest IS NOT NULL
AND active_install.state = 'active'
AND quarantine.event_digest IS NULL;
IF source_count > 128
OR source_count <>
jsonb_array_length(p_snapshot -> 'sources')
OR source_count <>
(p_receipt -> 'capability' ->> 'retainedSourceCount')::integer
OR EXISTS (
SELECT 1
FROM "ql3"."plugin_package_install_heads" AS head
JOIN "ql3"."plugin_package_installs" AS head_install
ON head_install.installation_id = head.installation_id
JOIN "ql3"."plugin_package_installs" AS active_install
ON active_install.project_id = head.project_id
AND active_install.package_name = head.package_name
AND active_install.lock_digest = head_install.active_lock_digest
JOIN "ql3"."plugin_package_materialized_revisions" AS revision
ON revision.project_id = active_install.project_id
AND revision.package_name = active_install.package_name
AND revision.generation = active_install.target_generation
AND revision.lock_digest = active_install.lock_digest
LEFT JOIN "ql3"."plugin_package_quarantine_events" AS quarantine
ON quarantine.project_id = active_install.project_id
AND quarantine.package_name = active_install.package_name
AND quarantine.installation_id = active_install.installation_id
AND quarantine.lock_digest = active_install.lock_digest
WHERE head.project_id = project_id_value
AND head_install.active_lock_digest IS NOT NULL
AND active_install.state = 'active'
AND quarantine.event_digest IS NULL
AND NOT EXISTS (
SELECT 1 FROM jsonb_array_elements(
p_snapshot -> 'sources'
) AS source
WHERE source ->> 'packageName' = active_install.package_name
AND source ->> 'installationId' =
active_install.installation_id
AND (source ->> 'generation')::integer =
active_install.target_generation
AND source ->> 'generationDigest' =
revision.generation_digest
AND source ->> 'lockDigest' = active_install.lock_digest
AND source ->> 'revisionDigest' =
revision.revision_digest
)
) THEN
RAISE EXCEPTION 'Package quarantine Tool source vector drifted'
USING ERRCODE = 'check_violation';
END IF;
SELECT count(*)::integer INTO enabled_task_count
FROM "ql3"."plugin_package_task_ownerships" AS ownership
JOIN "ql3"."task_definitions" AS head
ON head.project_id = ownership.project_id
AND head.task_id = ownership.task_id
JOIN "ql3"."task_definition_revisions" AS revision
ON revision.project_id = head.project_id
AND revision.task_id = head.task_id
AND revision.revision = head.current_revision
WHERE ownership.project_id = project_id_value
AND ownership.package_name = package_name_value
AND revision.enabled = true;
IF enabled_task_count > 128
OR enabled_task_count <> jsonb_array_length(p_task_writes)
OR enabled_task_count <>
jsonb_array_length(
p_receipt -> 'capability' -> 'taskWithdrawals'
) THEN
RAISE EXCEPTION 'Package quarantine Task set drifted'
USING ERRCODE = 'check_violation';
END IF;
FOR task_write IN SELECT value FROM jsonb_array_elements(p_task_writes)
LOOP
disabled_task := task_write -> 'disabled';
withdrawal := task_write -> 'withdrawal';
SELECT revision.* INTO previous_task
FROM "ql3"."plugin_package_task_ownerships" AS ownership
JOIN "ql3"."task_definitions" AS head
ON head.project_id = ownership.project_id
AND head.task_id = ownership.task_id
JOIN "ql3"."task_definition_revisions" AS revision
ON revision.project_id = head.project_id
AND revision.task_id = head.task_id
AND revision.revision = head.current_revision
WHERE ownership.project_id = project_id_value
AND ownership.package_name = package_name_value
AND ownership.task_id = withdrawal ->> 'taskId'
AND revision.enabled = true
FOR UPDATE OF head;
IF NOT FOUND
OR previous_task.revision <>
(withdrawal ->> 'previousRevision')::integer
OR previous_task.content_digest <>
withdrawal ->> 'previousContentDigest'
OR disabled_task ->> 'projectId' <> project_id_value
OR disabled_task ->> 'taskId' <> withdrawal ->> 'taskId'
OR (disabled_task ->> 'revision')::integer <>
previous_task.revision + 1
OR (disabled_task ->> 'enabled')::boolean <> false
OR disabled_task ->> 'contentDigest' <>
withdrawal ->> 'disabledContentDigest' THEN
RAISE EXCEPTION 'Package quarantine Task write drifted'
USING ERRCODE = 'check_violation';
END IF;
INSERT INTO "ql3"."task_definition_revisions" (
project_id, task_id, revision, mutation_id, name, description,
kind, spec_json, labels_json, enabled, content_digest, created_at_ms
) VALUES (
project_id_value,
disabled_task ->> 'taskId',
(disabled_task ->> 'revision')::integer,
(disabled_task ->> 'mutationId')::uuid,
disabled_task ->> 'name',
disabled_task ->> 'description',
disabled_task ->> 'kind',
disabled_task -> 'spec',
disabled_task -> 'labels',
false,
disabled_task ->> 'contentDigest',
(disabled_task ->> 'updatedAtMs')::bigint
);
UPDATE "ql3"."task_definitions"
SET current_revision = (disabled_task ->> 'revision')::integer,
updated_at_ms = (disabled_task ->> 'updatedAtMs')::bigint
WHERE project_id = project_id_value
AND task_id = disabled_task ->> 'taskId'
AND current_revision = previous_task.revision;
IF NOT FOUND THEN
RAISE EXCEPTION 'Package quarantine Task head drifted'
USING ERRCODE = 'serialization_failure';
END IF;
END LOOP;
INSERT INTO "ql3"."project_tool_definition_snapshots" (
project_id, active_vector_digest, definitions_digest,
snapshot_digest, snapshot_json, committed_at_ms
) VALUES (
project_id_value,
p_snapshot ->> 'activeVectorDigest',
p_snapshot ->> 'definitionsDigest',
p_snapshot ->> 'snapshotDigest',
p_snapshot,
(p_receipt ->> 'committedAtMs')::bigint
)
ON CONFLICT (project_id, active_vector_digest) DO NOTHING;
GET DIAGNOSTICS inserted_snapshot = ROW_COUNT;
IF inserted_snapshot = 1 THEN
INSERT INTO "ql3"."project_tool_definition_snapshot_sources" (
project_id, active_vector_digest, package_name, installation_id,
generation, generation_digest, lock_digest, revision_digest
)
SELECT
project_id_value,
p_snapshot ->> 'activeVectorDigest',
source ->> 'packageName',
source ->> 'installationId',
(source ->> 'generation')::integer,
source ->> 'generationDigest',
source ->> 'lockDigest',
source ->> 'revisionDigest'
FROM jsonb_array_elements(p_snapshot -> 'sources') AS source;
END IF;
IF NOT EXISTS (
SELECT 1
FROM "ql3"."project_tool_definition_snapshots"
WHERE project_id = project_id_value
AND active_vector_digest = p_snapshot ->> 'activeVectorDigest'
AND snapshot_json = p_snapshot
) THEN
RAISE EXCEPTION 'Package quarantine snapshot conflicts'
USING ERRCODE = 'unique_violation';
END IF;
END IF;
INSERT INTO "ql3"."plugin_package_withdrawal_receipts" (
event_digest, receipt_digest, project_id, capability_status,
task_count, previous_active_vector_digest,
current_active_vector_digest, current_tool_snapshot_digest,
retained_source_count, committed_at_ms, receipt_json
) VALUES (
event_digest_value,
p_receipt ->> 'receiptDigest',
project_id_value,
p_receipt -> 'capability' ->> 'status',
jsonb_array_length(
p_receipt -> 'capability' -> 'taskWithdrawals'
),
p_receipt -> 'capability' ->> 'previousActiveVectorDigest',
p_receipt -> 'capability' ->> 'currentActiveVectorDigest',
p_receipt -> 'capability' ->> 'currentToolSnapshotDigest',
(p_receipt -> 'capability' ->> 'retainedSourceCount')::integer,
(p_receipt ->> 'committedAtMs')::bigint,
p_receipt
);
INSERT INTO "ql3"."plugin_package_withdrawal_tasks" (
event_digest, project_id, task_id, previous_revision,
disabled_revision, previous_content_digest, disabled_content_digest
)
SELECT
event_digest_value,
project_id_value,
receipt_withdrawal ->> 'taskId',
(receipt_withdrawal ->> 'previousRevision')::integer,
(receipt_withdrawal ->> 'disabledRevision')::integer,
receipt_withdrawal ->> 'previousContentDigest',
receipt_withdrawal ->> 'disabledContentDigest'
FROM jsonb_array_elements(
p_receipt -> 'capability' -> 'taskWithdrawals'
) AS receipt_withdrawal;
RETURN true;
END
$ql3$
`.trim(),
`
REVOKE ALL ON
"ql3"."plugin_package_quarantine_events",
"ql3"."plugin_package_withdrawal_receipts",
"ql3"."plugin_package_withdrawal_tasks"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
REVOKE ALL ON FUNCTION
"ql3"."plugin_package_run_start_allowed"(varchar, varchar, varchar),
"ql3"."plugin_package_tool_start_allowed"(varchar, varchar, char(64)),
"ql3"."commit_plugin_package_quarantine"(jsonb, jsonb, jsonb, jsonb)
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`GRANT SELECT ON "ql3"."plugin_package_quarantine_events", "ql3"."plugin_package_withdrawal_receipts", "ql3"."plugin_package_withdrawal_tasks" TO ql3_package_executor`,
`GRANT EXECUTE ON FUNCTION "ql3"."plugin_package_run_start_allowed"(varchar, varchar, varchar), "ql3"."plugin_package_tool_start_allowed"(varchar, varchar, char(64)) TO ql3_runtime`,
`GRANT EXECUTE ON FUNCTION "ql3"."commit_plugin_package_quarantine"(jsonb, jsonb, jsonb, jsonb) TO ql3_package_executor`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 36,
migration_id = 'pg-0037-plugin-package-quarantine',
capabilities = '${CAPABILITIES_V36}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 35
AND migration_id = 'pg-0036-tool-result-rekey-overlays'
AND capabilities = '${CAPABILITIES_V35}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 35'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,426 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V36 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V37 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0038PluginPackagePublisherProvenanceMigration =
definePostgresSqlMigration({
id: 'pg-0038-plugin-package-publisher-provenance',
statements: [
`
CREATE TABLE "ql3"."plugin_package_publisher_provenance" (
installation_id varchar(128) PRIMARY KEY,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
lock_digest char(64) NOT NULL,
artifact_digest char(64) NOT NULL,
manifest_digest char(64) NOT NULL,
content_digest char(64) NOT NULL,
stage_evidence_digest char(64) NOT NULL,
publisher varchar(253) NOT NULL,
key_id varchar(128) NOT NULL,
signature_digest char(64) NOT NULL,
key_not_before_ms bigint NOT NULL,
key_not_after_ms bigint NOT NULL,
verified_at_ms bigint NOT NULL,
provenance_digest char(64) NOT NULL,
provenance_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_provenance_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_provenance_identity_check CHECK (
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
publisher ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_plugin_package_publisher_provenance_digest_check CHECK (
lock_digest ~ '^[0-9a-f]{64}$' AND
artifact_digest ~ '^[0-9a-f]{64}$' AND
manifest_digest ~ '^[0-9a-f]{64}$' AND
content_digest ~ '^[0-9a-f]{64}$' AND
stage_evidence_digest ~ '^[0-9a-f]{64}$' AND
signature_digest ~ '^[0-9a-f]{64}$' AND
provenance_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_publisher_provenance_time_check CHECK (
key_not_before_ms >= 0 AND
key_not_after_ms > key_not_before_ms AND
verified_at_ms >= key_not_before_ms AND
verified_at_ms < key_not_after_ms
),
CONSTRAINT ql3_plugin_package_publisher_provenance_json_check CHECK (
jsonb_typeof(provenance_json) = 'object' AND
octet_length(provenance_json::text) BETWEEN 2 AND 262144 AND
provenance_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-publisher-provenance@v1',
'projectId', project_id,
'packageName', package_name,
'installationId', installation_id,
'lockDigest', lock_digest,
'artifactDigest', artifact_digest,
'manifestDigest', manifest_digest,
'contentDigest', content_digest,
'stageEvidenceDigest', stage_evidence_digest,
'publisher', publisher,
'keyId', key_id,
'signatureDigest', signature_digest,
'keyNotBeforeMs', key_not_before_ms,
'keyNotAfterMs', key_not_after_ms,
'verifiedAtMs', verified_at_ms,
'provenanceDigest', provenance_digest
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_provenance_digest_key ON "ql3"."plugin_package_publisher_provenance" (provenance_digest)`,
`CREATE INDEX ql3_plugin_package_publisher_provenance_signer_idx ON "ql3"."plugin_package_publisher_provenance" (publisher, key_id, project_id, package_name, installation_id)`,
`CREATE INDEX ql3_plugin_package_publisher_provenance_lock_idx ON "ql3"."plugin_package_publisher_provenance" (lock_digest, installation_id)`,
`
CREATE TABLE "ql3"."plugin_package_publisher_revocation_receipts" (
receipt_digest char(64) PRIMARY KEY,
mutation_id varchar(128) NOT NULL,
publisher varchar(253) NOT NULL,
key_id varchar(128) NOT NULL,
previous_trust_digest char(64) NOT NULL,
current_trust_digest char(64) NOT NULL,
proposer_type varchar(16) NOT NULL,
proposer_id varchar(255) NOT NULL,
confirmer_type varchar(16) NOT NULL,
confirmer_id varchar(255) NOT NULL,
authorization_mode varchar(16) NOT NULL,
reason_code varchar(32) NOT NULL,
revoked_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_revocation_identity_check CHECK (
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
publisher ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
proposer_type IN (
'user', 'api_app', 'mcp_client', 'agent', 'system', 'worker'
) AND
confirmer_type IN (
'user', 'api_app', 'mcp_client', 'agent', 'system', 'worker'
) AND
octet_length(proposer_id) BETWEEN 1 AND 255 AND
octet_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_publisher_revocation_digest_check CHECK (
receipt_digest ~ '^[0-9a-f]{64}$' AND
previous_trust_digest ~ '^[0-9a-f]{64}$' AND
current_trust_digest ~ '^[0-9a-f]{64}$' AND
previous_trust_digest <> current_trust_digest
),
CONSTRAINT ql3_plugin_package_publisher_revocation_time_check CHECK (
revoked_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_publisher_revocation_json_check CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 262144 AND
receipt_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-publisher-key-revocation-receipt@v1',
'mutationId', mutation_id,
'publisher', publisher,
'keyId', key_id,
'previousTrustDigest', previous_trust_digest,
'currentTrustDigest', current_trust_digest,
'authorizationMode', authorization_mode,
'reasonCode', reason_code,
'revokedAtMs', revoked_at_ms,
'receiptDigest', receipt_digest
) AND
receipt_json -> 'proposer' @> jsonb_build_object(
'type', proposer_type, 'id', proposer_id
) AND
receipt_json -> 'confirmer' @> jsonb_build_object(
'type', confirmer_type, 'id', confirmer_id
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_revocation_mutation_key ON "ql3"."plugin_package_publisher_revocation_receipts" (mutation_id)`,
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_revocation_signer_key ON "ql3"."plugin_package_publisher_revocation_receipts" (publisher, key_id)`,
`
CREATE TABLE "ql3"."plugin_package_publisher_revocation_impacts" (
revocation_receipt_digest char(64) PRIMARY KEY,
impact_digest char(64) NOT NULL,
item_count integer NOT NULL,
generated_at_ms bigint NOT NULL,
impact_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_impact_receipt_fk
FOREIGN KEY (revocation_receipt_digest)
REFERENCES "ql3"."plugin_package_publisher_revocation_receipts"
(receipt_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_impact_digest_check CHECK (
revocation_receipt_digest ~ '^[0-9a-f]{64}$' AND
impact_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_publisher_impact_count_check CHECK (
item_count BETWEEN 0 AND 4096 AND generated_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_publisher_impact_json_check CHECK (
jsonb_typeof(impact_json) = 'object' AND
octet_length(impact_json::text) BETWEEN 2 AND 8388608 AND
impact_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-publisher-key-revocation-impact@v1',
'revocationReceiptDigest', revocation_receipt_digest,
'generatedAtMs', generated_at_ms,
'impactDigest', impact_digest
) AND
jsonb_array_length(impact_json -> 'items') = item_count
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_impact_digest_key ON "ql3"."plugin_package_publisher_revocation_impacts" (impact_digest)`,
`
CREATE TABLE "ql3"."plugin_package_publisher_revocation_impact_items" (
impact_digest char(64) NOT NULL,
provenance_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
PRIMARY KEY (impact_digest, provenance_digest),
CONSTRAINT ql3_plugin_package_publisher_impact_item_impact_fk
FOREIGN KEY (impact_digest)
REFERENCES "ql3"."plugin_package_publisher_revocation_impacts"
(impact_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_impact_item_provenance_fk
FOREIGN KEY (provenance_digest)
REFERENCES "ql3"."plugin_package_publisher_provenance"
(provenance_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_impact_item_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_impact_item_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
impact_digest ~ '^[0-9a-f]{64}$' AND
provenance_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$'
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_impact_item_install_key ON "ql3"."plugin_package_publisher_revocation_impact_items" (impact_digest, installation_id)`,
`CREATE INDEX ql3_plugin_package_publisher_impact_item_target_idx ON "ql3"."plugin_package_publisher_revocation_impact_items" (project_id, package_name, installation_id, lock_digest)`,
`
CREATE FUNCTION "ql3"."enforce_plugin_package_stage_provenance"()
RETURNS trigger
LANGUAGE plpgsql
SET search_path = pg_catalog, ql3
AS $ql3$
BEGIN
IF OLD.state = 'queued' AND NEW.state = 'staged' AND NOT EXISTS (
SELECT 1
FROM "ql3"."plugin_package_publisher_provenance" AS provenance
WHERE provenance.installation_id = NEW.installation_id
AND provenance.project_id = NEW.project_id
AND provenance.package_name = NEW.package_name
AND provenance.lock_digest = NEW.lock_digest
AND provenance.artifact_digest =
NEW.lock_json -> 'source' ->> 'artifactDigest'
AND provenance.manifest_digest = NEW.lock_json ->> 'manifestDigest'
AND provenance.content_digest =
NEW.lock_json -> 'source' ->> 'contentDigest'
AND provenance.stage_evidence_digest =
NEW.record_json -> 'stageReceipt' ->> 'evidenceDigest'
) THEN
RAISE EXCEPTION
'Plugin Package stage requires exact publisher provenance'
USING ERRCODE = 'check_violation';
END IF;
RETURN NEW;
END
$ql3$
`.trim(),
`
CREATE TRIGGER ql3_plugin_package_stage_provenance_guard
BEFORE UPDATE ON "ql3"."plugin_package_installs"
FOR EACH ROW EXECUTE FUNCTION
"ql3"."enforce_plugin_package_stage_provenance"()
`.trim(),
`
CREATE OR REPLACE FUNCTION "ql3"."plugin_package_run_start_allowed"(
p_project_id varchar,
p_task_id varchar,
p_task_revision varchar
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_exists boolean;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
SELECT true INTO project_exists
FROM "ql3"."projects"
WHERE id = p_project_id
FOR SHARE;
IF NOT COALESCE(project_exists, false) THEN
RETURN false;
END IF;
RETURN NOT EXISTS (
SELECT 1
FROM "ql3"."plugin_package_task_reconciliations" AS reconciliation
JOIN "ql3"."plugin_package_task_reconciliation_items" AS item
ON item.generation_digest = reconciliation.generation_digest
AND item.task_id = p_task_id
AND 'qltd:v1:' || item.revision || ':' || item.content_digest =
p_task_revision
WHERE reconciliation.project_id = p_project_id
AND (
EXISTS (
SELECT 1
FROM "ql3"."plugin_package_quarantine_events" AS quarantine
WHERE quarantine.project_id = reconciliation.project_id
AND quarantine.package_name = reconciliation.package_name
AND quarantine.lock_digest = reconciliation.lock_digest
) OR EXISTS (
SELECT 1
FROM "ql3"."plugin_package_publisher_provenance" AS provenance
JOIN "ql3"."plugin_package_publisher_revocation_receipts" AS revoked
ON revoked.publisher = provenance.publisher
AND revoked.key_id = provenance.key_id
WHERE provenance.lock_digest = reconciliation.lock_digest
)
)
);
END
$ql3$
`.trim(),
`
CREATE OR REPLACE FUNCTION "ql3"."plugin_package_tool_start_allowed"(
p_project_id varchar,
p_definition_ref varchar,
p_definition_digest char(64)
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_exists boolean;
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
SELECT true INTO project_exists
FROM "ql3"."projects"
WHERE id = p_project_id
FOR SHARE;
IF NOT COALESCE(project_exists, false) THEN
RETURN false;
END IF;
RETURN NOT EXISTS (
SELECT 1
FROM "ql3"."project_tool_definition_snapshot_sources" AS source
JOIN "ql3"."project_tool_definition_snapshots" AS snapshot
ON snapshot.project_id = source.project_id
AND snapshot.active_vector_digest = source.active_vector_digest
CROSS JOIN LATERAL jsonb_array_elements(
snapshot.snapshot_json -> 'definitions'
) AS definition(item)
WHERE source.project_id = p_project_id
AND definition.item ->> 'packageName' = source.package_name
AND 'tool:' ||
(definition.item -> 'definition' ->> 'name') || '@' ||
(definition.item -> 'definition' ->> 'version') = p_definition_ref
AND definition.item ->> 'definitionDigest' = p_definition_digest
AND (
EXISTS (
SELECT 1
FROM "ql3"."plugin_package_quarantine_events" AS quarantine
WHERE quarantine.project_id = source.project_id
AND quarantine.package_name = source.package_name
AND quarantine.installation_id = source.installation_id
AND quarantine.lock_digest = source.lock_digest
) OR EXISTS (
SELECT 1
FROM "ql3"."plugin_package_publisher_provenance" AS provenance
JOIN "ql3"."plugin_package_publisher_revocation_receipts" AS revoked
ON revoked.publisher = provenance.publisher
AND revoked.key_id = provenance.key_id
WHERE provenance.installation_id = source.installation_id
AND provenance.lock_digest = source.lock_digest
)
)
);
END
$ql3$
`.trim(),
`
REVOKE ALL ON
"ql3"."plugin_package_publisher_provenance",
"ql3"."plugin_package_publisher_revocation_receipts",
"ql3"."plugin_package_publisher_revocation_impacts",
"ql3"."plugin_package_publisher_revocation_impact_items"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
REVOKE ALL ON FUNCTION
"ql3"."enforce_plugin_package_stage_provenance"()
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT ON
"ql3"."plugin_package_publisher_provenance",
"ql3"."plugin_package_publisher_revocation_receipts",
"ql3"."plugin_package_publisher_revocation_impacts",
"ql3"."plugin_package_publisher_revocation_impact_items"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 37,
migration_id = 'pg-0038-plugin-package-publisher-provenance',
capabilities = '${CAPABILITIES_V37}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 36
AND migration_id = 'pg-0037-plugin-package-quarantine'
AND capabilities = '${CAPABILITIES_V36}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 36'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,250 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V37 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V38 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0039PluginPackagePublisherTrustAuthorityMigration =
definePostgresSqlMigration({
id: 'pg-0039-plugin-package-publisher-trust-authority',
statements: [
`
CREATE TABLE "ql3"."plugin_package_publisher_trust_snapshots" (
snapshot_digest char(64) PRIMARY KEY,
key_count integer NOT NULL,
observed_by varchar(128) NOT NULL,
observed_at_ms bigint NOT NULL,
snapshot_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_trust_snapshot_identity_check CHECK (
observed_by ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
),
CONSTRAINT ql3_plugin_package_publisher_trust_snapshot_digest_check CHECK (
snapshot_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_publisher_trust_snapshot_count_check CHECK (
key_count BETWEEN 0 AND 32 AND observed_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_publisher_trust_snapshot_json_check CHECK (
jsonb_typeof(snapshot_json) = 'object' AND
octet_length(snapshot_json::text) BETWEEN 2 AND 262144 AND
snapshot_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-publisher-trust-snapshot@v1',
'snapshotDigest', snapshot_digest
) AND
jsonb_array_length(snapshot_json -> 'keys') = key_count
)
)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_publisher_trust_heads" (
authority_id varchar(128) PRIMARY KEY,
generation integer NOT NULL,
base_snapshot_digest char(64) NOT NULL,
effective_trust_digest char(64) NOT NULL,
updated_at_ms bigint NOT NULL,
head_digest char(64) NOT NULL,
head_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_trust_head_snapshot_fk
FOREIGN KEY (base_snapshot_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_trust_head_effective_snapshot_fk
FOREIGN KEY (effective_trust_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_trust_head_identity_check CHECK (
authority_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
generation BETWEEN 1 AND 2147483647
),
CONSTRAINT ql3_plugin_package_publisher_trust_head_digest_check CHECK (
base_snapshot_digest ~ '^[0-9a-f]{64}$' AND
effective_trust_digest ~ '^[0-9a-f]{64}$' AND
head_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_publisher_trust_head_time_check CHECK (
updated_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_publisher_trust_head_json_check CHECK (
jsonb_typeof(head_json) = 'object' AND
octet_length(head_json::text) BETWEEN 2 AND 65536 AND
head_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-publisher-trust-head@v1',
'authorityId', authority_id,
'generation', generation,
'baseSnapshotDigest', base_snapshot_digest,
'effectiveTrustDigest', effective_trust_digest,
'updatedAtMs', updated_at_ms,
'headDigest', head_digest
)
)
)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_publisher_revocation_proposals" (
action_ref varchar(255) PRIMARY KEY,
project_id varchar(128) NOT NULL,
authority_id varchar(128) NOT NULL,
trust_generation integer NOT NULL,
publisher varchar(253) NOT NULL,
key_id varchar(128) NOT NULL,
previous_trust_digest char(64) NOT NULL,
current_trust_digest char(64) NOT NULL,
action_type varchar(128) NOT NULL,
permission varchar(128) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
authorization_mode varchar(16) NOT NULL,
reason_code varchar(32) NOT NULL,
proposed_by_type varchar(32) NOT NULL,
proposed_by_id varchar(255) NOT NULL,
proposer_assurance varchar(32) NOT NULL,
fence_project_version integer NOT NULL,
fence_binding_version integer,
created_at_ms bigint NOT NULL,
proposal_json jsonb NOT NULL,
proposal_digest char(64) NOT NULL,
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_head_fk
FOREIGN KEY (authority_id)
REFERENCES "ql3"."plugin_package_publisher_trust_heads" (authority_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_identity_check
CHECK (
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
authority_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
publisher ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
action_type = 'plugin_package.publisher_key.revoke' AND
permission = 'package.manage' AND
authorization_mode IN ('dual_control', 'break_glass') AND
reason_code IN (
'suspected_key_compromise', 'confirmed_key_compromise'
) AND
proposed_by_type IN (
'user', 'api_app', 'mcp_client', 'agent', 'system', 'worker'
) AND
octet_length(proposed_by_id) BETWEEN 1 AND 255 AND
proposer_assurance IN (
'single_factor', 'multi_factor', 'service', 'hardware',
'local_console'
) AND
(authorization_mode <> 'break_glass' OR
proposer_assurance = 'hardware')
),
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_digest_check
CHECK (
previous_trust_digest ~ '^[0-9a-f]{64}$' AND
current_trust_digest ~ '^[0-9a-f]{64}$' AND
previous_trust_digest <> current_trust_digest AND
action_digest ~ '^[0-9a-f]{64}$' AND
preview_digest ~ '^[0-9a-f]{64}$' AND
proposal_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_time_check
CHECK (
trust_generation BETWEEN 1 AND 2147483647 AND
fence_project_version BETWEEN 1 AND 2147483647 AND
(fence_binding_version IS NULL OR
fence_binding_version BETWEEN 1 AND 2147483647) AND
created_at_ms >= 0
),
CONSTRAINT ql3_plugin_package_publisher_revocation_proposal_json_check
CHECK (
jsonb_typeof(proposal_json) = 'object' AND
octet_length(proposal_json::text) BETWEEN 2 AND 262144 AND
proposal_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-publisher-key-revocation-proposal@v1',
'actionRef', action_ref,
'projectId', project_id,
'actionType', action_type,
'permission', permission,
'actionDigest', action_digest,
'previewDigest', preview_digest,
'proposerAssurance', proposer_assurance,
'createdAtMs', created_at_ms,
'proposalDigest', proposal_digest
) AND
proposal_json -> 'actionInput' @> jsonb_build_object(
'authorityProjectId', project_id,
'trustAuthorityId', authority_id,
'trustGeneration', trust_generation,
'publisher', publisher,
'keyId', key_id,
'previousTrustDigest', previous_trust_digest,
'currentTrustDigest', current_trust_digest,
'authorizationMode', authorization_mode,
'reasonCode', reason_code
) AND
proposal_json -> 'proposedBy' @> jsonb_build_object(
'type', proposed_by_type, 'id', proposed_by_id
) AND
proposal_json -> 'proposalFence' @> jsonb_build_object(
'projectVersion', fence_project_version,
'bindingVersion', fence_binding_version
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_publisher_revocation_proposal_digest_key ON "ql3"."plugin_package_publisher_revocation_proposals" (proposal_digest)`,
`CREATE INDEX ql3_plugin_package_publisher_revocation_proposal_project_idx ON "ql3"."plugin_package_publisher_revocation_proposals" (project_id, created_at_ms, action_ref)`,
`CREATE INDEX ql3_plugin_package_publisher_revocation_proposal_signer_idx ON "ql3"."plugin_package_publisher_revocation_proposals" (publisher, key_id, trust_generation)`,
`
REVOKE ALL ON
"ql3"."plugin_package_publisher_trust_snapshots",
"ql3"."plugin_package_publisher_trust_heads",
"ql3"."plugin_package_publisher_revocation_proposals"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT ON
"ql3"."plugin_package_publisher_trust_snapshots",
"ql3"."plugin_package_publisher_trust_heads",
"ql3"."plugin_package_publisher_revocation_proposals"
TO ql3_package_manager
`.trim(),
`
GRANT SELECT, INSERT ON
"ql3"."plugin_package_publisher_trust_snapshots"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT ON
"ql3"."plugin_package_publisher_revocation_proposals"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, UPDATE ON
"ql3"."plugin_package_publisher_trust_heads"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 38,
migration_id =
'pg-0039-plugin-package-publisher-trust-authority',
capabilities = '${CAPABILITIES_V38}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 37
AND migration_id = 'pg-0038-plugin-package-publisher-provenance'
AND capabilities = '${CAPABILITIES_V37}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 37'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,288 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V38 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V39 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0040PluginPackagePublisherTrustTransitionsMigration =
definePostgresSqlMigration({
id: 'pg-0040-plugin-package-publisher-trust-transitions',
statements: [
`
CREATE TABLE "ql3"."plugin_package_publisher_trust_transition_proposals" (
action_ref varchar(255) PRIMARY KEY,
project_id varchar(128) NOT NULL,
authority_id varchar(128) NOT NULL,
trust_generation integer NOT NULL,
mode varchar(16) NOT NULL,
publisher varchar(253) NOT NULL,
key_id varchar(128) NOT NULL,
previous_trust_digest char(64) NOT NULL,
current_trust_digest char(64) NOT NULL,
action_type varchar(128) NOT NULL,
permission varchar(128) NOT NULL,
action_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
proposed_by_type varchar(32) NOT NULL,
proposed_by_id varchar(255) NOT NULL,
proposer_assurance varchar(32) NOT NULL,
fence_project_version integer NOT NULL,
fence_binding_version integer,
created_at_ms bigint NOT NULL,
proposal_json jsonb NOT NULL,
proposal_digest char(64) NOT NULL,
CONSTRAINT ql3_pp_trust_transition_proposal_digest_key
UNIQUE (proposal_digest),
CONSTRAINT ql3_pp_trust_transition_proposal_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_proposal_head_fk
FOREIGN KEY (authority_id)
REFERENCES "ql3"."plugin_package_publisher_trust_heads" (authority_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_proposal_previous_fk
FOREIGN KEY (previous_trust_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_proposal_current_fk
FOREIGN KEY (current_trust_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_proposal_identity_check
CHECK (
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
authority_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
publisher ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
mode IN ('overlap_add', 'safe_retire') AND
action_type = CASE mode
WHEN 'overlap_add'
THEN 'plugin_package.publisher_key.overlap_add'
WHEN 'safe_retire'
THEN 'plugin_package.publisher_key.safe_retire'
END AND
permission = 'package.manage' AND
proposed_by_type = 'user' AND
octet_length(proposed_by_id) BETWEEN 1 AND 255 AND
proposer_assurance IN ('multi_factor', 'hardware')
),
CONSTRAINT ql3_pp_trust_transition_proposal_digest_check
CHECK (
previous_trust_digest ~ '^[0-9a-f]{64}$' AND
current_trust_digest ~ '^[0-9a-f]{64}$' AND
previous_trust_digest <> current_trust_digest AND
action_digest ~ '^[0-9a-f]{64}$' AND
preview_digest ~ '^[0-9a-f]{64}$' AND
proposal_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_pp_trust_transition_proposal_time_check
CHECK (
trust_generation BETWEEN 1 AND 2147483647 AND
fence_project_version BETWEEN 1 AND 2147483647 AND
(fence_binding_version IS NULL OR
fence_binding_version BETWEEN 1 AND 2147483647) AND
created_at_ms >= 0
),
CONSTRAINT ql3_pp_trust_transition_proposal_json_check
CHECK (
jsonb_typeof(proposal_json) = 'object' AND
octet_length(proposal_json::text) BETWEEN 2 AND 262144 AND
proposal_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-publisher-trust-transition-proposal@v1',
'actionRef', action_ref,
'projectId', project_id,
'actionType', action_type,
'permission', permission,
'actionDigest', action_digest,
'previewDigest', preview_digest,
'proposerAssurance', proposer_assurance,
'createdAtMs', created_at_ms,
'proposalDigest', proposal_digest
) AND
proposal_json -> 'actionInput' @> jsonb_build_object(
'authorityProjectId', project_id,
'trustAuthorityId', authority_id,
'trustGeneration', trust_generation,
'mode', mode,
'publisher', publisher,
'keyId', key_id,
'previousTrustDigest', previous_trust_digest,
'currentTrustDigest', current_trust_digest
) AND
proposal_json -> 'proposedBy' @> jsonb_build_object(
'type', proposed_by_type, 'id', proposed_by_id
) AND
proposal_json -> 'proposalFence' @> jsonb_build_object(
'projectVersion', fence_project_version,
'bindingVersion', fence_binding_version
)
)
)
`.trim(),
`CREATE INDEX ql3_pp_trust_transition_proposal_project_idx ON "ql3"."plugin_package_publisher_trust_transition_proposals" (project_id, created_at_ms, action_ref)`,
`CREATE INDEX ql3_pp_trust_transition_proposal_signer_idx ON "ql3"."plugin_package_publisher_trust_transition_proposals" (publisher, key_id, trust_generation)`,
`
CREATE TABLE "ql3"."plugin_package_publisher_trust_transition_receipts" (
mutation_id varchar(128) PRIMARY KEY,
proposal_digest char(64) NOT NULL,
authority_id varchar(128) NOT NULL,
previous_generation integer NOT NULL,
current_generation integer NOT NULL,
mode varchar(16) NOT NULL,
publisher varchar(253) NOT NULL,
key_id varchar(128) NOT NULL,
previous_trust_digest char(64) NOT NULL,
current_trust_digest char(64) NOT NULL,
proposer_type varchar(32) NOT NULL,
proposer_id varchar(255) NOT NULL,
confirmer_type varchar(32) NOT NULL,
confirmer_id varchar(255) NOT NULL,
retirement_matching_installations integer,
executed_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
receipt_digest char(64) NOT NULL,
CONSTRAINT ql3_pp_trust_transition_receipt_proposal_key
UNIQUE (proposal_digest),
CONSTRAINT ql3_pp_trust_transition_receipt_digest_key
UNIQUE (receipt_digest),
CONSTRAINT ql3_pp_trust_transition_receipt_dispatch_fk
FOREIGN KEY (mutation_id)
REFERENCES "ql3"."approved_action_dispatches" (dispatch_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_receipt_proposal_fk
FOREIGN KEY (proposal_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_transition_proposals"
(proposal_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_receipt_head_fk
FOREIGN KEY (authority_id)
REFERENCES "ql3"."plugin_package_publisher_trust_heads" (authority_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_receipt_previous_fk
FOREIGN KEY (previous_trust_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_receipt_current_fk
FOREIGN KEY (current_trust_digest)
REFERENCES "ql3"."plugin_package_publisher_trust_snapshots"
(snapshot_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_pp_trust_transition_receipt_identity_check
CHECK (
mutation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
proposal_digest ~ '^[0-9a-f]{64}$' AND
authority_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
mode IN ('overlap_add', 'safe_retire') AND
publisher ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$' AND
key_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
proposer_type = 'user' AND
confirmer_type = 'user' AND
octet_length(proposer_id) BETWEEN 1 AND 255 AND
octet_length(confirmer_id) BETWEEN 1 AND 255 AND
(proposer_type, proposer_id) <> (confirmer_type, confirmer_id)
),
CONSTRAINT ql3_pp_trust_transition_receipt_transition_check
CHECK (
previous_generation BETWEEN 1 AND 2147483646 AND
current_generation = previous_generation + 1 AND
previous_trust_digest ~ '^[0-9a-f]{64}$' AND
current_trust_digest ~ '^[0-9a-f]{64}$' AND
previous_trust_digest <> current_trust_digest AND
(
(mode = 'overlap_add' AND
retirement_matching_installations IS NULL) OR
(mode = 'safe_retire' AND
retirement_matching_installations = 0)
) AND
executed_at_ms >= 0 AND
receipt_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_pp_trust_transition_receipt_json_check
CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 262144 AND
receipt_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-publisher-trust-transition-receipt@v1',
'mutationId', mutation_id,
'proposalDigest', proposal_digest,
'trustAuthorityId', authority_id,
'previousGeneration', previous_generation,
'currentGeneration', current_generation,
'mode', mode,
'publisher', publisher,
'keyId', key_id,
'previousTrustDigest', previous_trust_digest,
'currentTrustDigest', current_trust_digest,
'retirementMatchingInstallations',
retirement_matching_installations,
'executedAtMs', executed_at_ms,
'receiptDigest', receipt_digest
) AND
receipt_json -> 'proposer' @> jsonb_build_object(
'type', proposer_type, 'id', proposer_id
) AND
receipt_json -> 'confirmer' @> jsonb_build_object(
'type', confirmer_type, 'id', confirmer_id
)
)
)
`.trim(),
`CREATE INDEX ql3_pp_trust_transition_receipt_signer_idx ON "ql3"."plugin_package_publisher_trust_transition_receipts" (publisher, key_id, current_generation)`,
`
REVOKE ALL ON
"ql3"."plugin_package_publisher_trust_transition_proposals",
"ql3"."plugin_package_publisher_trust_transition_receipts"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT ON
"ql3"."plugin_package_publisher_trust_transition_proposals"
TO ql3_package_manager
`.trim(),
`
GRANT SELECT ON
"ql3"."plugin_package_publisher_trust_transition_receipts"
TO ql3_package_manager
`.trim(),
`
GRANT SELECT ON
"ql3"."plugin_package_publisher_trust_transition_proposals"
TO ql3_package_executor
`.trim(),
`
GRANT SELECT, INSERT ON
"ql3"."plugin_package_publisher_trust_transition_receipts"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 39,
migration_id =
'pg-0040-plugin-package-publisher-trust-transitions',
capabilities = '${CAPABILITIES_V39}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 38
AND migration_id =
'pg-0039-plugin-package-publisher-trust-authority'
AND capabilities = '${CAPABILITIES_V38}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 38'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,108 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V40 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V41 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0042PluginPackageLifecyclePlansMigration =
definePostgresSqlMigration({
id: 'pg-0042-plugin-package-lifecycle-plans',
statements: [
`
CREATE TABLE "ql3"."plugin_package_lifecycle_plans" (
action_ref varchar(255) PRIMARY KEY,
plan_digest char(64) NOT NULL,
action varchar(16) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
impact_digest char(64) NOT NULL,
requested_by_type varchar(16) NOT NULL,
requested_by_id varchar(255) NOT NULL,
planned_at_ms bigint NOT NULL,
expires_at_ms bigint NOT NULL,
plan_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_lifecycle_plan_install_fk
FOREIGN KEY (installation_id)
REFERENCES "ql3"."plugin_package_installs" (installation_id)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_lifecycle_plan_identity_check CHECK (
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$'
AND action IN ('disable', 'enable', 'uninstall')
AND package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
AND requested_by_type = 'user'
AND char_length(requested_by_id) BETWEEN 1 AND 255
AND requested_by_id !~ '[[:cntrl:]]'
),
CONSTRAINT ql3_plugin_package_lifecycle_plan_digest_check CHECK (
plan_digest ~ '^[0-9a-f]{64}$'
AND lock_digest ~ '^[0-9a-f]{64}$'
AND impact_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_lifecycle_plan_time_check CHECK (
planned_at_ms >= 0
AND expires_at_ms > planned_at_ms
AND expires_at_ms - planned_at_ms <= 900000
),
CONSTRAINT ql3_plugin_package_lifecycle_plan_json_check CHECK (
jsonb_typeof(plan_json) = 'object'
AND octet_length(plan_json::text) BETWEEN 2 AND 98304
AND plan_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-lifecycle-plan@v1',
'actionRef', action_ref,
'planDigest', plan_digest,
'requestedBy', jsonb_build_object(
'type', requested_by_type,
'id', requested_by_id
),
'plannedAtMs', planned_at_ms,
'expiresAtMs', expires_at_ms,
'impact', jsonb_build_object(
'action', action,
'impactDigest', impact_digest,
'target', jsonb_build_object(
'projectId', project_id,
'packageName', package_name,
'installationId', installation_id,
'lockDigest', lock_digest
)
)
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_plan_digest_key ON "ql3"."plugin_package_lifecycle_plans" (plan_digest)`,
`CREATE UNIQUE INDEX ql3_plugin_package_lifecycle_plan_impact_key ON "ql3"."plugin_package_lifecycle_plans" (project_id, package_name, installation_id, lock_digest, impact_digest)`,
`CREATE INDEX ql3_plugin_package_lifecycle_plan_expiry_idx ON "ql3"."plugin_package_lifecycle_plans" (expires_at_ms, action_ref)`,
`
REVOKE ALL ON "ql3"."plugin_package_lifecycle_plans"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`GRANT SELECT ON "ql3"."plugin_package_lifecycle_plans" TO ql3_package_manager, ql3_package_executor`,
`GRANT INSERT ON "ql3"."plugin_package_lifecycle_plans" TO ql3_package_executor`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 41,
migration_id = 'pg-0042-plugin-package-lifecycle-plans',
capabilities = '${CAPABILITIES_V41}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 40
AND migration_id = 'pg-0041-plugin-package-lifecycle'
AND capabilities = '${CAPABILITIES_V40}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 40'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,181 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V41 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V42 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0043PluginPackageAutomationPublicationsMigration =
definePostgresSqlMigration({
id: 'pg-0043-plugin-package-automation-publications',
statements: [
`
CREATE TABLE "ql3"."plugin_package_automation_publications" (
publication_digest char(64) PRIMARY KEY,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
generation integer NOT NULL,
generation_digest char(64) NOT NULL,
materialized_revision_digest char(64) NOT NULL,
state varchar(16) NOT NULL,
version integer NOT NULL,
previous_publication_digest char(64),
lifecycle_event_digest char(64),
published_at_ms bigint NOT NULL,
publication_json jsonb NOT NULL,
CONSTRAINT ql3_plugin_package_automation_publication_revision_fk
FOREIGN KEY (generation_digest)
REFERENCES "ql3"."plugin_package_materialized_revisions" (
generation_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_previous_fk
FOREIGN KEY (previous_publication_digest)
REFERENCES "ql3"."plugin_package_automation_publications" (
publication_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_lifecycle_fk
FOREIGN KEY (lifecycle_event_digest)
REFERENCES "ql3"."plugin_package_lifecycle_events" (event_digest)
ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_identity_check CHECK (
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' 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 (
publication_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
generation_digest ~ '^[0-9a-f]{64}$' AND
materialized_revision_digest ~ '^[0-9a-f]{64}$' AND
(
previous_publication_digest IS NULL OR
previous_publication_digest ~ '^[0-9a-f]{64}$'
) AND
(
lifecycle_event_digest IS NULL OR
lifecycle_event_digest ~ '^[0-9a-f]{64}$'
)
),
CONSTRAINT ql3_plugin_package_automation_publication_json_check CHECK (
jsonb_typeof(publication_json) = 'object' AND
octet_length(publication_json::text) BETWEEN 2 AND 12582912 AND
publication_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-automation-publication@v1',
'state', state,
'version', version,
'previousPublicationDigest', previous_publication_digest,
'lifecycleEventDigest', lifecycle_event_digest,
'publishedAtMs', published_at_ms,
'publicationDigest', publication_digest,
'target', jsonb_build_object(
'projectId', project_id,
'packageName', package_name,
'installationId', installation_id,
'lockDigest', lock_digest,
'generation', generation,
'generationDigest', generation_digest,
'materializedRevisionDigest', materialized_revision_digest
)
) AND
jsonb_typeof(publication_json -> 'definitions' -> 'workflows') =
'array' AND
jsonb_typeof(publication_json -> 'definitions' -> 'prompts') =
'array' AND
(
state = 'absent' AND
jsonb_array_length(publication_json -> 'definitions' -> 'workflows') +
jsonb_array_length(publication_json -> 'definitions' -> 'prompts') = 0
OR
state <> 'absent' AND
jsonb_array_length(publication_json -> 'definitions' -> 'workflows') +
jsonb_array_length(publication_json -> 'definitions' -> 'prompts') > 0
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_version_key ON "ql3"."plugin_package_automation_publications" (project_id, package_name, version)`,
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_previous_key ON "ql3"."plugin_package_automation_publications" (previous_publication_digest) WHERE previous_publication_digest IS NOT NULL`,
`CREATE INDEX ql3_plugin_package_automation_publication_generation_idx ON "ql3"."plugin_package_automation_publications" (generation_digest, publication_digest)`,
`
CREATE TABLE "ql3"."plugin_package_automation_publication_heads" (
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
publication_digest char(64) NOT NULL,
generation_digest char(64) NOT NULL,
state varchar(16) NOT NULL,
version integer NOT NULL,
updated_at_ms bigint NOT NULL,
PRIMARY KEY (project_id, package_name),
CONSTRAINT ql3_plugin_package_automation_publication_head_publication_fk
FOREIGN KEY (publication_digest)
REFERENCES "ql3"."plugin_package_automation_publications" (
publication_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_automation_publication_head_state_check CHECK (
publication_digest ~ '^[0-9a-f]{64}$' AND
generation_digest ~ '^[0-9a-f]{64}$' AND
state IN ('active', 'withdrawn', 'absent') AND
version BETWEEN 1 AND 2147483647 AND
updated_at_ms >= 0
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_automation_publication_head_digest_key ON "ql3"."plugin_package_automation_publication_heads" (publication_digest)`,
`
REVOKE ALL
ON "ql3"."plugin_package_automation_publications",
"ql3"."plugin_package_automation_publication_heads"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT
ON "ql3"."plugin_package_automation_publications",
"ql3"."plugin_package_automation_publication_heads"
TO ql3_runtime, ql3_package_manager, ql3_package_executor
`.trim(),
`
GRANT INSERT
ON "ql3"."plugin_package_automation_publications"
TO ql3_package_executor
`.trim(),
`
GRANT INSERT, UPDATE
ON "ql3"."plugin_package_automation_publication_heads"
TO ql3_package_executor
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 42,
migration_id = 'pg-0043-plugin-package-automation-publications',
capabilities = '${CAPABILITIES_V42}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 41
AND migration_id = 'pg-0042-plugin-package-lifecycle-plans'
AND capabilities = '${CAPABILITIES_V41}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 41'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,160 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V42 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V43 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0044PluginPackageAutomationStartGuardMigration =
definePostgresSqlMigration({
id: 'pg-0044-plugin-package-automation-start-guard',
statements: [
`
CREATE FUNCTION "ql3"."plugin_package_automation_start_allowed"(
p_project_id varchar,
p_package_name varchar,
p_publication_digest char(64)
)
RETURNS boolean
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
DECLARE
project_exists boolean;
current_publication "ql3"."plugin_package_automation_publications"%ROWTYPE;
current_lifecycle varchar(16);
current_installation_id varchar(128);
current_publisher varchar(253);
current_key_id varchar(128);
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
SELECT true INTO project_exists
FROM "ql3"."projects"
WHERE id = p_project_id
FOR SHARE;
IF NOT COALESCE(project_exists, false) THEN
RETURN false;
END IF;
SELECT publication.* INTO current_publication
FROM "ql3"."plugin_package_automation_publication_heads" AS head
JOIN "ql3"."plugin_package_automation_publications" AS publication
ON publication.publication_digest = head.publication_digest
WHERE head.project_id = p_project_id
AND head.package_name = p_package_name
AND head.publication_digest = p_publication_digest
FOR SHARE OF head, publication;
IF NOT FOUND OR current_publication.state <> 'active' THEN
RETURN false;
END IF;
SELECT install.installation_id INTO current_installation_id
FROM "ql3"."plugin_package_install_heads" AS head
JOIN "ql3"."plugin_package_installs" AS install
ON install.installation_id = head.installation_id
WHERE head.project_id = current_publication.project_id
AND head.package_name = current_publication.package_name
AND head.installation_id = current_publication.installation_id
AND install.lock_digest = current_publication.lock_digest
AND install.state = 'active'
AND install.active_lock_digest = current_publication.lock_digest
FOR SHARE OF head, install;
IF NOT FOUND THEN
RETURN false;
END IF;
SELECT disposition INTO current_lifecycle
FROM "ql3"."plugin_package_lifecycle_heads"
WHERE project_id = current_publication.project_id
AND package_name = current_publication.package_name
FOR SHARE;
IF FOUND AND current_lifecycle <> 'active' THEN
RETURN false;
END IF;
IF EXISTS (
SELECT 1
FROM "ql3"."plugin_package_quarantine_events" AS quarantine
WHERE quarantine.project_id = current_publication.project_id
AND quarantine.package_name = current_publication.package_name
AND quarantine.installation_id =
current_publication.installation_id
AND quarantine.lock_digest = current_publication.lock_digest
) THEN
RETURN false;
END IF;
SELECT provenance.publisher, provenance.key_id
INTO current_publisher, current_key_id
FROM "ql3"."plugin_package_publisher_provenance" AS provenance
WHERE provenance.installation_id = current_publication.installation_id
AND provenance.lock_digest = current_publication.lock_digest;
IF NOT FOUND THEN
RETURN false;
END IF;
PERFORM pg_advisory_xact_lock(
hashtextextended(
octet_length(current_publisher)::text || ':' ||
current_publisher ||
octet_length(current_key_id)::text || ':' || current_key_id,
774635230
)
);
IF EXISTS (
SELECT 1
FROM "ql3"."plugin_package_publisher_revocation_receipts" AS revoked
WHERE revoked.publisher = current_publisher
AND revoked.key_id = current_key_id
) THEN
RETURN false;
END IF;
RETURN true;
END
$ql3$
`.trim(),
`
REVOKE ALL ON FUNCTION
"ql3"."plugin_package_automation_start_allowed"(
varchar, varchar, char(64)
)
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT EXECUTE ON FUNCTION
"ql3"."plugin_package_automation_start_allowed"(
varchar, varchar, char(64)
)
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 43,
migration_id = 'pg-0044-plugin-package-automation-start-guard',
capabilities = '${CAPABILITIES_V43}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 42
AND migration_id = 'pg-0043-plugin-package-automation-publications'
AND capabilities = '${CAPABILITIES_V42}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 42'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,234 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V43 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V44 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0045PluginPackageWorkflowAdmissionsMigration =
definePostgresSqlMigration({
id: 'pg-0045-plugin-package-workflow-admissions',
statements: [
`
CREATE TABLE "ql3"."plugin_package_workflow_admissions" (
plan_digest char(64) PRIMARY KEY,
plan_id varchar(128) NOT NULL,
run_id varchar(36) NOT NULL,
project_id varchar(128) NOT NULL,
package_name varchar(63) NOT NULL,
installation_id varchar(128) NOT NULL,
lock_digest char(64) NOT NULL,
generation integer NOT NULL,
generation_digest char(64) NOT NULL,
materialized_revision_digest char(64) NOT NULL,
publication_digest char(64) NOT NULL,
workflow_id varchar(63) NOT NULL,
workflow_definition_digest char(64) NOT NULL,
step_count integer NOT NULL,
admitted_at_ms bigint NOT NULL,
final_run_version integer NOT NULL,
final_run_event_sequence integer NOT NULL,
receipt_digest char(64) NOT NULL,
plan_json jsonb NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT plugin_package_workflow_admissions_plan_id_key
UNIQUE (plan_id),
CONSTRAINT plugin_package_workflow_admissions_run_id_key
UNIQUE (run_id),
CONSTRAINT plugin_package_workflow_admissions_receipt_digest_key
UNIQUE (receipt_digest),
CONSTRAINT ql3_plugin_package_workflow_admission_run_fk
FOREIGN KEY (run_id) REFERENCES "ql3"."runs" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_publication_fk
FOREIGN KEY (publication_digest)
REFERENCES "ql3"."plugin_package_automation_publications" (
publication_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_identity_check CHECK (
plan_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,35}$' AND
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
workflow_id ~ '^[a-z][a-z0-9-]{0,62}$' 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 (
plan_digest ~ '^[0-9a-f]{64}$' AND
lock_digest ~ '^[0-9a-f]{64}$' AND
generation_digest ~ '^[0-9a-f]{64}$' AND
materialized_revision_digest ~ '^[0-9a-f]{64}$' AND
publication_digest ~ '^[0-9a-f]{64}$' AND
workflow_definition_digest ~ '^[0-9a-f]{64}$' AND
receipt_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_plugin_package_workflow_admission_json_check CHECK (
jsonb_typeof(plan_json) = 'object' AND
octet_length(plan_json::text) BETWEEN 2 AND 262144 AND
plan_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-workflow-execution-plan@v1',
'planId', plan_id, 'planDigest', plan_digest, 'runId', run_id,
'plannedAtMs', admitted_at_ms
) AND
plan_json -> 'target' @> jsonb_build_object(
'projectId', project_id, 'packageName', package_name,
'installationId', installation_id, 'lockDigest', lock_digest,
'generation', generation, 'generationDigest', generation_digest,
'materializedRevisionDigest', materialized_revision_digest,
'publicationDigest', publication_digest, 'workflowId', workflow_id,
'workflowDefinitionDigest', workflow_definition_digest
) AND
jsonb_typeof(plan_json -> 'steps') = 'array' AND
jsonb_array_length(plan_json -> 'steps') = step_count AND
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 262144 AND
receipt_json @> jsonb_build_object(
'schema', 'qinglong/plugin-package-workflow-admission-receipt@v1',
'planId', plan_id, 'planDigest', plan_digest, 'runId', run_id,
'publicationDigest', publication_digest, 'workflowId', workflow_id,
'finalRunVersion', final_run_version,
'finalRunEventSequence', final_run_event_sequence,
'admittedAtMs', admitted_at_ms, 'receiptDigest', receipt_digest
) AND
jsonb_typeof(receipt_json -> 'steps') = 'array' AND
jsonb_array_length(receipt_json -> 'steps') = step_count
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_plugin_package_workflow_admission_plan_run_key ON "ql3"."plugin_package_workflow_admissions" (plan_digest, run_id)`,
`CREATE INDEX ql3_plugin_package_workflow_admission_target_idx ON "ql3"."plugin_package_workflow_admissions" (project_id, package_name, admitted_at_ms, plan_digest)`,
`
CREATE TABLE "ql3"."plugin_package_workflow_admission_steps" (
plan_digest char(64) NOT NULL,
run_id varchar(36) NOT NULL,
step_key varchar(63) NOT NULL,
step_run_id varchar(128) NOT NULL,
task_id varchar(63) NOT NULL,
task_definition_ref varchar(512) NOT NULL,
task_definition_digest char(64) NOT NULL,
needs_json jsonb NOT NULL,
initial_status varchar(16) NOT NULL,
mutation_id varchar(128) NOT NULL,
event_id varchar(36) NOT NULL,
PRIMARY KEY (plan_digest, step_key),
CONSTRAINT plugin_package_workflow_admission_steps_step_run_id_key
UNIQUE (step_run_id),
CONSTRAINT plugin_package_workflow_admission_steps_mutation_id_key
UNIQUE (mutation_id),
CONSTRAINT plugin_package_workflow_admission_steps_event_id_key
UNIQUE (event_id),
CONSTRAINT ql3_plugin_package_workflow_admission_step_admission_fk
FOREIGN KEY (plan_digest, run_id)
REFERENCES "ql3"."plugin_package_workflow_admissions" (
plan_digest, run_id
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_run_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_mutation_fk
FOREIGN KEY (mutation_id)
REFERENCES "ql3"."step_run_mutations" (mutation_id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_event_fk
FOREIGN KEY (event_id)
REFERENCES "ql3"."run_events" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_admission_step_identity_check CHECK (
step_key ~ '^[a-z][a-z0-9-]{0,62}$' AND
task_id ~ '^[a-z][a-z0-9-]{0,62}$' AND
initial_status IN ('pending', 'ready') AND
task_definition_digest ~ '^[0-9a-f]{64}$' AND
jsonb_typeof(needs_json) = 'array' AND
jsonb_array_length(needs_json) BETWEEN 0 AND 127
)
)
`.trim(),
`CREATE INDEX ql3_plugin_package_workflow_admission_step_task_idx ON "ql3"."plugin_package_workflow_admission_steps" (task_id, task_definition_digest, plan_digest)`,
`
CREATE FUNCTION "ql3"."plugin_package_workflow_admission_snapshot"(
p_project_id varchar,
p_package_name varchar,
p_publication_digest char(64)
)
RETURNS TABLE(publication_json jsonb, revision_json jsonb)
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
IF NOT "ql3"."plugin_package_automation_start_allowed"(
p_project_id, p_package_name, p_publication_digest
) THEN
RETURN;
END IF;
RETURN QUERY
SELECT publication.publication_json, revision.revision_json
FROM "ql3"."plugin_package_automation_publications" AS publication
JOIN "ql3"."plugin_package_materialized_revisions" AS revision
ON revision.generation_digest = publication.generation_digest
AND revision.revision_digest =
publication.materialized_revision_digest
WHERE publication.project_id = p_project_id
AND publication.package_name = p_package_name
AND publication.publication_digest = p_publication_digest
AND publication.state = 'active'
FOR SHARE OF publication, revision;
END
$ql3$
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_workflow_admissions",
"ql3"."plugin_package_workflow_admission_steps"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_workflow_admissions",
"ql3"."plugin_package_workflow_admission_steps"
TO ql3_runtime
`.trim(),
`
REVOKE ALL ON FUNCTION
"ql3"."plugin_package_workflow_admission_snapshot"(
varchar, varchar, char(64)
)
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT EXECUTE ON FUNCTION
"ql3"."plugin_package_workflow_admission_snapshot"(
varchar, varchar, char(64)
)
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 44,
migration_id = 'pg-0045-plugin-package-workflow-admissions',
capabilities = '${CAPABILITIES_V44}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 43
AND migration_id = 'pg-0044-plugin-package-automation-start-guard'
AND capabilities = '${CAPABILITIES_V43}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 43'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,258 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V44 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V45 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0046PluginPackageWorkflowTaskAttemptAdmissionsMigration =
definePostgresSqlMigration({
id: 'pg-0046-plugin-package-workflow-task-attempt-admissions',
statements: [
`
CREATE UNIQUE INDEX ql3_plugin_package_task_reconciliation_receipt_uidx
ON "ql3"."plugin_package_task_reconciliations"
(generation_digest, receipt_digest)
`.trim(),
`
CREATE TABLE "ql3"."plugin_package_workflow_task_attempt_admissions" (
receipt_digest char(64) PRIMARY KEY,
attempt_id varchar(36) NOT NULL,
plan_digest char(64) NOT NULL,
run_id varchar(36) NOT NULL,
step_run_id varchar(128) NOT NULL,
step_run_version integer NOT NULL,
step_run_digest char(64) NOT NULL,
generation_digest char(64) NOT NULL,
resource_task_id varchar(128) NOT NULL,
task_reconciliation_receipt_digest char(64) NOT NULL,
project_id varchar(128) NOT NULL,
task_id varchar(128) NOT NULL,
source_revision integer NOT NULL,
task_revision varchar(96) NOT NULL,
task_definition_digest char(64) NOT NULL,
executor_type varchar(32) NOT NULL,
execution_digest char(64) NOT NULL,
attempt_number integer NOT NULL,
event_id varchar(36) NOT NULL,
run_version integer NOT NULL,
run_event_sequence integer NOT NULL,
admitted_at_ms bigint NOT NULL,
receipt_json jsonb NOT NULL,
CONSTRAINT plugin_package_workflow_task_attempt_admissions_attempt_id_key
UNIQUE (attempt_id),
CONSTRAINT plugin_package_workflow_task_attempt_admissions_event_id_key
UNIQUE (event_id),
CONSTRAINT plugin_package_workflow_task_attempt_admissions_epoch_key
UNIQUE (run_id, step_run_id, step_run_version),
CONSTRAINT plugin_package_workflow_task_attempt_admissions_number_key
UNIQUE (run_id, attempt_number),
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_plan_fk
FOREIGN KEY (plan_digest, run_id)
REFERENCES "ql3"."plugin_package_workflow_admissions" (
plan_digest, run_id
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_step_fk
FOREIGN KEY (run_id, step_run_id)
REFERENCES "ql3"."step_runs" (run_id, id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_attempt_fk
FOREIGN KEY (attempt_id)
REFERENCES "ql3"."run_attempts" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_event_fk
FOREIGN KEY (event_id)
REFERENCES "ql3"."run_events" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_pp_workflow_task_attempt_reconciliation_fk
FOREIGN KEY (
generation_digest, task_reconciliation_receipt_digest
) REFERENCES "ql3"."plugin_package_task_reconciliations" (
generation_digest, receipt_digest
) ON DELETE RESTRICT,
CONSTRAINT ql3_plugin_package_workflow_task_attempt_admission_execution_fk
FOREIGN KEY (
project_id, task_id, source_revision, executor_type
) REFERENCES "ql3"."task_execution_revisions" (
project_id, task_id, source_revision, executor_type
) ON DELETE RESTRICT,
CONSTRAINT ql3_pp_workflow_task_attempt_identity_check
CHECK (
attempt_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,35}$' AND
run_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,35}$' AND
char_length(step_run_id) BETWEEN 1 AND 128 AND
char_length(resource_task_id) BETWEEN 1 AND 128 AND
char_length(project_id) BETWEEN 1 AND 128 AND
char_length(task_id) BETWEEN 1 AND 128 AND
event_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,35}$' AND
executor_type = 'remote_worker'
),
CONSTRAINT ql3_pp_workflow_task_attempt_counter_check
CHECK (
step_run_version BETWEEN 1 AND 2147483647 AND
source_revision 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 (
receipt_digest ~ '^[0-9a-f]{64}$' AND
plan_digest ~ '^[0-9a-f]{64}$' AND
step_run_digest ~ '^[0-9a-f]{64}$' AND
generation_digest ~ '^[0-9a-f]{64}$' AND
task_reconciliation_receipt_digest ~ '^[0-9a-f]{64}$' AND
task_definition_digest ~ '^[0-9a-f]{64}$' AND
execution_digest ~ '^[0-9a-f]{64}$' AND
task_revision = concat(
'qltd:v1:', source_revision::text, ':', task_definition_digest
)
),
CONSTRAINT
ql3_plugin_package_workflow_task_attempt_admission_json_check
CHECK (
jsonb_typeof(receipt_json) = 'object' AND
octet_length(receipt_json::text) BETWEEN 2 AND 16384 AND
receipt_json @> jsonb_build_object(
'schema',
'qinglong/plugin-package-workflow-task-attempt-admission@v1',
'receiptDigest', receipt_digest,
'attemptId', attempt_id,
'planDigest', plan_digest,
'runId', run_id,
'stepRunId', step_run_id,
'stepRunVersion', step_run_version,
'stepRunDigest', step_run_digest,
'resourceTaskId', resource_task_id,
'taskReconciliationReceiptDigest',
task_reconciliation_receipt_digest,
'taskId', task_id,
'taskRevision', task_revision,
'taskDefinitionDigest', task_definition_digest,
'executorType', executor_type,
'executionDigest', execution_digest,
'attemptNumber', attempt_number,
'eventId', event_id,
'runVersion', run_version,
'runEventSequence', run_event_sequence,
'admittedAtMs', admitted_at_ms
)
)
)
`.trim(),
`
CREATE INDEX ql3_pp_workflow_task_attempt_candidate_idx
ON "ql3"."plugin_package_workflow_task_attempt_admissions"
(run_id, step_run_id, admitted_at_ms)
`.trim(),
`
CREATE FUNCTION "ql3"."plugin_package_workflow_task_attempt_snapshot"(
p_run_id varchar,
p_step_run_id varchar
)
RETURNS TABLE(
plan_json jsonb,
reconciliation_json jsonb,
execution_project_id varchar,
execution_task_id varchar,
execution_source_revision integer,
execution_task_revision varchar,
execution_source_content_digest char(64),
execution_executor_type varchar,
execution_plan_schema varchar,
execution_plan_json jsonb,
execution_content_digest char(64),
execution_created_at_ms bigint
)
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, ql3
AS $ql3$
BEGIN
IF NOT pg_has_role(session_user, 'ql3_runtime', 'member') THEN
RAISE EXCEPTION 'Runtime authority is required'
USING ERRCODE = 'insufficient_privilege';
END IF;
RETURN QUERY
SELECT
workflow.plan_json,
reconciliation.receipt_json,
execution.project_id,
execution.task_id,
execution.source_revision,
execution.task_revision,
execution.source_content_digest,
execution.executor_type,
execution.plan_schema,
execution.plan_json,
execution.content_digest,
execution.created_at_ms
FROM "ql3"."plugin_package_workflow_admissions" AS workflow
JOIN "ql3"."plugin_package_workflow_admission_steps" AS source
ON source.plan_digest = workflow.plan_digest
AND source.run_id = workflow.run_id
AND source.step_run_id = p_step_run_id
JOIN "ql3"."plugin_package_task_reconciliations" AS reconciliation
ON reconciliation.generation_digest = workflow.generation_digest
JOIN "ql3"."plugin_package_task_reconciliation_items" AS item
ON item.generation_digest = reconciliation.generation_digest
AND item.task_id =
concat('pkg:', workflow.package_name, ':', source.task_id)
AND item.disposition IN ('created', 'retained', 'updated')
JOIN "ql3"."task_execution_revisions" AS execution
ON execution.project_id = workflow.project_id
AND execution.task_id = item.task_id
AND execution.source_revision = item.revision
AND execution.executor_type = 'remote_worker'
AND execution.source_content_digest = item.content_digest
WHERE workflow.run_id = p_run_id
FOR KEY SHARE OF workflow, source, reconciliation, item, execution;
END
$ql3$
`.trim(),
`
REVOKE ALL
ON "ql3"."plugin_package_workflow_task_attempt_admissions"
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT SELECT, INSERT
ON "ql3"."plugin_package_workflow_task_attempt_admissions"
TO ql3_runtime
`.trim(),
`
REVOKE ALL ON FUNCTION
"ql3"."plugin_package_workflow_task_attempt_snapshot"(varchar, varchar)
FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager,
ql3_package_executor, ql3_worker_ingress
`.trim(),
`
GRANT EXECUTE ON FUNCTION
"ql3"."plugin_package_workflow_task_attempt_snapshot"(varchar, varchar)
TO ql3_runtime
`.trim(),
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 45,
migration_id =
'pg-0046-plugin-package-workflow-task-attempt-admissions',
capabilities = '${CAPABILITIES_V45}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 44
AND migration_id = 'pg-0045-plugin-package-workflow-admissions'
AND capabilities = '${CAPABILITIES_V44}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 44'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,175 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V45 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V46 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_management_plan":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0047WorkerCredentialManagementPlansMigration =
definePostgresSqlMigration({
id: 'pg-0047-worker-credential-management-plans',
statements: [
`
DO $ql3$
DECLARE
invalid_roles text[];
BEGIN
SELECT array_agg(expected.role_name ORDER BY expected.role_name)
INTO invalid_roles
FROM (
VALUES
('ql3_worker_credential_manager'),
('ql3_worker_credential_executor')
) AS expected(role_name)
LEFT JOIN pg_catalog.pg_roles roles
ON roles.rolname = expected.role_name
WHERE roles.rolname IS NULL
OR roles.rolcanlogin IS NOT TRUE
OR roles.rolsuper IS NOT FALSE
OR roles.rolcreatedb IS NOT FALSE
OR roles.rolcreaterole IS NOT FALSE
OR roles.rolreplication IS NOT FALSE
OR roles.rolbypassrls IS NOT FALSE;
IF invalid_roles IS NOT NULL THEN
RAISE EXCEPTION
'required QingLong Worker credential roles are missing or privileged: %',
invalid_roles
USING ERRCODE = 'insufficient_privilege';
END IF;
END
$ql3$
`.trim(),
`
DO $ql3$
BEGIN
EXECUTE format(
'GRANT CONNECT ON DATABASE %I TO ql3_worker_credential_manager, ql3_worker_credential_executor',
current_database()
);
END
$ql3$
`.trim(),
`GRANT USAGE ON SCHEMA "ql3" TO ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities" TO ql3_worker_credential_manager, ql3_worker_credential_executor`,
`
CREATE TABLE "ql3"."worker_credential_management_plans" (
action_ref varchar(255) PRIMARY KEY,
authority_project_id varchar(128) NOT NULL,
action varchar(16) NOT NULL,
delivery_id varchar(36) NOT NULL,
worker_id varchar(128) NOT NULL,
credential_id varchar(64) NOT NULL,
previous_credential_id varchar(64),
credential_not_before_at_ms bigint NOT NULL,
credential_expires_at_ms bigint NOT NULL,
deployment_target_digest char(64) NOT NULL,
deployment_generation varchar(128) NOT NULL,
requested_by_type varchar(16) NOT NULL,
requested_by_id varchar(255) NOT NULL,
planned_at_ms bigint NOT NULL,
expires_at_ms bigint NOT NULL,
plan_digest char(64) NOT NULL,
preview_digest char(64) NOT NULL,
plan_json jsonb NOT NULL,
CONSTRAINT ql3_worker_credential_management_plan_project_fk
FOREIGN KEY (authority_project_id)
REFERENCES "ql3"."projects" (id) ON DELETE RESTRICT,
CONSTRAINT ql3_worker_credential_management_plan_identity_check CHECK (
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
action IN ('issue', 'rotate') AND
delivery_id ~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' AND
worker_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$' AND
(previous_credential_id IS NULL OR
previous_credential_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$') AND
deployment_generation ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
requested_by_type = 'user' AND
char_length(requested_by_id) BETWEEN 1 AND 255 AND
requested_by_id !~ '[[:cntrl:]]'
),
CONSTRAINT ql3_worker_credential_management_plan_action_check CHECK (
(action = 'issue' AND previous_credential_id IS NULL) OR
(action = 'rotate' AND previous_credential_id IS NOT NULL AND
previous_credential_id <> credential_id)
),
CONSTRAINT ql3_worker_credential_management_plan_digest_check CHECK (
deployment_target_digest ~ '^[0-9a-f]{64}$' AND
plan_digest ~ '^[0-9a-f]{64}$' AND
preview_digest ~ '^[0-9a-f]{64}$'
),
CONSTRAINT ql3_worker_credential_management_plan_time_check CHECK (
planned_at_ms >= 0 AND
expires_at_ms > planned_at_ms AND
expires_at_ms - planned_at_ms <= 900000 AND
credential_not_before_at_ms >= planned_at_ms AND
credential_expires_at_ms > credential_not_before_at_ms AND
credential_expires_at_ms - credential_not_before_at_ms <= 63072000000
),
CONSTRAINT ql3_worker_credential_management_plan_json_check CHECK (
jsonb_typeof(plan_json) = 'object' AND
octet_length(plan_json::text) BETWEEN 2 AND 16384 AND
plan_json @> jsonb_build_object(
'schema', 'qinglong/worker-credential-management-plan@v1',
'actionRef', action_ref,
'authorityProjectId', authority_project_id,
'action', action,
'planDigest', plan_digest,
'previewDigest', preview_digest,
'requestedBy', jsonb_build_object(
'type', requested_by_type,
'id', requested_by_id
),
'plannedAtMs', planned_at_ms,
'expiresAtMs', expires_at_ms,
'target', jsonb_build_object(
'deliveryId', delivery_id,
'workerId', worker_id,
'credentialId', credential_id,
'previousCredentialId', previous_credential_id,
'credentialNotBeforeAtMs', credential_not_before_at_ms,
'credentialExpiresAtMs', credential_expires_at_ms,
'deploymentTargetDigest', deployment_target_digest,
'deploymentGeneration', deployment_generation
)
)
)
)
`.trim(),
`CREATE UNIQUE INDEX ql3_worker_credential_management_plan_digest_key ON "ql3"."worker_credential_management_plans" (plan_digest)`,
`CREATE UNIQUE INDEX ql3_worker_credential_management_plan_delivery_key ON "ql3"."worker_credential_management_plans" (delivery_id)`,
`CREATE INDEX ql3_worker_credential_management_plan_expiry_idx ON "ql3"."worker_credential_management_plans" (expires_at_ms, action_ref)`,
`REVOKE ALL ON "ql3"."worker_credential_management_plans" FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager, ql3_package_executor, ql3_worker_ingress, ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT ON "ql3"."worker_credential_management_plans" TO ql3_worker_credential_manager`,
`GRANT SELECT ON "ql3"."worker_credential_management_plans" TO ql3_worker_credential_executor`,
`GRANT SELECT ON "ql3"."projects", "ql3"."project_role_bindings" TO ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT ON "ql3"."security_audit_events" TO ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."approval_requests" TO ql3_worker_credential_manager`,
`GRANT SELECT, UPDATE ON "ql3"."approval_requests" TO ql3_worker_credential_executor`,
`GRANT SELECT, INSERT ON "ql3"."approved_action_dispatches" TO ql3_worker_credential_executor`,
`GRANT SELECT, INSERT ON "ql3"."worker_credentials", "ql3"."worker_credential_mutations", "ql3"."worker_credential_deliveries", "ql3"."worker_credential_stage_discards" TO ql3_worker_credential_executor`,
`GRANT EXECUTE ON FUNCTION "ql3"."lock_approval_policy_fence"(varchar, varchar, varchar, integer, integer) TO ql3_worker_credential_manager, ql3_worker_credential_executor`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 46,
migration_id = 'pg-0047-worker-credential-management-plans',
capabilities = '${CAPABILITIES_V46}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 45
AND migration_id =
'pg-0046-plugin-package-workflow-task-attempt-admissions'
AND capabilities = '${CAPABILITIES_V45}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 45'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,36 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V46 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_management_plan":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V47 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_management_plan":1,"worker_credential_preapproved_activation":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0048WorkerCredentialPreapprovedActivationMigration =
definePostgresSqlMigration({
id: 'pg-0048-worker-credential-preapproved-activation',
statements: [
`ALTER TABLE "ql3"."worker_credentials" DROP CONSTRAINT ql3_worker_credentials_lifetime_check`,
`ALTER TABLE "ql3"."worker_credentials" ADD CONSTRAINT ql3_worker_credentials_lifetime_check CHECK (created_at_ms >= 0 AND not_before_at_ms >= 0 AND expires_at_ms > GREATEST(created_at_ms, not_before_at_ms))`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 47,
migration_id = 'pg-0048-worker-credential-preapproved-activation',
capabilities = '${CAPABILITIES_V47}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 46
AND migration_id = 'pg-0047-worker-credential-management-plans'
AND capabilities = '${CAPABILITIES_V46}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 46'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,36 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V47 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_management_plan":1,"worker_credential_preapproved_activation":1,"worker_credential_stage_discard":1,"worker_session":1}';
const CAPABILITIES_V48 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_execution_receipt":1,"worker_credential_management_plan":1,"worker_credential_preapproved_activation":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const pg0049WorkerCredentialExecutionReceiptsMigration =
definePostgresSqlMigration({
id: 'pg-0049-worker-credential-execution-receipts',
statements: [
`REVOKE ALL ON "ql3"."approved_action_executions" FROM ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."approved_action_executions" TO ql3_worker_credential_executor`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 48,
migration_id = 'pg-0049-worker-credential-execution-receipts',
capabilities = '${CAPABILITIES_V48}'::jsonb,
updated_at_ms = floor(
extract(epoch FROM transaction_timestamp()) * 1000
)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 47
AND migration_id = 'pg-0048-worker-credential-preapproved-activation'
AND capabilities = '${CAPABILITIES_V47}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 47'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,69 @@
import { definePostgresSqlMigration } from './sqlMigration';
const CAPABILITIES_V48 =
'{"api_credential":1,"api_credential_admin":1,"api_credential_pepper_binding":1,"approved_action":1,"approved_action_execution":1,"cluster_execution_revision":1,"cluster_recovery":1,"cluster_recovery_claim":1,"cluster_scheduler_admission":1,"database_role_grants":1,"identity_admin":1,"plugin_package_admission":1,"plugin_package_authority_split":1,"plugin_package_automation_publication":1,"plugin_package_automation_start_guard":1,"plugin_package_identity_keyset_ledger":1,"plugin_package_install":1,"plugin_package_lifecycle":1,"plugin_package_lifecycle_plan":1,"plugin_package_management_quota":1,"plugin_package_materialized_revision":1,"plugin_package_proposal":1,"plugin_package_publisher_provenance":1,"plugin_package_publisher_trust_authority":1,"plugin_package_publisher_trust_transition":1,"plugin_package_quarantine":1,"plugin_package_task_reconciliation":1,"plugin_package_workflow_admission":1,"plugin_package_workflow_task_attempt_admission":1,"project_policy":1,"project_tool_definition_snapshot":1,"run_core":1,"run_dispatch_lease":1,"run_retry_policy":1,"security_audit":1,"security_audit_query":1,"step_run":1,"task_definition":1,"tool_execution_artifact_binding":1,"tool_execution_completion":1,"tool_execution_evidence":1,"tool_execution_failure_completion":1,"tool_execution_start_barrier":1,"tool_invocation_artifact":1,"tool_result_key_catalog":1,"tool_result_rekey":1,"trigger_definition":1,"worker_attestation":1,"worker_credential":1,"worker_credential_delivery":1,"worker_credential_execution_receipt":1,"worker_credential_management_plan":1,"worker_credential_preapproved_activation":1,"worker_credential_stage_discard":1,"worker_session":1}';
export const CAPABILITIES_V49 = CAPABILITIES_V48.replace(
'"worker_credential_management_plan":1,',
'"worker_credential_management_identity_keyset_ledger":1,"worker_credential_management_plan":1,"worker_credential_management_quota":1,',
);
export const pg0050WorkerCredentialManagementBoundaryMigration =
definePostgresSqlMigration({
id: 'pg-0050-worker-credential-management-boundary',
statements: [
`
CREATE TABLE "ql3"."worker_credential_management_quota_buckets" (
project_id varchar(128) NOT NULL,
subject_type varchar(32) NOT NULL,
subject_id varchar(255) NOT NULL,
operation varchar(64) NOT NULL,
window_started_at_ms bigint NOT NULL,
consumed_count integer NOT NULL,
receipt_ids jsonb NOT NULL,
updated_at_ms bigint NOT NULL,
CONSTRAINT worker_credential_management_quota_buckets_pkey
PRIMARY KEY (project_id, subject_type, subject_id, operation),
CONSTRAINT ql3_worker_credential_management_quota_project_fk
FOREIGN KEY (project_id) REFERENCES "ql3"."projects"(id) ON DELETE RESTRICT,
CONSTRAINT ql3_worker_credential_management_quota_identity_check
CHECK (subject_type = 'user' AND char_length(subject_id) BETWEEN 1 AND 255
AND subject_id !~ '[[:cntrl:]]'),
CONSTRAINT ql3_worker_credential_management_quota_operation_check
CHECK (operation IN ('worker-credential.plan', 'worker-credential.propose',
'worker-credential.decide', 'worker-credential.inspect')),
CONSTRAINT ql3_worker_credential_management_quota_window_check
CHECK (window_started_at_ms >= 0 AND consumed_count BETWEEN 1 AND 1000
AND updated_at_ms >= window_started_at_ms),
CONSTRAINT ql3_worker_credential_management_quota_receipts_check
CHECK (jsonb_typeof(receipt_ids) = 'array'
AND jsonb_array_length(receipt_ids) = consumed_count
AND octet_length(receipt_ids::text) BETWEEN 3 AND 262144)
)
`.trim(),
`REVOKE ALL ON "ql3"."worker_credential_management_quota_buckets" FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager, ql3_package_executor, ql3_worker_ingress, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."worker_credential_management_quota_buckets" TO ql3_worker_credential_manager`,
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" DROP CONSTRAINT ql3_plugin_package_identity_keyset_authority_check`,
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" ADD CONSTRAINT ql3_plugin_package_identity_keyset_authority_check CHECK (authority IN ('plugin-package-management', 'worker-credential-management'))`,
`REVOKE ALL ON "ql3"."plugin_package_identity_keyset_ledger" FROM ql3_worker_credential_manager, ql3_worker_credential_executor`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."plugin_package_identity_keyset_ledger" TO ql3_worker_credential_manager`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 49,
migration_id = 'pg-0050-worker-credential-management-boundary',
capabilities = '${CAPABILITIES_V49}'::jsonb,
updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 48
AND migration_id = 'pg-0049-worker-credential-execution-receipts'
AND capabilities = '${CAPABILITIES_V48}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 48'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,77 @@
import { CAPABILITIES_V49 } from './pg-0050-worker-credential-management-boundary';
import { definePostgresSqlMigration } from './sqlMigration';
export const CAPABILITIES_V50 = CAPABILITIES_V49.replace(
'"approved_action":1,',
'"approved_action":1,"automation_management_boundary":1,',
);
export const pg0051AutomationManagementBoundaryMigration =
definePostgresSqlMigration({
id: 'pg-0051-automation-management-boundary',
statements: [
`
DO $ql3$
DECLARE
role_invalid boolean;
BEGIN
SELECT roles.rolname IS NULL
OR roles.rolcanlogin IS NOT TRUE
OR roles.rolsuper IS NOT FALSE
OR roles.rolcreatedb IS NOT FALSE
OR roles.rolcreaterole IS NOT FALSE
OR roles.rolreplication IS NOT FALSE
OR roles.rolbypassrls IS NOT FALSE
INTO role_invalid
FROM (SELECT 1) AS expected
LEFT JOIN pg_catalog.pg_roles AS roles
ON roles.rolname = 'ql3_automation_manager';
IF role_invalid IS NOT FALSE THEN
RAISE EXCEPTION
'required QingLong automation manager role is missing or privileged'
USING ERRCODE = 'insufficient_privilege';
END IF;
END
$ql3$
`.trim(),
`
DO $ql3$
BEGIN
EXECUTE format(
'GRANT CONNECT ON DATABASE %I TO ql3_automation_manager',
current_database()
);
END
$ql3$
`.trim(),
`GRANT USAGE ON SCHEMA "ql3" TO ql3_automation_manager`,
`REVOKE ALL ON ALL TABLES IN SCHEMA "ql3" FROM ql3_automation_manager`,
`REVOKE ALL ON ALL FUNCTIONS IN SCHEMA "ql3" FROM ql3_automation_manager`,
`GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities", "ql3"."projects", "ql3"."project_role_bindings", "ql3"."plugin_package_task_ownerships" TO ql3_automation_manager`,
`GRANT SELECT, INSERT ON "ql3"."security_audit_events" TO ql3_automation_manager`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."task_definitions", "ql3"."triggers", "ql3"."trigger_schedules" TO ql3_automation_manager`,
`GRANT SELECT, INSERT ON "ql3"."task_definition_revisions", "ql3"."task_execution_revisions", "ql3"."trigger_revisions" TO ql3_automation_manager`,
`REVOKE SELECT, INSERT, UPDATE ON "ql3"."task_definitions", "ql3"."triggers", "ql3"."trigger_schedules" FROM ql3_admin`,
`REVOKE SELECT, INSERT ON "ql3"."task_definition_revisions", "ql3"."task_execution_revisions", "ql3"."trigger_revisions" FROM ql3_admin`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 50,
migration_id = 'pg-0051-automation-management-boundary',
capabilities = '${CAPABILITIES_V50}'::jsonb,
updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 49
AND migration_id = 'pg-0050-worker-credential-management-boundary'
AND capabilities = '${CAPABILITIES_V49}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 49'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,37 @@
import { CAPABILITIES_V50 } from './pg-0051-automation-management-boundary';
import { definePostgresSqlMigration } from './sqlMigration';
export const CAPABILITIES_V51 = CAPABILITIES_V50.replace(
'"automation_management_boundary":1,',
'"automation_management_boundary":1,"automation_management_identity_keyset_ledger":1,',
);
export const pg0052AutomationManagementIdentityKeysetLedgerMigration =
definePostgresSqlMigration({
id: 'pg-0052-automation-management-identity-keyset-ledger',
statements: [
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" DROP CONSTRAINT ql3_plugin_package_identity_keyset_authority_check`,
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" ADD CONSTRAINT ql3_plugin_package_identity_keyset_authority_check CHECK (authority IN ('plugin-package-management', 'worker-credential-management', 'automation-management'))`,
`REVOKE ALL ON "ql3"."plugin_package_identity_keyset_ledger" FROM ql3_automation_manager`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."plugin_package_identity_keyset_ledger" TO ql3_automation_manager`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 51,
migration_id = 'pg-0052-automation-management-identity-keyset-ledger',
capabilities = '${CAPABILITIES_V51}'::jsonb,
updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 50
AND migration_id = 'pg-0051-automation-management-boundary'
AND capabilities = '${CAPABILITIES_V50}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 50'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,34 @@
import { CAPABILITIES_V51 } from './pg-0052-automation-management-identity-keyset-ledger';
import { definePostgresSqlMigration } from './sqlMigration';
export const CAPABILITIES_V52 = CAPABILITIES_V51.replace(
'"plugin_package_workflow_admission":1,',
'"plugin_package_workflow_admission":1,"plugin_package_workflow_run_list":1,',
);
export const pg0053PluginPackageWorkflowRunListIndexMigration =
definePostgresSqlMigration({
id: 'pg-0053-plugin-package-workflow-run-list-index',
statements: [
`CREATE INDEX ql3_plugin_package_workflow_admission_workflow_history_idx ON "ql3"."plugin_package_workflow_admissions" (project_id, package_name, workflow_id, admitted_at_ms, run_id)`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 52,
migration_id = 'pg-0053-plugin-package-workflow-run-list-index',
capabilities = '${CAPABILITIES_V52}'::jsonb,
updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 51
AND migration_id = 'pg-0052-automation-management-identity-keyset-ledger'
AND capabilities = '${CAPABILITIES_V51}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 51'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,78 @@
import { CAPABILITIES_V52 } from './pg-0053-plugin-package-workflow-run-list-index';
import { definePostgresSqlMigration } from './sqlMigration';
export const CAPABILITIES_V53 = CAPABILITIES_V52.replace(
'"approved_action":1,',
'"approval_management_boundary":1,"approved_action":1,',
);
export const pg0054ApprovalManagementBoundaryMigration =
definePostgresSqlMigration({
id: 'pg-0054-approval-management-boundary',
statements: [
`
DO $ql3$
DECLARE
role_invalid boolean;
BEGIN
SELECT roles.rolname IS NULL
OR roles.rolcanlogin IS NOT TRUE
OR roles.rolsuper IS NOT FALSE
OR roles.rolcreatedb IS NOT FALSE
OR roles.rolcreaterole IS NOT FALSE
OR roles.rolreplication IS NOT FALSE
OR roles.rolbypassrls IS NOT FALSE
INTO role_invalid
FROM (SELECT 1) AS expected
LEFT JOIN pg_catalog.pg_roles AS roles
ON roles.rolname = 'ql3_approval_manager';
IF role_invalid IS NOT FALSE THEN
RAISE EXCEPTION
'required QingLong approval manager role is missing or privileged'
USING ERRCODE = 'insufficient_privilege';
END IF;
END
$ql3$
`.trim(),
`
DO $ql3$
BEGIN
EXECUTE format(
'GRANT CONNECT ON DATABASE %I TO ql3_approval_manager',
current_database()
);
END
$ql3$
`.trim(),
`GRANT USAGE ON SCHEMA "ql3" TO ql3_approval_manager`,
`REVOKE ALL ON ALL TABLES IN SCHEMA "ql3" FROM ql3_approval_manager`,
`REVOKE ALL ON ALL FUNCTIONS IN SCHEMA "ql3" FROM ql3_approval_manager`,
`GRANT SELECT ON "ql3"."schema_migrations", "ql3"."schema_capabilities", "ql3"."projects", "ql3"."project_role_bindings", "ql3"."tool_invocation_preview_artifacts" TO ql3_approval_manager`,
`GRANT SELECT, INSERT ON "ql3"."security_audit_events" TO ql3_approval_manager`,
`GRANT SELECT, UPDATE ON "ql3"."approval_requests" TO ql3_approval_manager`,
`GRANT SELECT, INSERT, UPDATE ON "ql3"."plugin_package_identity_keyset_ledger" TO ql3_approval_manager`,
`GRANT EXECUTE ON FUNCTION "ql3"."lock_approval_policy_fence"(varchar, varchar, varchar, integer, integer) TO ql3_approval_manager`,
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" DROP CONSTRAINT ql3_plugin_package_identity_keyset_authority_check`,
`ALTER TABLE "ql3"."plugin_package_identity_keyset_ledger" ADD CONSTRAINT ql3_plugin_package_identity_keyset_authority_check CHECK (authority IN ('plugin-package-management', 'worker-credential-management', 'automation-management', 'approval-management'))`,
`
DO $ql3$
BEGIN
UPDATE "ql3"."schema_capabilities"
SET contract_version = 53,
migration_id = 'pg-0054-approval-management-boundary',
capabilities = '${CAPABILITIES_V53}'::jsonb,
updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
WHERE contract_name = 'control-core'
AND contract_version = 52
AND migration_id = 'pg-0053-plugin-package-workflow-run-list-index'
AND capabilities = '${CAPABILITIES_V52}'::jsonb;
IF NOT FOUND THEN
RAISE EXCEPTION 'control-core capability is not at version 52'
USING ERRCODE = 'check_violation';
END IF;
END
$ql3$
`.trim(),
],
});
@@ -0,0 +1,262 @@
import {
MigrationStreamHistoryCorruptionError,
type MigrationStreamRecord,
type MigrationStreamStore,
type MigrationStreamTransaction,
} from '@qinglong/runtime-core';
import type {
PostgresClient as PostgresMigrationClient,
PostgresPool as PostgresMigrationPool,
PostgresQueryable as PostgresMigrationQueryable,
PostgresQueryResult as PostgresMigrationQueryResult,
} from '@qinglong/runtime-core';
export type {
PostgresClient as PostgresMigrationClient,
PostgresPool as PostgresMigrationPool,
PostgresQueryable as PostgresMigrationQueryable,
PostgresQueryResult as PostgresMigrationQueryResult,
} from '@qinglong/runtime-core';
export const POSTGRESQL_MAIN_MIGRATION_STREAM_ID = 'postgresql-main';
export const POSTGRESQL_MIGRATION_SCHEMA = 'ql3';
export const POSTGRESQL_MIGRATION_HISTORY_TABLE = 'schema_migrations';
const POSTGRESQL_MIGRATION_LOCK_KEY = [0x514c, 0x0300] as const;
const POSTGRESQL_MIGRATION_STATEMENT_TIMEOUT_MS = 15_000;
const POSTGRESQL_MIGRATION_LOCK_TIMEOUT_MS = 5_000;
const POSTGRESQL_MIGRATION_IDLE_TRANSACTION_TIMEOUT_MS = 15_000;
export type PostgresMigrationContext = PostgresMigrationQueryable;
export class PostgresMigrationLeaderUnavailableError extends Error {
constructor() {
super('PostgreSQL migration leader lock is unavailable');
this.name = 'PostgresMigrationLeaderUnavailableError';
}
}
interface HistoryRow extends Record<string, unknown> {
streamId: unknown;
dialect: unknown;
migrationId: unknown;
checksum: unknown;
appliedAtMs: unknown;
}
interface AdvisoryLockRow extends Record<string, unknown> {
acquired: unknown;
}
const CREATE_HISTORY_SQL = `
CREATE TABLE IF NOT EXISTS "${POSTGRESQL_MIGRATION_SCHEMA}"."${POSTGRESQL_MIGRATION_HISTORY_TABLE}" (
migration_id varchar(128) PRIMARY KEY,
stream_id varchar(64) NOT NULL,
dialect varchar(16) NOT NULL
CONSTRAINT ql3_schema_migrations_dialect_check
CHECK (dialect = 'postgresql'),
checksum char(64) NOT NULL
CONSTRAINT ql3_schema_migrations_checksum_check
CHECK (checksum ~ '^[0-9a-f]{64}$'),
applied_at_ms bigint NOT NULL
CONSTRAINT ql3_schema_migrations_applied_at_check
CHECK (applied_at_ms >= 0)
)`.trim();
const SELECT_HISTORY_SQL = `
SELECT
stream_id AS "streamId",
dialect,
migration_id AS "migrationId",
checksum,
applied_at_ms AS "appliedAtMs"
FROM "${POSTGRESQL_MIGRATION_SCHEMA}"."${POSTGRESQL_MIGRATION_HISTORY_TABLE}"
WHERE migration_id = $1
`.trim();
const SELECT_ALL_HISTORY_SQL = `
SELECT
stream_id AS "streamId",
dialect,
migration_id AS "migrationId",
checksum,
applied_at_ms AS "appliedAtMs"
FROM "${POSTGRESQL_MIGRATION_SCHEMA}"."${POSTGRESQL_MIGRATION_HISTORY_TABLE}"
ORDER BY applied_at_ms, migration_id
`.trim();
const INSERT_HISTORY_SQL = `
INSERT INTO "${POSTGRESQL_MIGRATION_SCHEMA}"."${POSTGRESQL_MIGRATION_HISTORY_TABLE}" (
migration_id,
stream_id,
dialect,
checksum,
applied_at_ms
)
VALUES ($1, $2, $3, $4, $5)
`.trim();
function parseAppliedAtMs(value: unknown, migrationId: string): number {
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) {
return value;
}
if (typeof value === 'string' && /^(0|[1-9]\d*)$/.test(value)) {
const parsed = Number(value);
if (Number.isSafeInteger(parsed)) return parsed;
}
throw new MigrationStreamHistoryCorruptionError(migrationId);
}
async function findHistoryRecord(
queryable: PostgresMigrationQueryable,
migrationId: string,
): Promise<MigrationStreamRecord | null> {
const result = await queryable.query<HistoryRow>(SELECT_HISTORY_SQL, [
migrationId,
]);
if (result.rows.length === 0) return null;
if (result.rows.length !== 1) {
throw new MigrationStreamHistoryCorruptionError(migrationId);
}
const row = result.rows[0];
if (!row) {
throw new MigrationStreamHistoryCorruptionError(migrationId);
}
return {
streamId: row.streamId as string,
dialect: row.dialect as 'postgresql',
migrationId: row.migrationId as string,
checksum: row.checksum as string,
appliedAtMs: parseAppliedAtMs(row.appliedAtMs, migrationId),
};
}
export async function readPostgresMigrationHistory(
queryable: PostgresMigrationQueryable,
): Promise<readonly MigrationStreamRecord[]> {
const result = await queryable.query<HistoryRow>(SELECT_ALL_HISTORY_SQL);
return result.rows.map((row) => ({
streamId: row.streamId as string,
dialect: row.dialect as 'postgresql',
migrationId: row.migrationId as string,
checksum: row.checksum as string,
appliedAtMs: parseAppliedAtMs(
row.appliedAtMs,
typeof row.migrationId === 'string' ? row.migrationId : 'unknown',
),
}));
}
async function configureTransaction(
client: PostgresMigrationClient,
): Promise<void> {
await client.query(`SELECT set_config('statement_timeout', $1, true)`, [
`${POSTGRESQL_MIGRATION_STATEMENT_TIMEOUT_MS}ms`,
]);
await client.query(`SELECT set_config('lock_timeout', $1, true)`, [
`${POSTGRESQL_MIGRATION_LOCK_TIMEOUT_MS}ms`,
]);
await client.query(
`SELECT set_config('idle_in_transaction_session_timeout', $1, true)`,
[`${POSTGRESQL_MIGRATION_IDLE_TRANSACTION_TIMEOUT_MS}ms`],
);
}
async function acquireLeaderLock(
client: PostgresMigrationClient,
): Promise<void> {
const result = await client.query<AdvisoryLockRow>(
'SELECT pg_try_advisory_xact_lock($1, $2) AS acquired',
POSTGRESQL_MIGRATION_LOCK_KEY,
);
if (result.rows.length !== 1 || result.rows[0]?.acquired !== true) {
throw new PostgresMigrationLeaderUnavailableError();
}
}
/**
* PostgreSQL migration history adapter without a runtime dependency on `pg`.
* The cluster-only package owns the concrete Pool binding; edge and standalone
* builds can compile this contract without installing or importing the driver.
*/
export class PostgresMigrationStreamStore
implements MigrationStreamStore<PostgresMigrationContext>
{
constructor(private readonly pool: PostgresMigrationPool) {}
async ensureHistory(): Promise<void> {
await this.withLeaderTransaction(async (client) => {
await client.query(
`CREATE SCHEMA IF NOT EXISTS "${POSTGRESQL_MIGRATION_SCHEMA}"`,
);
await client.query(CREATE_HISTORY_SQL);
});
}
async findById(migrationId: string): Promise<MigrationStreamRecord | null> {
return findHistoryRecord(this.pool, migrationId);
}
async listAll(): Promise<readonly MigrationStreamRecord[]> {
return readPostgresMigrationHistory(this.pool);
}
async transaction<T>(
work: (
transaction: MigrationStreamTransaction<PostgresMigrationContext>,
) => Promise<T>,
): Promise<T> {
return this.withLeaderTransaction(async (client) =>
work({
context: client,
findById: (migrationId) => findHistoryRecord(client, migrationId),
insert: async (record) => {
if (
record.streamId !== POSTGRESQL_MAIN_MIGRATION_STREAM_ID ||
record.dialect !== 'postgresql'
) {
throw new TypeError(
'PostgreSQL migration history record has the wrong stream or dialect',
);
}
await client.query(INSERT_HISTORY_SQL, [
record.migrationId,
record.streamId,
record.dialect,
record.checksum,
record.appliedAtMs,
]);
},
}),
);
}
private async withLeaderTransaction<T>(
work: (client: PostgresMigrationClient) => Promise<T>,
): Promise<T> {
const client = await this.pool.connect();
let began = false;
try {
await client.query('BEGIN');
began = true;
await configureTransaction(client);
await acquireLeaderLock(client);
const result = await work(client);
await client.query('COMMIT');
began = false;
return result;
} catch (error) {
if (began) {
try {
await client.query('ROLLBACK');
} catch {
// Preserve the migration error. A broken connection is discarded by
// the concrete driver when release() runs.
}
}
throw error;
} finally {
client.release();
}
}
}
@@ -0,0 +1,34 @@
import { createHash } from 'crypto';
import type { MigrationStreamStep } from '@qinglong/runtime-core';
import type { PostgresMigrationContext } from './postgresMigrationStreamStore';
export interface PostgresSqlMigrationDefinition {
readonly id: string;
readonly statements: readonly string[];
}
export function checksumPostgresStatements(
statements: readonly string[],
): string {
return createHash('sha256')
.update(
JSON.stringify({
format: 1,
statements,
}),
)
.digest('hex');
}
export function definePostgresSqlMigration(
definition: PostgresSqlMigrationDefinition,
): MigrationStreamStep<PostgresMigrationContext> {
const statements = Object.freeze([...definition.statements]);
return Object.freeze({
id: definition.id,
checksum: checksumPostgresStatements(statements),
async up(context: PostgresMigrationContext) {
for (const statement of statements) await context.query(statement);
},
});
}