import { sql } from 'drizzle-orm'; // Canonical Drizzle declaration of the complete Local SQLite storage contract. import { type AnySQLiteColumn, blob, check, foreignKey, index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from 'drizzle-orm/sqlite-core'; export const localSchemaMigrations = sqliteTable( 'QingLong3SchemaMigrations', { migrationId: text('migration_id').primaryKey(), streamId: text('stream_id').notNull(), dialect: text('dialect').notNull(), checksum: text('checksum').notNull(), appliedAtMs: integer('applied_at_ms').notNull(), }, (table) => [ check( 'ql3_local_migrations_dialect_check', sql`${table.dialect} = 'sqlite'`, ), check( 'ql3_local_migrations_checksum_check', sql`length(${table.checksum}) = 64 and ${table.checksum} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_migrations_applied_at_check', sql`${table.appliedAtMs} >= 0`, ), ], ); export const localSchemaCapabilities = sqliteTable( 'QingLong3SchemaCapabilities', { contractName: text('contract_name').primaryKey(), contractVersion: integer('contract_version').notNull(), migrationId: text('migration_id') .notNull() .references(() => localSchemaMigrations.migrationId), capabilities: text('capabilities', { mode: 'json' }) .$type>() .notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_local_capabilities_version_check', sql`${table.contractVersion} >= 1`, ), check( 'ql3_local_capabilities_json_check', sql`json_valid(${table.capabilities}) and json_type(${table.capabilities}) = 'object'`, ), check( 'ql3_local_capabilities_updated_at_check', sql`${table.updatedAtMs} >= 0`, ), ], ); export const runs = sqliteTable( 'Runs', { id: text('id').primaryKey(), projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), taskRevision: text('task_revision').notNull(), taskName: text('task_name'), taskSnapshotRef: text('task_snapshot_ref'), legacyCronId: integer('legacy_cron_id'), parentRunId: text('parent_run_id').references( (): AnySQLiteColumn => runs.id, ), retryOfRunId: text('retry_of_run_id').references( (): AnySQLiteColumn => runs.id, ), triggerId: text('trigger_id'), triggerType: text('trigger_type').notNull(), executionOrigin: text('execution_origin').notNull(), executionOwner: text('execution_owner').notNull(), triggeredBy: text('triggered_by'), requestId: text('request_id'), scheduledForMs: integer('scheduled_for_ms'), status: text('status').notNull(), version: integer('version').notNull().default(0), eventSequence: integer('event_sequence').notNull().default(0), priority: integer('priority').notNull().default(0), idempotencyKey: text('idempotency_key'), inputRef: text('input_ref'), outputRef: text('output_ref'), createdAtMs: integer('created_at_ms').notNull(), queuedAtMs: integer('queued_at_ms'), startedAtMs: integer('started_at_ms'), finishedAtMs: integer('finished_at_ms'), cancelRequestedAtMs: integer('cancel_requested_at_ms'), cancelReason: text('cancel_reason'), errorCode: text('error_code'), errorSummary: text('error_summary'), }, (table) => [ check( 'ql3_local_runs_execution_origin_check', sql`${table.executionOrigin} in ('manual','scheduled_system','scheduled_node','once','boot','grpc','subscription','system','script','legacy_import')`, ), check( 'ql3_local_runs_execution_owner_check', sql`${table.executionOwner} in ('legacy','runtime')`, ), check( 'ql3_local_runs_status_check', sql`${table.status} in ('created','queued','dispatching','running','waiting_approval','retry_wait','lost','succeeded','failed','cancelled','timed_out')`, ), check('ql3_local_runs_version_check', sql`${table.version} >= 0`), check( 'ql3_local_runs_event_sequence_check', sql`${table.eventSequence} >= 0`, ), check( 'ql3_local_runs_time_check', sql`${table.createdAtMs} >= 0 and (${table.scheduledForMs} is null or ${table.scheduledForMs} >= 0) and (${table.queuedAtMs} is null or ${table.queuedAtMs} >= 0) and (${table.startedAtMs} is null or ${table.startedAtMs} >= 0) and (${table.finishedAtMs} is null or ${table.finishedAtMs} >= 0) and (${table.cancelRequestedAtMs} is null or ${table.cancelRequestedAtMs} >= 0)`, ), check( 'ql3_local_runs_cancel_reason_check', sql`${table.cancelReason} is null or ${table.cancelReason} in ('user','policy','shutdown','reconcile','timeout')`, ), uniqueIndex('ql3_local_runs_project_idempotency_uidx') .on(table.projectId, table.idempotencyKey) .where(sql`${table.idempotencyKey} is not null`), index('ql3_local_runs_project_created_idx').on( table.projectId, table.createdAtMs, table.id, ), index('ql3_local_runs_task_created_idx').on( table.taskId, table.createdAtMs, table.id, ), index('ql3_local_runs_cancel_requested_idx').on( table.status, table.cancelRequestedAtMs, table.id, ), index('ql3_local_runs_lost_retry_idx').on( table.executionOwner, table.status, table.id, ), index('ql3_local_runs_dispatch_idx') .on( table.executionOwner, table.status, sql`${table.priority} desc`, table.queuedAtMs, table.id, ) .where( sql`${table.executionOwner} = 'runtime' and ${table.status} = 'queued' and ${table.cancelRequestedAtMs} is null`, ), ], ); export const stepRuns = sqliteTable( 'StepRuns', { id: text('id').primaryKey(), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'cascade' }), parentStepRunId: text('parent_step_run_id'), stepKey: text('step_key').notNull(), kind: text('kind').notNull(), definitionRef: text('definition_ref').notNull(), definitionDigest: text('definition_digest').notNull(), required: integer('required', { mode: 'boolean' }).notNull(), status: text('status').notNull(), version: integer('version').notNull(), attemptCount: integer('attempt_count').notNull(), inputRef: text('input_ref'), outputRef: text('output_ref'), approvalRequestId: text('approval_request_id'), readyAtMs: integer('ready_at_ms'), startedAtMs: integer('started_at_ms'), finishedAtMs: integer('finished_at_ms'), resultCode: text('result_code'), errorSummary: text('error_summary'), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), lastMutationId: text('last_mutation_id').notNull(), stepRunDigest: text('step_run_digest').notNull(), stepRunJson: text('step_run_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.runId, table.parentStepRunId], foreignColumns: [table.runId, table.id], name: 'ql3_step_runs_parent_fk', }).onDelete('restrict'), check( 'ql3_step_runs_identity_check', sql`length(${table.id}) between 1 and 128 and length(${table.runId}) between 1 and 128 and (${table.parentStepRunId} is null or (length(${table.parentStepRunId}) between 1 and 128 and ${table.parentStepRunId} <> ${table.id})) and length(${table.stepKey}) between 1 and 128 and length(cast(${table.definitionRef} as blob)) between 1 and 512`, ), check( 'ql3_step_runs_kind_check', sql`${table.kind} in ('task','tool','model','agent','condition','approval','subworkflow')`, ), check( 'ql3_step_runs_status_check', sql`${table.status} in ('pending','ready','waiting_approval','running','lost','succeeded','failed','skipped','cancelled','timed_out')`, ), check( 'ql3_step_runs_digest_check', sql`length(${table.definitionDigest}) = 64 and ${table.definitionDigest} not glob '*[^0-9a-f]*' and length(${table.stepRunDigest}) = 64 and ${table.stepRunDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_step_runs_counter_check', sql`${table.required} in (0, 1) and ${table.version} between 1 and 2147483647 and ${table.attemptCount} between 0 and 64`, ), check( 'ql3_step_runs_reference_check', sql`(${table.inputRef} is null or length(cast(${table.inputRef} as blob)) between 1 and 512) and (${table.outputRef} is null or length(cast(${table.outputRef} as blob)) between 1 and 512) and (${table.approvalRequestId} is null or length(${table.approvalRequestId}) between 1 and 128)`, ), check( 'ql3_step_runs_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs} and (${table.readyAtMs} is null or ${table.readyAtMs} between ${table.createdAtMs} and ${table.updatedAtMs}) and (${table.startedAtMs} is null or (${table.readyAtMs} is not null and ${table.startedAtMs} between ${table.readyAtMs} and ${table.updatedAtMs})) and (${table.finishedAtMs} is null or (${table.finishedAtMs} between ${table.createdAtMs} and ${table.updatedAtMs} and (${table.readyAtMs} is null or ${table.finishedAtMs} >= ${table.readyAtMs}) and (${table.startedAtMs} is null or ${table.finishedAtMs} >= ${table.startedAtMs})))`, ), check( 'ql3_step_runs_state_shape_check', sql`(${table.status} = 'pending' and ${table.readyAtMs} is null and ${table.startedAtMs} is null and ${table.finishedAtMs} is null) or (${table.status} in ('ready','waiting_approval') and ${table.readyAtMs} is not null and ${table.startedAtMs} is null and ${table.finishedAtMs} is null) or (${table.status} in ('running','lost') and ${table.readyAtMs} is not null and ${table.startedAtMs} is not null and ${table.finishedAtMs} is null) or (${table.status} in ('succeeded','failed','skipped','cancelled','timed_out') and ${table.finishedAtMs} is not null)`, ), check( 'ql3_step_runs_result_shape_check', sql`(${table.status} = 'waiting_approval' and ${table.approvalRequestId} is not null) or ${table.status} <> 'waiting_approval'`, ), check( 'ql3_step_runs_result_value_check', sql`(${table.outputRef} is null or ${table.status} = 'succeeded') and ((${table.status} = 'succeeded' and ${table.resultCode} is null and ${table.errorSummary} is null) or (${table.status} in ('failed','skipped','cancelled','timed_out','lost') and ${table.resultCode} is not null) or (${table.status} in ('pending','ready','waiting_approval','running') and ${table.resultCode} is null and ${table.errorSummary} is null)) and (${table.resultCode} is null or (length(${table.resultCode}) between 1 and 64 and ${table.resultCode} not glob '*[^a-z0-9_]*' and substr(${table.resultCode}, 1, 1) glob '[a-z]')) and (${table.errorSummary} is null or length(cast(${table.errorSummary} as blob)) between 1 and 2048)`, ), check( 'ql3_step_runs_mutation_identity_check', sql`length(${table.lastMutationId}) between 1 and 128`, ), check( 'ql3_step_runs_json_check', sql`length(cast(${table.stepRunJson} as blob)) between 2 and 16384 and json_valid(${table.stepRunJson}) and json_type(${table.stepRunJson}) = 'object' and json_extract(${table.stepRunJson}, '$.schema') = 'qinglong/step-run@v1' and json_extract(${table.stepRunJson}, '$.id') = ${table.id} and json_extract(${table.stepRunJson}, '$.runId') = ${table.runId} and json_extract(${table.stepRunJson}, '$.parentStepRunId') is ${table.parentStepRunId} and json_extract(${table.stepRunJson}, '$.stepKey') = ${table.stepKey} and json_extract(${table.stepRunJson}, '$.kind') = ${table.kind} and json_extract(${table.stepRunJson}, '$.definitionRef') = ${table.definitionRef} and json_extract(${table.stepRunJson}, '$.definitionDigest') = ${table.definitionDigest} and json_extract(${table.stepRunJson}, '$.required') is ${table.required} and json_extract(${table.stepRunJson}, '$.status') = ${table.status} and json_extract(${table.stepRunJson}, '$.version') = ${table.version} and json_extract(${table.stepRunJson}, '$.attemptCount') is ${table.attemptCount} and json_extract(${table.stepRunJson}, '$.inputRef') is ${table.inputRef} and json_extract(${table.stepRunJson}, '$.outputRef') is ${table.outputRef} and json_extract(${table.stepRunJson}, '$.approvalRequestId') is ${table.approvalRequestId} and json_extract(${table.stepRunJson}, '$.readyAtMs') is ${table.readyAtMs} and json_extract(${table.stepRunJson}, '$.startedAtMs') is ${table.startedAtMs} and json_extract(${table.stepRunJson}, '$.finishedAtMs') is ${table.finishedAtMs} and json_extract(${table.stepRunJson}, '$.resultCode') is ${table.resultCode} and json_extract(${table.stepRunJson}, '$.errorSummary') is ${table.errorSummary} and json_extract(${table.stepRunJson}, '$.createdAtMs') is ${table.createdAtMs} and json_extract(${table.stepRunJson}, '$.updatedAtMs') is ${table.updatedAtMs} and json_extract(${table.stepRunJson}, '$.lastMutationId') = ${table.lastMutationId} and json_extract(${table.stepRunJson}, '$.stepRunDigest') = ${table.stepRunDigest}`, ), uniqueIndex('ql3_step_runs_run_id_uidx').on(table.runId, table.id), uniqueIndex('ql3_step_runs_run_step_uidx').on(table.runId, table.stepKey), index('ql3_step_runs_run_status_idx').on( table.runId, table.status, table.id, ), index('ql3_step_runs_recovery_idx') .on(table.status, table.updatedAtMs, table.id) .where(sql`${table.status} in ('waiting_approval','running','lost')`), ], ); export const runAttempts = sqliteTable( 'RunAttempts', { id: text('id').primaryKey(), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'cascade' }), stepRunId: text('step_run_id'), attempt: integer('attempt').notNull(), status: text('status').notNull(), executorType: text('executor_type').notNull(), workerId: text('worker_id'), workerSessionId: text('worker_session_id'), workerGeneration: integer('worker_generation'), executorHandle: text('executor_handle'), pid: integer('pid'), logArtifactId: text('log_artifact_id'), leaseToken: text('lease_token'), leaseTokenDigest: text('lease_token_digest'), leaseGeneration: integer('lease_generation'), leaseVersion: integer('lease_version'), leaseExpiresAtMs: integer('lease_expires_at_ms'), offerId: text('offer_id'), deadlineAtMs: integer('deadline_at_ms'), callbackTokenHash: text('callback_token_hash'), callbackSequence: integer('callback_sequence').notNull().default(0), createdAtMs: integer('created_at_ms').notNull(), startedAtMs: integer('started_at_ms'), finishedAtMs: integer('finished_at_ms'), exitCode: integer('exit_code'), errorCode: text('error_code'), errorSummary: text('error_summary'), }, (table) => [ check('ql3_local_attempts_attempt_check', sql`${table.attempt} >= 1`), check( 'ql3_local_attempts_status_check', sql`${table.status} in ('claimed','starting','running','succeeded','failed','cancelled','timed_out','lost')`, ), check( 'ql3_local_attempts_callback_sequence_check', sql`${table.callbackSequence} >= 0`, ), check( 'ql3_local_attempts_time_check', sql`${table.createdAtMs} >= 0 and (${table.startedAtMs} is null or ${table.startedAtMs} >= 0) and (${table.finishedAtMs} is null or ${table.finishedAtMs} >= 0) and (${table.leaseExpiresAtMs} is null or ${table.leaseExpiresAtMs} >= 0) and (${table.deadlineAtMs} is null or ${table.deadlineAtMs} >= 0)`, ), uniqueIndex('ql3_local_attempts_run_attempt_uidx').on( table.runId, table.attempt, ), index('ql3_local_attempts_run_status_idx').on( table.runId, table.status, table.id, ), index('ql3_local_attempts_lease_idx').on(table.leaseExpiresAtMs, table.id), index('ql3_local_attempts_deadline_idx').on( table.status, table.deadlineAtMs, table.id, ), index('ql3_run_log_retention_candidate_idx') .on(table.executorType, table.status, table.finishedAtMs, table.id) .where(sql`${table.logArtifactId} is not null`), ], ); export const runEvents = sqliteTable( 'RunEvents', { id: text('id').primaryKey(), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'cascade' }), sequence: integer('sequence').notNull(), type: text('type').notNull(), dedupeKey: text('dedupe_key'), actorType: text('actor_type').notNull(), actorId: text('actor_id'), attemptId: text('attempt_id').references(() => runAttempts.id, { onDelete: 'set null', }), stepRunId: text('step_run_id'), payload: text('payload', { mode: 'json' }) .$type>() .notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check('ql3_local_events_sequence_check', sql`${table.sequence} >= 1`), check( 'ql3_local_events_actor_type_check', sql`${table.actorType} in ('user','api_app','trigger','agent','mcp_client','worker','executor','system','legacy_shell','scheduler','reconciler','compatibility')`, ), check( 'ql3_local_events_payload_check', sql`json_valid(${table.payload}) and json_type(${table.payload}) = 'object'`, ), check('ql3_local_events_created_at_check', sql`${table.createdAtMs} >= 0`), uniqueIndex('ql3_local_events_run_sequence_uidx').on( table.runId, table.sequence, ), uniqueIndex('ql3_local_events_run_dedupe_uidx') .on(table.runId, table.dedupeKey) .where(sql`${table.dedupeKey} is not null`), index('ql3_local_events_run_created_idx').on( table.runId, table.createdAtMs, table.id, ), ], ); export const stepRunMutations = sqliteTable( 'StepRunMutations', { mutationId: text('mutation_id').primaryKey(), mutationDigest: text('mutation_digest').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), stepRunDigest: text('step_run_digest').notNull(), eventId: text('event_id') .notNull() .references(() => runEvents.id, { onDelete: 'cascade' }), eventSequence: integer('event_sequence').notNull(), runVersion: integer('run_version').notNull(), stepRunJson: text('step_run_json', { mode: 'json' }) .$type>() .notNull(), committedAtMs: integer('committed_at_ms').notNull(), }, (table) => [ foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_step_run_mutations_step_fk', }).onDelete('cascade'), check( 'ql3_step_run_mutations_identity_check', sql`length(${table.mutationId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.eventId}) between 1 and 128`, ), check( 'ql3_step_run_mutations_digest_check', sql`length(${table.mutationDigest}) = 64 and ${table.mutationDigest} not glob '*[^0-9a-f]*' and length(${table.stepRunDigest}) = 64 and ${table.stepRunDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_step_run_mutations_counter_check', sql`${table.eventSequence} between 1 and 2147483647 and ${table.runVersion} between 1 and 2147483647 and ${table.committedAtMs} >= 0`, ), check( 'ql3_step_run_mutations_json_check', sql`length(cast(${table.stepRunJson} as blob)) between 2 and 16384 and json_valid(${table.stepRunJson}) and json_type(${table.stepRunJson}) = 'object' and json_extract(${table.stepRunJson}, '$.schema') = 'qinglong/step-run@v1' and json_extract(${table.stepRunJson}, '$.id') = ${table.stepRunId} and json_extract(${table.stepRunJson}, '$.runId') = ${table.runId} and json_extract(${table.stepRunJson}, '$.lastMutationId') = ${table.mutationId} and json_extract(${table.stepRunJson}, '$.stepRunDigest') = ${table.stepRunDigest}`, ), uniqueIndex('ql3_step_run_mutations_event_uidx').on(table.eventId), index('ql3_step_run_mutations_step_idx').on( table.runId, table.stepRunId, table.eventSequence, table.mutationId, ), ], ); export const runRetryPolicies = sqliteTable( 'RunRetryPolicies', { runId: text('run_id') .primaryKey() .references(() => runs.id, { onDelete: 'cascade' }), maxAttempts: integer('max_attempts').notNull(), retryOnLost: integer('retry_on_lost', { mode: 'boolean' }).notNull(), safety: text('safety').notNull(), backoffBaseMs: integer('backoff_base_ms').notNull(), backoffMaxMs: integer('backoff_max_ms').notNull(), nextAttemptAtMs: integer('next_attempt_at_ms'), version: integer('version').notNull().default(0), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_local_retry_max_attempts_check', sql`${table.maxAttempts} between 1 and 16`, ), check('ql3_local_retry_on_lost_check', sql`${table.retryOnLost} in (0, 1)`), check( 'ql3_local_retry_safety_check', sql`${table.safety} in ('unknown','idempotent','deduplicated')`, ), check( 'ql3_local_retry_backoff_check', sql`${table.backoffBaseMs} between 0 and 86400000 and ${table.backoffMaxMs} between ${table.backoffBaseMs} and 86400000`, ), check('ql3_local_retry_version_check', sql`${table.version} >= 0`), check( 'ql3_local_retry_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs} and (${table.nextAttemptAtMs} is null or ${table.nextAttemptAtMs} >= 0)`, ), index('ql3_local_retry_due_idx') .on(table.nextAttemptAtMs, table.runId) .where(sql`${table.nextAttemptAtMs} is not null`), ], ); export const localCompletionReceiptJournal = sqliteTable( 'LocalCompletionReceiptJournal', { attemptId: text('attempt_id') .primaryKey() .references(() => runAttempts.id, { onDelete: 'cascade' }), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'cascade' }), state: text('state').notNull(), quarantineRef: text('quarantine_ref'), purgeAfterMs: integer('purge_after_ms'), registeredAtMs: integer('registered_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_local_receipt_journal_state_check', sql`${table.state} in ('pending','quarantined')`, ), check( 'ql3_local_receipt_journal_time_check', sql`${table.registeredAtMs} >= 0 and ${table.updatedAtMs} >= ${table.registeredAtMs} and (${table.purgeAfterMs} is null or ${table.purgeAfterMs} >= ${table.updatedAtMs})`, ), check( 'ql3_local_receipt_journal_shape_check', sql`(${table.state} = 'pending' and ${table.quarantineRef} is null and ${table.purgeAfterMs} is null) or (${table.state} = 'quarantined' and ${table.quarantineRef} is not null and ${table.purgeAfterMs} is not null)`, ), index('ql3_local_receipt_journal_scan_idx').on( table.state, table.updatedAtMs, table.attemptId, ), index('ql3_local_receipt_journal_purge_idx') .on(table.purgeAfterMs, table.attemptId) .where(sql`${table.state} = 'quarantined'`), ], ); export const runAttemptLogArtifactTombstones = sqliteTable( 'QingLong3RunAttemptLogArtifactTombstones', { logArtifactId: text('log_artifact_id').primaryKey(), projectId: text('project_id').notNull(), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'cascade' }), attemptId: text('attempt_id') .notNull() .references(() => runAttempts.id, { onDelete: 'cascade' }), executorType: text('executor_type').notNull(), finishedAtMs: integer('finished_at_ms').notNull(), eligibleAtMs: integer('eligible_at_ms').notNull(), retiredAtMs: integer('retired_at_ms').notNull(), disposition: text('disposition').notNull(), byteLength: integer('byte_length').notNull(), truncated: text('truncated').notNull(), maximumBytes: integer('maximum_bytes'), truncationObservedAtMs: integer('truncation_observed_at_ms'), recordDigest: text('record_digest').notNull(), }, (table) => [ uniqueIndex('ql3_run_log_tombstone_attempt_uidx').on(table.attemptId), index('ql3_run_log_tombstone_retired_idx').on( table.retiredAtMs, table.attemptId, ), check( 'ql3_run_log_tombstone_executor_check', sql`${table.executorType} = 'local_process'`, ), check( 'ql3_run_log_tombstone_disposition_check', sql`${table.disposition} in ('deleted','already_absent')`, ), check( 'ql3_run_log_tombstone_truncated_check', sql`${table.truncated} in ('true','false','unknown')`, ), check( 'ql3_run_log_tombstone_identity_check', sql`length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.attemptId}) between 1 and 128 and length(${table.logArtifactId}) = 36 and substr(${table.logArtifactId}, 1, 6) = 'local-' and substr(${table.logArtifactId}, 7) not glob '*[^0-9a-f]*'`, ), check( 'ql3_run_log_tombstone_time_check', sql`${table.finishedAtMs} >= 0 and ${table.eligibleAtMs} >= ${table.finishedAtMs} and ${table.retiredAtMs} >= ${table.eligibleAtMs}`, ), check( 'ql3_run_log_tombstone_size_check', sql`${table.byteLength} between 0 and 1073741824 and (${table.disposition} <> 'already_absent' or ${table.byteLength} = 0)`, ), check( 'ql3_run_log_tombstone_truncation_shape_check', sql`(${table.truncated} = 'unknown' and ${table.maximumBytes} is null and ${table.truncationObservedAtMs} is null) or (${table.truncated} in ('true','false') and ${table.maximumBytes} >= 1 and ${table.truncationObservedAtMs} >= 0)`, ), check( 'ql3_run_log_tombstone_digest_check', sql`length(${table.recordDigest}) = 64 and ${table.recordDigest} not glob '*[^0-9a-f]*'`, ), ], ); export const runAttemptLogRetentionState = sqliteTable( 'QingLong3RunAttemptLogRetentionState', { maintenanceId: text('maintenance_id').primaryKey(), cursorFinishedAtMs: integer('cursor_finished_at_ms'), cursorAttemptId: text('cursor_attempt_id'), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_run_log_retention_state_id_check', sql`${table.maintenanceId} = 'local-run-attempt-log'`, ), check( 'ql3_run_log_retention_state_cursor_check', sql`(${table.cursorFinishedAtMs} is null and ${table.cursorAttemptId} is null) or (${table.cursorFinishedAtMs} >= 0 and length(${table.cursorAttemptId}) between 1 and 128)`, ), check( 'ql3_run_log_retention_state_time_check', sql`${table.updatedAtMs} >= 0`, ), ], ); export const localExecutionContextRecipes = sqliteTable( 'QingLong3LocalExecutionContextRecipes', { contextRef: text('context_ref').primaryKey(), environmentJson: text('environment_json').notNull(), contentDigest: text('content_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_local_context_ref_check', sql`length(${table.contextRef}) = 80 and ${table.contextRef} glob 'localctx:sha256:[0-9a-f]*' and length(replace(${table.contextRef}, 'localctx:sha256:', '')) = 64`, ), check( 'ql3_local_context_environment_check', sql`json_valid(${table.environmentJson}) and json_type(${table.environmentJson}) = 'array' and length(${table.environmentJson}) <= 262144`, ), check( 'ql3_local_context_digest_check', sql`length(${table.contentDigest}) = 64 and ${table.contentDigest} not glob '*[^0-9a-f]*' and ${table.contextRef} = 'localctx:sha256:' || ${table.contentDigest}`, ), check('ql3_local_context_created_check', sql`${table.createdAtMs} >= 0`), ], ); export const localTaskExecutionRevisions = sqliteTable( 'QingLong3LocalTaskExecutionRevisions', { projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), taskRevision: text('task_revision').notNull(), executorType: text('executor_type').notNull(), commandJson: text('command_json').notNull(), workingDirectory: text('working_directory'), timeoutMs: integer('timeout_ms'), contextRef: text('context_ref') .notNull() .references(() => localExecutionContextRecipes.contextRef, { onDelete: 'restrict', }), contentDigest: text('content_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.taskId, table.taskRevision], }), check( 'ql3_local_revision_executor_check', sql`${table.executorType} = 'local_process'`, ), check( 'ql3_local_revision_command_check', sql`json_valid(${table.commandJson}) and json_type(${table.commandJson}) = 'object' and length(${table.commandJson}) between 1 and 131072`, ), check( 'ql3_local_revision_working_directory_check', sql`${table.workingDirectory} is null or (length(${table.workingDirectory}) between 1 and 4096 and substr(${table.workingDirectory}, 1, 1) = '/')`, ), check( 'ql3_local_revision_timeout_check', sql`${table.timeoutMs} is null or ${table.timeoutMs} between 1 and 31536000000`, ), check( 'ql3_local_revision_digest_check', sql`length(${table.contentDigest}) = 64 and ${table.contentDigest} not glob '*[^0-9a-f]*'`, ), check('ql3_local_revision_created_check', sql`${table.createdAtMs} >= 0`), ], ); export const localSecretEnvelopes = sqliteTable( 'QingLong3LocalSecretEnvelopes', { projectId: text('project_id').notNull(), name: text('secret_name').notNull(), version: integer('version').notNull(), mutationId: text('mutation_id').notNull(), keyId: text('key_id').notNull(), algorithm: text('algorithm').notNull(), nonce: blob('nonce', { mode: 'buffer' }).notNull(), ciphertext: blob('ciphertext', { mode: 'buffer' }).notNull(), authTag: blob('auth_tag', { mode: 'buffer' }).notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.name, table.version] }), check( 'ql3_local_secret_project_check', sql`length(${table.projectId}) between 1 and 128 and ${table.projectId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*'`, ), check( 'ql3_local_secret_name_check', sql`length(${table.name}) between 1 and 128 and ${table.name} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*'`, ), check( 'ql3_local_secret_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_secret_mutation_check', sql`length(${table.mutationId}) between 1 and 64`, ), check( 'ql3_local_secret_key_check', sql`length(${table.keyId}) between 1 and 128 and ${table.keyId} not glob '*[^A-Za-z0-9._-]*'`, ), check( 'ql3_local_secret_algorithm_check', sql`${table.algorithm} = 'aes-256-gcm'`, ), check( 'ql3_local_secret_crypto_shape_check', sql`length(${table.nonce}) = 12 and length(${table.ciphertext}) <= 16384 and length(${table.authTag}) = 16`, ), check('ql3_local_secret_created_check', sql`${table.createdAtMs} >= 0`), uniqueIndex('ql3_local_secret_mutation_uidx').on( table.projectId, table.name, table.mutationId, ), index('ql3_local_secret_current_idx').on( table.projectId, table.name, sql`${table.version} desc`, ), index('ql3_local_secret_key_usage_idx').on( table.keyId, table.projectId, table.name, table.version, ), ], ); export const localProjects = sqliteTable( 'QingLong3Projects', { id: text('id').primaryKey(), name: text('name').notNull(), slug: text('slug').notNull(), status: text('status').notNull(), version: integer('version').notNull(), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_local_projects_id_check', sql`length(${table.id}) between 1 and 128 and ${table.id} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*'`, ), check( 'ql3_local_projects_name_check', sql`length(${table.name}) between 1 and 255`, ), check( 'ql3_local_projects_slug_check', sql`length(${table.slug}) between 1 and 128 and ${table.slug} = lower(${table.slug}) and ${table.slug} not glob '*[^a-z0-9-]*' and substr(${table.slug}, 1, 1) not glob '[^a-z0-9]' and substr(${table.slug}, -1, 1) not glob '[^a-z0-9]'`, ), check( 'ql3_local_projects_status_check', sql`${table.status} in ('active', 'archived')`, ), check( 'ql3_local_projects_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_projects_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), uniqueIndex('ql3_local_projects_slug_uidx').on(table.slug), ], ); export const approvalRequests = sqliteTable( 'QingLong3ApprovalRequests', { requestId: text('request_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), version: integer('version').notNull(), state: text('state').notNull(), actionType: text('action_type').notNull(), actionRef: text('action_ref').notNull(), actionDigest: text('action_digest').notNull(), previewDigest: text('preview_digest').notNull(), requestedByType: text('requested_by_type').notNull(), requestedById: text('requested_by_id').notNull(), decisionId: text('decision_id'), consumptionId: text('consumption_id'), dispatchId: text('dispatch_id'), expiresAtMs: integer('expires_at_ms').notNull(), requestJson: text('request_json', { mode: 'json' }) .$type>() .notNull(), requestDigest: text('request_digest').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_approval_requests_identity_check', sql`length(${table.requestId}) between 1 and 128 and length(${table.actionType}) between 1 and 128 and length(${table.actionRef}) between 1 and 255`, ), check( 'ql3_approval_requests_state_version_check', sql`(${table.state} = 'pending' and ${table.version} = 1) or (${table.state} in ('approved','rejected') and ${table.version} = 2) or (${table.state} = 'consumed' and ${table.version} = 3)`, ), check( 'ql3_approval_requests_digest_check', sql`length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and length(${table.previewDigest}) = 64 and ${table.previewDigest} not glob '*[^0-9a-f]*' and length(${table.requestDigest}) = 64 and ${table.requestDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_approval_requests_subject_check', sql`${table.requestedByType} in ('user','api_app','mcp_client','agent','system','worker') and length(${table.requestedById}) between 1 and 255`, ), check( 'ql3_approval_requests_mutation_tuple_check', sql`(${table.version} = 1 and ${table.decisionId} is null and ${table.consumptionId} is null and ${table.dispatchId} is null) or (${table.version} = 2 and ${table.decisionId} is not null and ${table.consumptionId} is null and ${table.dispatchId} is null) or (${table.version} = 3 and ${table.decisionId} is not null and ${table.consumptionId} is not null and ${table.dispatchId} is not null)`, ), check( 'ql3_approval_requests_json_check', sql`length(${table.requestJson}) between 2 and 65536 and json_valid(${table.requestJson}) and json_type(${table.requestJson}) = 'object' and json_extract(${table.requestJson}, '$.id') = ${table.requestId} and json_extract(${table.requestJson}, '$.projectId') = ${table.projectId} and json_extract(${table.requestJson}, '$.version') = ${table.version} and json_extract(${table.requestJson}, '$.state') = ${table.state} and json_extract(${table.requestJson}, '$.action.actionType') = ${table.actionType} and json_extract(${table.requestJson}, '$.action.actionRef') = ${table.actionRef} and json_extract(${table.requestJson}, '$.action.actionDigest') = ${table.actionDigest} and json_extract(${table.requestJson}, '$.action.previewDigest') = ${table.previewDigest}`, ), check( 'ql3_approval_requests_time_check', sql`${table.expiresAtMs} > 0 and ${table.updatedAtMs} >= 0`, ), uniqueIndex('ql3_approval_requests_decision_uidx').on(table.decisionId), uniqueIndex('ql3_approval_requests_consumption_uidx').on( table.consumptionId, ), uniqueIndex('ql3_approval_requests_dispatch_uidx').on(table.dispatchId), index('ql3_approval_requests_pending_idx') .on(table.expiresAtMs, table.requestId) .where(sql`${table.state} = 'pending'`), index('ql3_approval_requests_project_idx').on( table.projectId, table.updatedAtMs, table.requestId, ), ], ); export const approvedActionDispatches = sqliteTable( 'QingLong3ApprovedActionDispatches', { dispatchId: text('dispatch_id').primaryKey(), approvalRequestId: text('approval_request_id') .notNull() .references(() => approvalRequests.requestId, { onDelete: 'restrict' }), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), actionType: text('action_type').notNull(), actionRef: text('action_ref').notNull(), actionDigest: text('action_digest').notNull(), previewDigest: text('preview_digest').notNull(), dispatchJson: text('dispatch_json', { mode: 'json' }) .$type>() .notNull(), dispatchDigest: text('dispatch_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ uniqueIndex('ql3_approved_action_dispatch_request_uidx').on( table.approvalRequestId, ), uniqueIndex('ql3_approved_action_dispatch_lifecycle_uidx').on( table.dispatchId, table.projectId, table.actionType, table.actionDigest, table.previewDigest, ), check( 'ql3_approved_action_dispatch_identity_check', sql`length(${table.dispatchId}) between 1 and 128 and length(${table.actionType}) between 1 and 128 and length(${table.actionRef}) between 1 and 255`, ), check( 'ql3_approved_action_dispatch_digest_check', sql`length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and length(${table.previewDigest}) = 64 and ${table.previewDigest} not glob '*[^0-9a-f]*' and length(${table.dispatchDigest}) = 64 and ${table.dispatchDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_approved_action_dispatch_json_check', sql`length(${table.dispatchJson}) between 2 and 65536 and json_valid(${table.dispatchJson}) and json_type(${table.dispatchJson}) = 'object' and json_extract(${table.dispatchJson}, '$.id') = ${table.dispatchId} and json_extract(${table.dispatchJson}, '$.approvalRequestId') = ${table.approvalRequestId} and json_extract(${table.dispatchJson}, '$.projectId') = ${table.projectId} and json_extract(${table.dispatchJson}, '$.action.actionType') = ${table.actionType} and json_extract(${table.dispatchJson}, '$.action.actionRef') = ${table.actionRef} and json_extract(${table.dispatchJson}, '$.action.actionDigest') = ${table.actionDigest} and json_extract(${table.dispatchJson}, '$.action.previewDigest') = ${table.previewDigest}`, ), check( 'ql3_approved_action_dispatch_time_check', sql`${table.createdAtMs} >= 0`, ), index('ql3_approved_action_dispatch_project_idx').on( table.projectId, table.createdAtMs, table.dispatchId, ), ], ); export const approvedActionExecutions = sqliteTable( 'QingLong3ApprovedActionExecutions', { dispatchId: text('dispatch_id') .primaryKey() .references(() => approvedActionDispatches.dispatchId, { onDelete: 'restrict', }), dispatchDigest: text('dispatch_digest').notNull(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), status: text('status').notNull(), version: integer('version').notNull(), attemptCount: integer('attempt_count').notNull(), maxAttempts: integer('max_attempts').notNull(), eligibleAtMs: integer('eligible_at_ms'), nextAttemptAtMs: integer('next_attempt_at_ms'), leaseOwner: text('lease_owner'), leaseToken: text('lease_token'), leaseExpiresAtMs: integer('lease_expires_at_ms'), startedAtMs: integer('started_at_ms'), resultMutationId: text('result_mutation_id'), resultCode: text('result_code'), resultDigest: text('result_digest'), completedAtMs: integer('completed_at_ms'), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), executionJson: text('execution_json', { mode: 'json' }) .$type>() .notNull(), executionDigest: text('execution_digest').notNull(), }, (table) => [ check( 'ql3_approved_action_execution_state_check', sql`${table.status} in ('pending','leased','executing','retry_wait','succeeded','failed','blocked') and ${table.version} between 0 and 2147483647 and ${table.attemptCount} between 0 and 16 and ${table.maxAttempts} between 1 and 16 and ${table.attemptCount} <= ${table.maxAttempts}`, ), check( 'ql3_approved_action_execution_lease_check', sql`(${table.leaseOwner} is null and ${table.leaseToken} is null and ${table.leaseExpiresAtMs} is null) or (length(${table.leaseOwner}) between 1 and 128 and length(${table.leaseToken}) between 1 and 128 and ${table.leaseExpiresAtMs} > ${table.updatedAtMs})`, ), check( 'ql3_approved_action_execution_result_check', sql`(${table.resultMutationId} is null and ${table.resultCode} is null) or (length(${table.resultMutationId}) between 1 and 128 and length(${table.resultCode}) between 1 and 64)`, ), check( 'ql3_approved_action_execution_digest_check', sql`length(${table.dispatchDigest}) = 64 and ${table.dispatchDigest} not glob '*[^0-9a-f]*' and (${table.resultDigest} is null or (length(${table.resultDigest}) = 64 and ${table.resultDigest} not glob '*[^0-9a-f]*')) and length(${table.executionDigest}) = 64 and ${table.executionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_approved_action_execution_json_check', sql`length(${table.executionJson}) between 2 and 65536 and json_valid(${table.executionJson}) and json_type(${table.executionJson}) = 'object' and json_extract(${table.executionJson}, '$.schema') = 'qinglong/approved-action-execution@v1' and json_extract(${table.executionJson}, '$.dispatchId') = ${table.dispatchId} and json_extract(${table.executionJson}, '$.dispatchDigest') = ${table.dispatchDigest} and json_extract(${table.executionJson}, '$.projectId') = ${table.projectId} and json_extract(${table.executionJson}, '$.status') = ${table.status} and json_extract(${table.executionJson}, '$.version') = ${table.version} and json_extract(${table.executionJson}, '$.attemptCount') = ${table.attemptCount} and json_extract(${table.executionJson}, '$.maxAttempts') = ${table.maxAttempts} and json_extract(${table.executionJson}, '$.executionDigest') = ${table.executionDigest}`, ), check( 'ql3_approved_action_execution_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), index('ql3_approved_action_execution_due_idx') .on(table.eligibleAtMs, table.dispatchId) .where(sql`${table.status} in ('pending','leased','retry_wait')`), index('ql3_approved_action_execution_recovery_idx') .on(table.leaseExpiresAtMs, table.dispatchId) .where(sql`${table.status} = 'executing'`), index('ql3_approved_action_execution_project_idx').on( table.projectId, table.updatedAtMs, table.dispatchId, ), ], ); export const pluginPackageInstallProposals = sqliteTable( 'QingLong3PluginPackageInstallProposals', { actionRef: text('action_ref').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), actionType: text('action_type').notNull(), permission: text('permission').notNull(), actionDigest: text('action_digest').notNull(), previewDigest: text('preview_digest').notNull(), proposedByType: text('proposed_by_type').notNull(), proposedById: text('proposed_by_id').notNull(), fenceProjectVersion: integer('fence_project_version').notNull(), fenceBindingVersion: integer('fence_binding_version'), createdAtMs: integer('created_at_ms').notNull(), proposalJson: text('proposal_json', { mode: 'json' }) .$type>() .notNull(), proposalDigest: text('proposal_digest').notNull(), }, (table) => [ check( 'ql3_plugin_package_proposal_identity_check', sql`length(${table.actionRef}) between 1 and 255 and ${table.actionType} = 'plugin_package.install' and ${table.permission} = 'package.manage' and ${table.proposedByType} in ('user','api_app','mcp_client','agent','system','worker') and length(${table.proposedById}) between 1 and 255`, ), check( 'ql3_plugin_package_proposal_digest_check', sql`length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and length(${table.previewDigest}) = 64 and ${table.previewDigest} not glob '*[^0-9a-f]*' and length(${table.proposalDigest}) = 64 and ${table.proposalDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_proposal_json_check', sql`length(${table.proposalJson}) between 2 and 262144 and json_valid(${table.proposalJson}) and json_type(${table.proposalJson}) = 'object' and json_extract(${table.proposalJson}, '$.schema') = 'qinglong/plugin-package-install-proposal@v1' and json_extract(${table.proposalJson}, '$.actionRef') = ${table.actionRef} and json_extract(${table.proposalJson}, '$.projectId') = ${table.projectId} and json_extract(${table.proposalJson}, '$.actionType') = ${table.actionType} and json_extract(${table.proposalJson}, '$.permission') = ${table.permission} and json_extract(${table.proposalJson}, '$.actionDigest') = ${table.actionDigest} and json_extract(${table.proposalJson}, '$.previewDigest') = ${table.previewDigest} and json_extract(${table.proposalJson}, '$.proposedBy.type') = ${table.proposedByType} and json_extract(${table.proposalJson}, '$.proposedBy.id') = ${table.proposedById} and json_extract(${table.proposalJson}, '$.proposalFence.projectVersion') = ${table.fenceProjectVersion} and json_extract(${table.proposalJson}, '$.proposalFence.bindingVersion') is ${table.fenceBindingVersion} and json_extract(${table.proposalJson}, '$.createdAtMs') = ${table.createdAtMs} and json_extract(${table.proposalJson}, '$.proposalDigest') = ${table.proposalDigest}`, ), check( 'ql3_plugin_package_proposal_time_check', sql`${table.fenceProjectVersion} > 0 and (${table.fenceBindingVersion} is null or ${table.fenceBindingVersion} > 0) and ${table.createdAtMs} >= 0`, ), index('ql3_plugin_package_proposal_project_idx').on( table.projectId, table.createdAtMs, table.actionRef, ), ], ); export const pluginPackageInstalls = sqliteTable( 'QingLong3PluginPackageInstalls', { installationId: text('installation_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), packageName: text('package_name').notNull(), packageVersion: text('package_version').notNull(), operation: text('operation').notNull(), lockDigest: text('lock_digest').notNull(), targetGeneration: integer('target_generation').notNull(), previousActiveLockDigest: text('previous_active_lock_digest'), activeLockDigest: text('active_lock_digest'), state: text('state').notNull(), version: integer('version').notNull(), lastMutationId: text('last_mutation_id').notNull(), lastMutationDigest: text('last_mutation_digest').notNull(), lockJson: text('lock_json', { mode: 'json' }) .$type>() .notNull(), recordJson: text('record_json', { mode: 'json' }) .$type>() .notNull(), recordDigest: text('record_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ check( 'ql3_plugin_package_installs_identity_check', sql`length(${table.installationId}) between 1 and 128 and length(${table.packageName}) between 1 and 253 and length(${table.packageVersion}) between 1 and 128 and length(${table.lastMutationId}) between 1 and 128`, ), check( 'ql3_plugin_package_installs_operation_check', sql`${table.operation} in ('install','reinstall','upgrade','rollback')`, ), check( 'ql3_plugin_package_installs_state_check', sql`${table.state} in ('queued','staged','activating','active','failed')`, ), check( 'ql3_plugin_package_installs_version_check', sql`${table.targetGeneration} between 1 and 2147483647 and ${table.version} between 1 and 2147483647`, ), check( 'ql3_plugin_package_installs_digest_check', sql`length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and (${table.previousActiveLockDigest} is null or (length(${table.previousActiveLockDigest}) = 64 and ${table.previousActiveLockDigest} not glob '*[^0-9a-f]*')) and (${table.activeLockDigest} is null or (length(${table.activeLockDigest}) = 64 and ${table.activeLockDigest} not glob '*[^0-9a-f]*')) and length(${table.lastMutationDigest}) = 64 and ${table.lastMutationDigest} not glob '*[^0-9a-f]*' and length(${table.recordDigest}) = 64 and ${table.recordDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_installs_record_check', sql`length(${table.lockJson}) between 2 and 262144 and json_valid(${table.lockJson}) and json_type(${table.lockJson}) = 'object' and json_extract(${table.lockJson}, '$.lockDigest') = ${table.lockDigest} and json_extract(${table.lockJson}, '$.projectId') = ${table.projectId} and json_extract(${table.lockJson}, '$.packageName') = ${table.packageName} and length(${table.recordJson}) between 2 and 262144 and json_valid(${table.recordJson}) and json_type(${table.recordJson}) = 'object' and json_extract(${table.recordJson}, '$.installationId') = ${table.installationId} and json_extract(${table.recordJson}, '$.projectId') = ${table.projectId} and json_extract(${table.recordJson}, '$.packageName') = ${table.packageName} and json_extract(${table.recordJson}, '$.lockDigest') = ${table.lockDigest} and json_extract(${table.recordJson}, '$.state') = ${table.state} and json_extract(${table.recordJson}, '$.version') = ${table.version} and json_extract(${table.recordJson}, '$.recordDigest') = ${table.recordDigest}`, ), check( 'ql3_plugin_package_installs_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), index('ql3_plugin_package_installs_recovery_idx') .on(table.state, table.packageName, table.installationId) .where(sql`${table.state} in ('queued','staged','activating')`), index('ql3_plugin_package_installs_project_history_idx').on( table.projectId, table.packageName, table.createdAtMs, table.installationId, ), uniqueIndex('ql3_plugin_package_installs_snapshot_source_uidx').on( table.projectId, table.packageName, table.installationId, table.targetGeneration, table.lockDigest, ), uniqueIndex('ql3_plugin_package_installs_quarantine_target_uidx').on( table.projectId, table.packageName, table.installationId, table.lockDigest, table.recordDigest, ), ], ); export const pluginPackageInstallHeads = sqliteTable( 'QingLong3PluginPackageInstallHeads', { projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), packageName: text('package_name').notNull(), installationId: text('installation_id') .notNull() .references(() => pluginPackageInstalls.installationId, { onDelete: 'restrict', }), }, (table) => [ primaryKey({ columns: [table.projectId, table.packageName] }), uniqueIndex('ql3_plugin_package_install_heads_install_uidx').on( table.installationId, ), check( 'ql3_plugin_package_install_heads_identity_check', sql`length(${table.packageName}) between 1 and 253 and length(${table.installationId}) between 1 and 128`, ), ], ); export const pluginPackageInstallMutations = sqliteTable( 'QingLong3PluginPackageInstallMutations', { installationId: text('installation_id') .notNull() .references(() => pluginPackageInstalls.installationId, { onDelete: 'restrict', }), mutationId: text('mutation_id').notNull(), mutationDigest: text('mutation_digest').notNull(), resultingRecordDigest: text('resulting_record_digest').notNull(), occurredAtMs: integer('occurred_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.installationId, table.mutationId] }), check( 'ql3_plugin_package_install_mutations_identity_check', sql`length(${table.mutationId}) between 1 and 128`, ), check( 'ql3_plugin_package_install_mutations_digest_check', sql`length(${table.mutationDigest}) = 64 and ${table.mutationDigest} not glob '*[^0-9a-f]*' and length(${table.resultingRecordDigest}) = 64 and ${table.resultingRecordDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_install_mutations_time_check', sql`${table.occurredAtMs} >= 0`, ), index('ql3_plugin_package_install_mutations_result_idx').on( table.installationId, table.resultingRecordDigest, ), ], ); export const pluginPackageMaterializedRevisions = sqliteTable( 'QingLong3PluginPackageMaterializedRevisions', { generationDigest: text('generation_digest').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), packageName: text('package_name').notNull(), generation: integer('generation').notNull(), lockDigest: text('lock_digest').notNull(), manifestDigest: text('manifest_digest').notNull(), revisionDigest: text('revision_digest').notNull(), revisionJson: text('revision_json', { mode: 'json' }) .$type>() .notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_plugin_package_materialized_revision_identity_check', sql`length(${table.packageName}) between 1 and 63 and ${table.generation} between 1 and 2147483647`, ), check( 'ql3_plugin_package_materialized_revision_digest_check', sql`length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.manifestDigest}) = 64 and ${table.manifestDigest} not glob '*[^0-9a-f]*' and length(${table.revisionDigest}) = 64 and ${table.revisionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_materialized_revision_json_check', sql`length(${table.revisionJson}) between 2 and 25165824 and json_valid(${table.revisionJson}) and json_type(${table.revisionJson}) = 'object' and json_extract(${table.revisionJson}, '$.schema') = 'qinglong/plugin-package-materialized-revision@v1' and json_extract(${table.revisionJson}, '$.generation.generationDigest') = ${table.generationDigest} and json_extract(${table.revisionJson}, '$.generation.projectId') = ${table.projectId} and json_extract(${table.revisionJson}, '$.generation.packageName') = ${table.packageName} and json_extract(${table.revisionJson}, '$.generation.generation') = ${table.generation} and json_extract(${table.revisionJson}, '$.generation.lockDigest') = ${table.lockDigest} and json_extract(${table.revisionJson}, '$.manifestDigest') = ${table.manifestDigest} and json_extract(${table.revisionJson}, '$.revisionDigest') = ${table.revisionDigest}`, ), check( 'ql3_plugin_package_materialized_revision_time_check', sql`${table.createdAtMs} >= 0`, ), uniqueIndex('ql3_plugin_package_materialized_revision_generation_uidx').on( table.projectId, table.packageName, table.generation, ), index('ql3_plugin_package_materialized_revision_lock_idx').on( table.lockDigest, table.generationDigest, ), uniqueIndex( 'ql3_plugin_package_materialized_revision_snapshot_source_uidx', ).on( table.projectId, table.packageName, table.generation, table.generationDigest, table.lockDigest, table.revisionDigest, ), ], ); export const projectToolDefinitionSnapshots = sqliteTable( 'QingLong3ProjectToolDefinitionSnapshots', { projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), activeVectorDigest: text('active_vector_digest').notNull(), definitionsDigest: text('definitions_digest').notNull(), snapshotDigest: text('snapshot_digest').notNull(), snapshotJson: text('snapshot_json', { mode: 'json' }) .$type>() .notNull(), committedAtMs: integer('committed_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.activeVectorDigest] }), check( 'ql3_project_tool_definition_snapshot_identity_check', sql`length(${table.projectId}) between 1 and 128`, ), check( 'ql3_project_tool_definition_snapshot_digest_check', sql`length(${table.activeVectorDigest}) = 64 and ${table.activeVectorDigest} not glob '*[^0-9a-f]*' and length(${table.definitionsDigest}) = 64 and ${table.definitionsDigest} not glob '*[^0-9a-f]*' and length(${table.snapshotDigest}) = 64 and ${table.snapshotDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_project_tool_definition_snapshot_json_check', sql`length(${table.snapshotJson}) between 2 and 8388608 and json_valid(${table.snapshotJson}) and json_type(${table.snapshotJson}) = 'object' and json_extract(${table.snapshotJson}, '$.schema') = 'qinglong/project-tool-definition-snapshot@v1' and json_extract(${table.snapshotJson}, '$.projectId') = ${table.projectId} and json_extract(${table.snapshotJson}, '$.activeVectorDigest') = ${table.activeVectorDigest} and json_extract(${table.snapshotJson}, '$.definitionsDigest') = ${table.definitionsDigest} and json_extract(${table.snapshotJson}, '$.snapshotDigest') = ${table.snapshotDigest}`, ), check( 'ql3_project_tool_definition_snapshot_time_check', sql`${table.committedAtMs} >= 0`, ), uniqueIndex('ql3_project_tool_definition_snapshot_digest_uidx').on( table.snapshotDigest, ), uniqueIndex('ql3_project_tool_definition_snapshot_withdrawal_uidx').on( table.projectId, table.activeVectorDigest, table.snapshotDigest, ), index('ql3_project_tool_definition_snapshot_current_idx').on( table.projectId, sql`${table.committedAtMs} desc`, table.activeVectorDigest, ), ], ); export const projectToolDefinitionSnapshotSources = sqliteTable( 'QingLong3ProjectToolDefinitionSnapshotSources', { projectId: text('project_id').notNull(), activeVectorDigest: text('active_vector_digest').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), generation: integer('generation').notNull(), generationDigest: text('generation_digest').notNull(), lockDigest: text('lock_digest').notNull(), revisionDigest: text('revision_digest').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.activeVectorDigest, table.packageName], }), foreignKey({ columns: [table.projectId, table.activeVectorDigest], foreignColumns: [ projectToolDefinitionSnapshots.projectId, projectToolDefinitionSnapshots.activeVectorDigest, ], name: 'ql3_project_tool_definition_snapshot_source_snapshot_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.projectId, table.packageName, table.installationId, table.generation, table.lockDigest, ], foreignColumns: [ pluginPackageInstalls.projectId, pluginPackageInstalls.packageName, pluginPackageInstalls.installationId, pluginPackageInstalls.targetGeneration, pluginPackageInstalls.lockDigest, ], name: 'ql3_project_tool_definition_snapshot_source_install_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.projectId, table.packageName, table.generation, table.generationDigest, table.lockDigest, table.revisionDigest, ], foreignColumns: [ pluginPackageMaterializedRevisions.projectId, pluginPackageMaterializedRevisions.packageName, pluginPackageMaterializedRevisions.generation, pluginPackageMaterializedRevisions.generationDigest, pluginPackageMaterializedRevisions.lockDigest, pluginPackageMaterializedRevisions.revisionDigest, ], name: 'ql3_project_tool_definition_snapshot_source_revision_fk', }).onDelete('restrict'), check( 'ql3_project_tool_definition_snapshot_source_identity_check', sql`length(${table.packageName}) between 1 and 63 and length(${table.installationId}) between 1 and 128 and ${table.generation} between 1 and 2147483647`, ), check( 'ql3_project_tool_definition_snapshot_source_digest_check', sql`length(${table.activeVectorDigest}) = 64 and ${table.activeVectorDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.revisionDigest}) = 64 and ${table.revisionDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_project_tool_definition_snapshot_source_generation_idx').on( table.generationDigest, table.projectId, table.packageName, ), index('ql3_project_tool_definition_snapshot_source_install_idx').on( table.installationId, table.activeVectorDigest, ), ], ); export const taskDefinitions = sqliteTable( 'QingLong3TaskDefinitions', { projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), taskId: text('task_id').notNull(), currentRevision: integer('current_revision').notNull(), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.taskId] }), check( 'ql3_task_definitions_id_check', sql`length(${table.projectId}) between 1 and 128 and length(${table.taskId}) between 1 and 128 and ${table.projectId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*' and ${table.taskId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*'`, ), check( 'ql3_task_definitions_revision_check', sql`${table.currentRevision} between 1 and 2147483647`, ), check( 'ql3_task_definitions_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), ], ); export const taskDefinitionRevisions = sqliteTable( 'QingLong3TaskDefinitionRevisions', { projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), revision: integer('revision').notNull(), mutationId: text('mutation_id').notNull(), name: text('name').notNull(), description: text('description'), kind: text('kind').notNull(), specJson: text('spec_json').notNull(), labelsJson: text('labels_json').notNull(), enabled: integer('enabled', { mode: 'boolean' }).notNull(), contentDigest: text('content_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.taskId, table.revision] }), foreignKey({ columns: [table.projectId, table.taskId], foreignColumns: [taskDefinitions.projectId, taskDefinitions.taskId], name: 'ql3_task_definition_revisions_task_fk', }).onDelete('restrict'), check( 'ql3_task_definition_revisions_revision_check', sql`${table.revision} between 1 and 2147483647`, ), check( 'ql3_task_definition_revisions_mutation_check', sql`length(${table.mutationId}) = 36 and substr(${table.mutationId}, 9, 1) = '-' and substr(${table.mutationId}, 14, 1) = '-' and substr(${table.mutationId}, 19, 1) = '-' and substr(${table.mutationId}, 24, 1) = '-' and replace(${table.mutationId}, '-', '') not glob '*[^0-9a-f]*'`, ), check( 'ql3_task_definition_revisions_name_check', sql`length(${table.name}) between 1 and 255 and (${table.description} is null or length(${table.description}) between 1 and 4096)`, ), check( 'ql3_task_definition_revisions_kind_check', sql`${table.kind} in ('script','command','workflow','agent','tool')`, ), check( 'ql3_task_definition_revisions_spec_check', sql`json_valid(${table.specJson}) and json_type(${table.specJson}) = 'object' and length(${table.specJson}) between 1 and 65536`, ), check( 'ql3_task_definition_revisions_labels_check', sql`json_valid(${table.labelsJson}) and json_type(${table.labelsJson}) = 'object' and length(${table.labelsJson}) between 2 and 16384`, ), check( 'ql3_task_definition_revisions_enabled_check', sql`${table.enabled} in (0, 1)`, ), check( 'ql3_task_definition_revisions_digest_check', sql`length(${table.contentDigest}) = 64 and ${table.contentDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_task_definition_revisions_created_check', sql`${table.createdAtMs} >= 0`, ), uniqueIndex('ql3_task_definition_revisions_mutation_uidx').on( table.mutationId, ), index('ql3_task_definition_revisions_project_kind_idx').on( table.projectId, table.kind, table.enabled, table.taskId, table.revision, ), ], ); export const pluginPackageQuarantineEvents = sqliteTable( 'QingLong3PluginPackageQuarantineEvents', { eventDigest: text('event_digest').primaryKey(), mutationId: text('mutation_id').notNull(), revocationReceiptDigest: text('revocation_receipt_digest').notNull(), impactDigest: text('impact_digest').notNull(), projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), lockDigest: text('lock_digest').notNull(), installState: text('install_state').notNull(), installVersion: integer('install_version').notNull(), installRecordDigest: text('install_record_digest').notNull(), activeLockDigest: text('active_lock_digest'), proposerType: text('proposer_type').notNull(), proposerId: text('proposer_id').notNull(), confirmerType: text('confirmer_type').notNull(), confirmerId: text('confirmer_id').notNull(), authorizationMode: text('authorization_mode').notNull(), reasonCode: text('reason_code').notNull(), occurredAtMs: integer('occurred_at_ms').notNull(), eventJson: text('event_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_quarantine_mutation_uidx').on( table.mutationId, ), uniqueIndex('ql3_plugin_package_quarantine_target_uidx').on( table.projectId, table.packageName, table.installationId, table.lockDigest, ), foreignKey({ columns: [ table.projectId, table.packageName, table.installationId, table.lockDigest, table.installRecordDigest, ], foreignColumns: [ pluginPackageInstalls.projectId, pluginPackageInstalls.packageName, pluginPackageInstalls.installationId, pluginPackageInstalls.lockDigest, pluginPackageInstalls.recordDigest, ], name: 'ql3_plugin_package_quarantine_install_fk', }) .onDelete('restrict') .onUpdate('restrict'), check( 'ql3_plugin_package_quarantine_identity_check', sql`length(${table.mutationId}) between 1 and 128 and length(${table.packageName}) between 1 and 63 and length(${table.installationId}) between 1 and 128 and ${table.installState} in ('queued','staged','activating','active') and ${table.installVersion} between 1 and 2147483647`, ), check( 'ql3_plugin_package_quarantine_state_check', sql`(${table.installState} = 'active' and ${table.activeLockDigest} = ${table.lockDigest}) or (${table.installState} <> 'active' and (${table.activeLockDigest} is null or ${table.activeLockDigest} <> ${table.lockDigest}))`, ), check( 'ql3_plugin_package_quarantine_subject_check', sql`${table.proposerType} in ('user','api_app','mcp_client','agent','system','worker') and ${table.confirmerType} in ('user','api_app','mcp_client','agent','system','worker') and length(${table.proposerId}) between 1 and 255 and length(${table.confirmerId}) between 1 and 255 and ${table.authorizationMode} in ('dual_control','break_glass') and (${table.authorizationMode} = 'break_glass' or ${table.proposerType} <> ${table.confirmerType} or ${table.proposerId} <> ${table.confirmerId}) and ${table.reasonCode} in ('suspected_key_compromise','confirmed_key_compromise')`, ), check( 'ql3_plugin_package_quarantine_digest_check', sql`length(${table.eventDigest}) = 64 and ${table.eventDigest} not glob '*[^0-9a-f]*' and length(${table.revocationReceiptDigest}) = 64 and ${table.revocationReceiptDigest} not glob '*[^0-9a-f]*' and length(${table.impactDigest}) = 64 and ${table.impactDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.installRecordDigest}) = 64 and ${table.installRecordDigest} not glob '*[^0-9a-f]*' and (${table.activeLockDigest} is null or (length(${table.activeLockDigest}) = 64 and ${table.activeLockDigest} not glob '*[^0-9a-f]*'))`, ), check( 'ql3_plugin_package_quarantine_json_check', sql`length(${table.eventJson}) between 2 and 262144 and json_valid(${table.eventJson}) and json_type(${table.eventJson}) = 'object' and json_extract(${table.eventJson}, '$.schema') = 'qinglong/plugin-package-quarantine-event@v1' and json_extract(${table.eventJson}, '$.mutationId') = ${table.mutationId} and json_extract(${table.eventJson}, '$.revocationReceiptDigest') = ${table.revocationReceiptDigest} and json_extract(${table.eventJson}, '$.impactDigest') = ${table.impactDigest} and json_extract(${table.eventJson}, '$.target.projectId') = ${table.projectId} and json_extract(${table.eventJson}, '$.target.packageName') = ${table.packageName} and json_extract(${table.eventJson}, '$.target.installationId') = ${table.installationId} and json_extract(${table.eventJson}, '$.target.lockDigest') = ${table.lockDigest} and json_extract(${table.eventJson}, '$.target.installState') = ${table.installState} and json_extract(${table.eventJson}, '$.target.installVersion') = ${table.installVersion} and json_extract(${table.eventJson}, '$.target.installRecordDigest') = ${table.installRecordDigest} and ((${table.activeLockDigest} is null and json_type(${table.eventJson}, '$.target.activeLockDigest') = 'null') or json_extract(${table.eventJson}, '$.target.activeLockDigest') = ${table.activeLockDigest}) and json_extract(${table.eventJson}, '$.proposer.type') = ${table.proposerType} and json_extract(${table.eventJson}, '$.proposer.id') = ${table.proposerId} and json_extract(${table.eventJson}, '$.confirmer.type') = ${table.confirmerType} and json_extract(${table.eventJson}, '$.confirmer.id') = ${table.confirmerId} and json_extract(${table.eventJson}, '$.authorizationMode') = ${table.authorizationMode} and json_extract(${table.eventJson}, '$.reasonCode') = ${table.reasonCode} and json_extract(${table.eventJson}, '$.occurredAtMs') = ${table.occurredAtMs} and json_extract(${table.eventJson}, '$.eventDigest') = ${table.eventDigest}`, ), check( 'ql3_plugin_package_quarantine_time_check', sql`${table.occurredAtMs} >= 0`, ), index('ql3_plugin_package_quarantine_lock_idx').on( table.lockDigest, table.projectId, table.packageName, ), index('ql3_plugin_package_quarantine_project_idx').on( table.projectId, table.packageName, table.occurredAtMs, table.eventDigest, ), ], ); export const pluginPackageWithdrawalReceipts = sqliteTable( 'QingLong3PluginPackageWithdrawalReceipts', { eventDigest: text('event_digest') .primaryKey() .references(() => pluginPackageQuarantineEvents.eventDigest, { onDelete: 'restrict', }), receiptDigest: text('receipt_digest').notNull(), projectId: text('project_id').notNull(), capabilityStatus: text('capability_status').notNull(), taskCount: integer('task_count').notNull(), previousActiveVectorDigest: text('previous_active_vector_digest'), currentActiveVectorDigest: text('current_active_vector_digest'), currentToolSnapshotDigest: text('current_tool_snapshot_digest'), retainedSourceCount: integer('retained_source_count').notNull(), committedAtMs: integer('committed_at_ms').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_withdrawal_receipt_uidx').on( table.receiptDigest, ), foreignKey({ columns: [ table.projectId, table.currentActiveVectorDigest, table.currentToolSnapshotDigest, ], foreignColumns: [ projectToolDefinitionSnapshots.projectId, projectToolDefinitionSnapshots.activeVectorDigest, projectToolDefinitionSnapshots.snapshotDigest, ], name: 'ql3_plugin_package_withdrawal_snapshot_fk', }).onDelete('restrict'), check( 'ql3_plugin_package_withdrawal_disposition_check', sql`(${table.capabilityStatus} = 'not_active' and ${table.taskCount} = 0 and ${table.previousActiveVectorDigest} is null and ${table.currentActiveVectorDigest} is null and ${table.currentToolSnapshotDigest} is null and ${table.retainedSourceCount} = 0) or (${table.capabilityStatus} = 'withdrawn' and ${table.taskCount} between 0 and 128 and ${table.previousActiveVectorDigest} is not null and ${table.currentActiveVectorDigest} is not null and ${table.previousActiveVectorDigest} <> ${table.currentActiveVectorDigest} and ${table.currentToolSnapshotDigest} is not null and ${table.retainedSourceCount} between 0 and 128)`, ), check( 'ql3_plugin_package_withdrawal_digest_check', sql`length(${table.eventDigest}) = 64 and ${table.eventDigest} not glob '*[^0-9a-f]*' and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*' and (${table.previousActiveVectorDigest} is null or (length(${table.previousActiveVectorDigest}) = 64 and ${table.previousActiveVectorDigest} not glob '*[^0-9a-f]*')) and (${table.currentActiveVectorDigest} is null or (length(${table.currentActiveVectorDigest}) = 64 and ${table.currentActiveVectorDigest} not glob '*[^0-9a-f]*')) and (${table.currentToolSnapshotDigest} is null or (length(${table.currentToolSnapshotDigest}) = 64 and ${table.currentToolSnapshotDigest} not glob '*[^0-9a-f]*'))`, ), check( 'ql3_plugin_package_withdrawal_json_check', sql`length(${table.receiptJson}) between 2 and 8388608 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-withdrawal-receipt@v1' and json_extract(${table.receiptJson}, '$.eventDigest') = ${table.eventDigest} and json_extract(${table.receiptJson}, '$.target.projectId') = ${table.projectId} and json_extract(${table.receiptJson}, '$.capability.status') = ${table.capabilityStatus} and json_array_length(json_extract(${table.receiptJson}, '$.capability.taskWithdrawals')) = ${table.taskCount} and ((${table.previousActiveVectorDigest} is null and json_type(${table.receiptJson}, '$.capability.previousActiveVectorDigest') = 'null') or json_extract(${table.receiptJson}, '$.capability.previousActiveVectorDigest') = ${table.previousActiveVectorDigest}) and ((${table.currentActiveVectorDigest} is null and json_type(${table.receiptJson}, '$.capability.currentActiveVectorDigest') = 'null') or json_extract(${table.receiptJson}, '$.capability.currentActiveVectorDigest') = ${table.currentActiveVectorDigest}) and ((${table.currentToolSnapshotDigest} is null and json_type(${table.receiptJson}, '$.capability.currentToolSnapshotDigest') = 'null') or json_extract(${table.receiptJson}, '$.capability.currentToolSnapshotDigest') = ${table.currentToolSnapshotDigest}) and json_extract(${table.receiptJson}, '$.capability.retainedSourceCount') = ${table.retainedSourceCount} and json_extract(${table.receiptJson}, '$.committedAtMs') = ${table.committedAtMs} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), check( 'ql3_plugin_package_withdrawal_time_check', sql`${table.committedAtMs} >= 0`, ), index('ql3_plugin_package_withdrawal_snapshot_idx').on( table.currentToolSnapshotDigest, table.eventDigest, ), ], ); export const pluginPackageWithdrawalTasks = sqliteTable( 'QingLong3PluginPackageWithdrawalTasks', { eventDigest: text('event_digest') .notNull() .references(() => pluginPackageWithdrawalReceipts.eventDigest, { onDelete: 'restrict', }), projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), previousRevision: integer('previous_revision').notNull(), disabledRevision: integer('disabled_revision').notNull(), previousContentDigest: text('previous_content_digest').notNull(), disabledContentDigest: text('disabled_content_digest').notNull(), }, (table) => [ primaryKey({ columns: [table.eventDigest, table.taskId] }), foreignKey({ columns: [table.projectId, table.taskId, table.previousRevision], foreignColumns: [ taskDefinitionRevisions.projectId, taskDefinitionRevisions.taskId, taskDefinitionRevisions.revision, ], name: 'ql3_plugin_package_withdrawal_task_previous_fk', }).onDelete('restrict'), foreignKey({ columns: [table.projectId, table.taskId, table.disabledRevision], foreignColumns: [ taskDefinitionRevisions.projectId, taskDefinitionRevisions.taskId, taskDefinitionRevisions.revision, ], name: 'ql3_plugin_package_withdrawal_task_disabled_fk', }).onDelete('restrict'), check( 'ql3_plugin_package_withdrawal_task_identity_check', sql`length(${table.taskId}) between 1 and 128 and ${table.previousRevision} between 1 and 2147483646 and ${table.disabledRevision} = ${table.previousRevision} + 1`, ), check( 'ql3_plugin_package_withdrawal_task_digest_check', sql`length(${table.eventDigest}) = 64 and ${table.eventDigest} not glob '*[^0-9a-f]*' and length(${table.previousContentDigest}) = 64 and ${table.previousContentDigest} not glob '*[^0-9a-f]*' and length(${table.disabledContentDigest}) = 64 and ${table.disabledContentDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_plugin_package_withdrawal_task_task_idx').on( table.projectId, table.taskId, table.eventDigest, ), ], ); export const pluginPackageTaskOwnerships = sqliteTable( 'QingLong3PluginPackageTaskOwnerships', { projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), packageName: text('package_name').notNull(), claimedGenerationDigest: text('claimed_generation_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.taskId] }), foreignKey({ columns: [table.projectId, table.taskId], foreignColumns: [taskDefinitions.projectId, taskDefinitions.taskId], name: 'ql3_plugin_package_task_ownership_task_fk', }).onDelete('restrict'), foreignKey({ columns: [table.projectId], foreignColumns: [localProjects.id], name: 'ql3_plugin_package_task_ownership_project_fk', }).onDelete('restrict'), check( 'ql3_plugin_package_task_ownership_identity_check', sql`length(${table.taskId}) between 1 and 128 and length(${table.packageName}) between 1 and 63`, ), check( 'ql3_plugin_package_task_ownership_digest_check', sql`length(${table.claimedGenerationDigest}) = 64 and ${table.claimedGenerationDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_task_ownership_namespace_check', sql`${table.taskId} like 'pkg:' || ${table.packageName} || ':%'`, ), check( 'ql3_plugin_package_task_ownership_time_check', sql`${table.createdAtMs} >= 0`, ), index('ql3_plugin_package_task_ownership_package_idx').on( table.projectId, table.packageName, table.taskId, ), ], ); export const pluginPackageTaskReconciliations = sqliteTable( 'QingLong3PluginPackageTaskReconciliations', { generationDigest: text('generation_digest') .primaryKey() .references(() => pluginPackageMaterializedRevisions.generationDigest, { onDelete: 'restrict', }), projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), generation: integer('generation').notNull(), materializedRevisionDigest: text('materialized_revision_digest').notNull(), lockDigest: text('lock_digest').notNull(), previousLockDigest: text('previous_lock_digest'), receiptDigest: text('receipt_digest').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), committedAtMs: integer('committed_at_ms').notNull(), }, (table) => [ check( 'ql3_plugin_package_task_reconciliation_identity_check', sql`length(${table.packageName}) between 1 and 63 and ${table.generation} between 1 and 2147483647`, ), check( 'ql3_plugin_package_task_reconciliation_digest_check', sql`length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.materializedRevisionDigest}) = 64 and ${table.materializedRevisionDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and (${table.previousLockDigest} is null or (length(${table.previousLockDigest}) = 64 and ${table.previousLockDigest} not glob '*[^0-9a-f]*')) and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_task_reconciliation_json_check', sql`length(${table.receiptJson}) between 2 and 8388608 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-task-reconciliation@v1' and json_extract(${table.receiptJson}, '$.generationDigest') = ${table.generationDigest} and json_extract(${table.receiptJson}, '$.projectId') = ${table.projectId} and json_extract(${table.receiptJson}, '$.packageName') = ${table.packageName} and json_extract(${table.receiptJson}, '$.generation') = ${table.generation} and json_extract(${table.receiptJson}, '$.materializedRevisionDigest') = ${table.materializedRevisionDigest} and json_extract(${table.receiptJson}, '$.lockDigest') = ${table.lockDigest} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), check( 'ql3_plugin_package_task_reconciliation_time_check', sql`${table.committedAtMs} >= 0`, ), uniqueIndex('ql3_plugin_package_task_reconciliation_generation_uidx').on( table.projectId, table.packageName, table.generation, ), uniqueIndex('ql3_plugin_package_task_reconciliation_receipt_uidx').on( table.generationDigest, table.receiptDigest, ), index('ql3_plugin_package_task_reconciliation_lock_idx').on( table.lockDigest, table.generationDigest, ), ], ); export const pluginPackageTaskReconciliationItems = sqliteTable( 'QingLong3PluginPackageTaskReconciliationItems', { generationDigest: text('generation_digest') .notNull() .references(() => pluginPackageTaskReconciliations.generationDigest, { onDelete: 'restrict', }), taskId: text('task_id').notNull(), revision: integer('revision').notNull(), disposition: text('disposition').notNull(), contentDigest: text('content_digest').notNull(), }, (table) => [ primaryKey({ columns: [table.generationDigest, table.taskId] }), check( 'ql3_plugin_package_task_reconciliation_item_identity_check', sql`length(${table.taskId}) between 1 and 128 and ${table.revision} between 1 and 2147483647`, ), check( 'ql3_plugin_package_task_reconciliation_item_disposition_check', sql`${table.disposition} in ('already_disabled','created','disabled','retained','updated')`, ), check( 'ql3_plugin_package_task_reconciliation_item_digest_check', sql`length(${table.contentDigest}) = 64 and ${table.contentDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_plugin_package_task_reconciliation_item_task_idx').on( table.taskId, table.generationDigest, ), ], ); export const triggers = sqliteTable( 'QingLong3Triggers', { projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), triggerId: text('trigger_id').notNull(), taskId: text('task_id').notNull(), currentRevision: integer('current_revision').notNull(), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.triggerId] }), foreignKey({ columns: [table.projectId, table.taskId], foreignColumns: [taskDefinitions.projectId, taskDefinitions.taskId], name: 'ql3_triggers_task_fk', }).onDelete('restrict'), check( 'ql3_triggers_id_check', sql`length(${table.projectId}) between 1 and 128 and length(${table.triggerId}) between 1 and 128 and length(${table.taskId}) between 1 and 128 and ${table.projectId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*' and ${table.triggerId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*' and ${table.taskId} not glob '*[' || char(0) || '-' || char(31) || char(127) || ']*'`, ), check( 'ql3_triggers_revision_check', sql`${table.currentRevision} between 1 and 2147483647`, ), check( 'ql3_triggers_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), uniqueIndex('ql3_triggers_task_uidx').on( table.projectId, table.triggerId, table.taskId, ), ], ); export const triggerRevisions = sqliteTable( 'QingLong3TriggerRevisions', { projectId: text('project_id').notNull(), triggerId: text('trigger_id').notNull(), revision: integer('revision').notNull(), mutationId: text('mutation_id').notNull(), taskId: text('task_id').notNull(), taskRevision: integer('task_revision').notNull(), taskContentDigest: text('task_content_digest').notNull(), specJson: text('spec_json').notNull(), enabled: integer('enabled', { mode: 'boolean' }).notNull(), contentDigest: text('content_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.triggerId, table.revision] }), foreignKey({ columns: [table.projectId, table.triggerId, table.taskId], foreignColumns: [triggers.projectId, triggers.triggerId, triggers.taskId], name: 'ql3_trigger_revisions_trigger_fk', }).onDelete('restrict'), foreignKey({ columns: [table.projectId, table.taskId, table.taskRevision], foreignColumns: [ taskDefinitionRevisions.projectId, taskDefinitionRevisions.taskId, taskDefinitionRevisions.revision, ], name: 'ql3_trigger_revisions_task_revision_fk', }).onDelete('restrict'), check( 'ql3_trigger_revisions_revision_check', sql`${table.revision} between 1 and 2147483647 and ${table.taskRevision} between 1 and 2147483647`, ), check( 'ql3_trigger_revisions_mutation_check', sql`length(${table.mutationId}) = 36 and substr(${table.mutationId}, 9, 1) = '-' and substr(${table.mutationId}, 14, 1) = '-' and substr(${table.mutationId}, 19, 1) = '-' and substr(${table.mutationId}, 24, 1) = '-' and replace(${table.mutationId}, '-', '') not glob '*[^0-9a-f]*'`, ), check( 'ql3_trigger_revisions_task_digest_check', sql`length(${table.taskContentDigest}) = 64 and ${table.taskContentDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_trigger_revisions_spec_check', sql`json_valid(${table.specJson}) and json_type(${table.specJson}) = 'object' and length(${table.specJson}) between 1 and 16384`, ), check( 'ql3_trigger_revisions_enabled_check', sql`${table.enabled} in (0, 1)`, ), check( 'ql3_trigger_revisions_digest_check', sql`length(${table.contentDigest}) = 64 and ${table.contentDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_trigger_revisions_created_check', sql`${table.createdAtMs} >= 0`, ), uniqueIndex('ql3_trigger_revisions_mutation_uidx').on(table.mutationId), index('ql3_trigger_revisions_project_enabled_idx').on( table.projectId, table.enabled, table.triggerId, table.revision, ), index('ql3_trigger_revisions_task_idx').on( table.projectId, table.taskId, table.taskRevision, table.triggerId, table.revision, ), ], ); export const localTriggerSchedules = sqliteTable( 'QingLong3LocalTriggerSchedules', { projectId: text('project_id').notNull(), triggerId: text('trigger_id').notNull(), triggerRevision: integer('trigger_revision').notNull(), nextFireAtMs: integer('next_fire_at_ms'), lastScheduledAtMs: integer('last_scheduled_at_ms'), stateVersion: integer('state_version').notNull().default(0), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.triggerId] }), foreignKey({ columns: [table.projectId, table.triggerId], foreignColumns: [triggers.projectId, triggers.triggerId], name: 'ql3_local_trigger_schedules_trigger_fk', }).onDelete('restrict'), check( 'ql3_local_trigger_schedules_revision_check', sql`${table.triggerRevision} between 1 and 2147483647`, ), check( 'ql3_local_trigger_schedules_state_check', sql`${table.stateVersion} >= 0`, ), check( 'ql3_local_trigger_schedules_time_check', sql`${table.updatedAtMs} >= 0 and (${table.nextFireAtMs} is null or ${table.nextFireAtMs} >= 0) and (${table.lastScheduledAtMs} is null or ${table.lastScheduledAtMs} >= 0)`, ), index('ql3_local_trigger_schedules_due_idx') .on(table.nextFireAtMs, table.projectId, table.triggerId) .where(sql`${table.nextFireAtMs} is not null`), index('ql3_local_trigger_schedules_initialize_idx') .on(table.projectId, table.triggerId) .where(sql`${table.nextFireAtMs} is null`), ], ); export const localProjectRoleBindings = sqliteTable( 'QingLong3ProjectRoleBindings', { projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), version: integer('version').notNull(), state: text('state').notNull(), role: text('role'), mutationId: text('mutation_id').notNull(), changedByType: text('changed_by_type').notNull(), changedById: text('changed_by_id').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [ table.projectId, table.subjectType, table.subjectId, table.version, ], }), check( 'ql3_local_bindings_subject_type_check', sql`${table.subjectType} in ('user','api_app','mcp_client','agent','system','worker')`, ), check( 'ql3_local_bindings_subject_id_check', sql`length(${table.subjectId}) between 1 and 255`, ), check( 'ql3_local_bindings_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_bindings_state_role_check', sql`(${table.state} = 'active' and ${table.role} in ('owner','admin','operator','viewer')) or (${table.state} = 'revoked' and ${table.role} is null)`, ), check( 'ql3_local_bindings_mutation_check', sql`length(${table.mutationId}) between 1 and 64`, ), check( 'ql3_local_bindings_changed_by_type_check', sql`${table.changedByType} in ('user','api_app','mcp_client','agent','system','worker')`, ), check( 'ql3_local_bindings_changed_by_id_check', sql`length(${table.changedById}) between 1 and 255`, ), check('ql3_local_bindings_created_check', sql`${table.createdAtMs} >= 0`), uniqueIndex('ql3_local_bindings_mutation_uidx').on( table.projectId, table.subjectType, table.subjectId, table.mutationId, ), index('ql3_local_bindings_current_idx').on( table.projectId, table.subjectType, table.subjectId, sql`${table.version} desc`, ), index('ql3_local_bindings_project_idx').on( table.projectId, sql`${table.version} desc`, ), ], ); export const localSecurityAuditEvents = sqliteTable( 'QingLong3SecurityAuditEvents', { eventId: text('event_id').primaryKey(), requestId: text('request_id').notNull(), operationId: text('operation_id').notNull(), projectId: text('project_id').references(() => localProjects.id, { onDelete: 'restrict', }), subjectType: text('subject_type'), subjectId: text('subject_id'), authenticationId: text('authentication_id'), outcome: text('outcome').notNull(), reasonsJson: text('reasons_json', { mode: 'json' }) .$type() .notNull(), fenceProjectVersion: integer('fence_project_version'), fenceBindingVersion: integer('fence_binding_version'), occurredAtMs: integer('occurred_at_ms').notNull(), }, (table) => [ check('ql3_local_audit_event_check', sql`length(${table.eventId}) = 36`), check( 'ql3_local_audit_request_check', sql`length(${table.requestId}) between 1 and 128`, ), check( 'ql3_local_audit_operation_check', sql`length(${table.operationId}) between 1 and 128`, ), check( 'ql3_local_audit_subject_check', sql`(${table.subjectType} is null and ${table.subjectId} is null and ${table.authenticationId} is null) or (${table.subjectType} in ('user','api_app','mcp_client','agent','system','worker') and length(${table.subjectId}) between 1 and 255 and length(${table.authenticationId}) between 1 and 128)`, ), check( 'ql3_local_audit_outcome_check', sql`${table.outcome} in ('authentication_rejected','authentication_unavailable','authorization_unavailable','denied','approval_required','allowed')`, ), check( 'ql3_local_audit_reasons_check', sql`json_valid(${table.reasonsJson}) and json_type(${table.reasonsJson}) = 'array' and json_array_length(${table.reasonsJson}) between 1 and 8 and length(${table.reasonsJson}) <= 2048`, ), check( 'ql3_local_audit_fence_check', sql`(${table.fenceProjectVersion} is null and ${table.fenceBindingVersion} is null) or (${table.fenceProjectVersion} between 1 and 2147483647 and (${table.fenceBindingVersion} is null or ${table.fenceBindingVersion} between 1 and 2147483647))`, ), check('ql3_local_audit_time_check', sql`${table.occurredAtMs} >= 0`), index('ql3_local_audit_project_time_idx').on( table.projectId, sql`${table.occurredAtMs} desc`, sql`${table.eventId} desc`, ), index('ql3_local_audit_subject_time_idx').on( table.subjectType, table.subjectId, sql`${table.occurredAtMs} desc`, sql`${table.eventId} desc`, ), ], ); export const localProjectAdministrationMutations = sqliteTable( 'QingLong3ProjectAdministrationMutations', { mutationId: text('mutation_id').primaryKey(), operation: text('operation').notNull(), authorityProjectId: text('authority_project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), projectName: text('project_name').notNull(), projectSlug: text('project_slug').notNull(), projectStatus: text('project_status').notNull(), projectVersion: integer('project_version').notNull(), expectedPreviousVersion: integer('expected_previous_version').notNull(), changedByType: text('changed_by_type').notNull(), changedById: text('changed_by_id').notNull(), initialOwnerBindingVersion: integer('initial_owner_binding_version'), auditEventId: text('audit_event_id') .notNull() .unique() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), projectCreatedAtMs: integer('project_created_at_ms').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_project_admin_mutation_id_check', sql`length(${table.mutationId}) = 36 and substr(${table.mutationId}, 9, 1) = '-' and substr(${table.mutationId}, 14, 1) = '-' and substr(${table.mutationId}, 19, 1) = '-' and substr(${table.mutationId}, 24, 1) = '-' and replace(${table.mutationId}, '-', '') not glob '*[^0-9a-f]*'`, ), check( 'ql3_project_admin_operation_check', sql`${table.operation} in ('create','archive','restore')`, ), check( 'ql3_project_admin_identity_check', sql`length(${table.authorityProjectId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.projectName}) between 1 and 255 and length(${table.projectSlug}) between 1 and 128 and ${table.projectSlug} = lower(${table.projectSlug}) and ${table.projectSlug} not glob '*[^a-z0-9-]*' and substr(${table.projectSlug}, 1, 1) not glob '[^a-z0-9]' and substr(${table.projectSlug}, -1, 1) not glob '[^a-z0-9]'`, ), check( 'ql3_project_admin_transition_check', sql`${table.projectVersion} = ${table.expectedPreviousVersion} + 1 and ${table.projectVersion} between 1 and 2147483647 and ${table.expectedPreviousVersion} between 0 and 2147483646 and ((${table.operation} = 'create' and ${table.expectedPreviousVersion} = 0 and ${table.projectStatus} = 'active' and ${table.initialOwnerBindingVersion} = 1) or (${table.operation} = 'archive' and ${table.expectedPreviousVersion} > 0 and ${table.projectStatus} = 'archived' and ${table.initialOwnerBindingVersion} is null) or (${table.operation} = 'restore' and ${table.expectedPreviousVersion} > 0 and ${table.projectStatus} = 'active' and ${table.initialOwnerBindingVersion} is null))`, ), check( 'ql3_project_admin_actor_check', sql`${table.changedByType} = 'user' and length(${table.changedById}) between 1 and 255`, ), check( 'ql3_project_admin_audit_check', sql`${table.auditEventId} = ${table.mutationId}`, ), check( 'ql3_project_admin_time_check', sql`${table.projectCreatedAtMs} >= 0 and ${table.createdAtMs} >= ${table.projectCreatedAtMs}`, ), uniqueIndex('ql3_project_admin_project_version_uidx').on( table.projectId, table.projectVersion, ), index('ql3_project_admin_authority_time_idx').on( table.authorityProjectId, sql`${table.createdAtMs} desc`, sql`${table.mutationId} desc`, ), ], ); export const localSecurityAuditCompactions = sqliteTable( 'QingLong3SecurityAuditCompactions', { mutationId: text('mutation_id').primaryKey(), requestId: text('request_id').notNull(), authorityProjectId: text('authority_project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), retentionMs: integer('retention_ms').notNull(), eligibleBeforeMs: integer('eligible_before_ms').notNull(), batchLimit: integer('batch_limit').notNull(), deletedCount: integer('deleted_count').notNull(), deletedPayloadBytes: integer('deleted_payload_bytes').notNull(), firstOccurredAtMs: integer('first_occurred_at_ms'), firstEventId: text('first_event_id'), lastOccurredAtMs: integer('last_occurred_at_ms'), lastEventId: text('last_event_id'), recordsDigest: text('records_digest').notNull(), auditEventId: text('audit_event_id') .notNull() .unique() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_audit_compaction_mutation_check', sql`length(${table.mutationId}) = 36 and substr(${table.mutationId}, 9, 1) = '-' and substr(${table.mutationId}, 14, 1) = '-' and substr(${table.mutationId}, 19, 1) = '-' and substr(${table.mutationId}, 24, 1) = '-' and replace(${table.mutationId}, '-', '') not glob '*[^0-9a-f]*'`, ), check( 'ql3_audit_compaction_request_check', sql`length(${table.requestId}) between 1 and 128`, ), check( 'ql3_audit_compaction_authority_check', sql`length(${table.authorityProjectId}) between 1 and 128`, ), check( 'ql3_audit_compaction_policy_check', sql`${table.retentionMs} between 2592000000 and 315360000000 and ${table.eligibleBeforeMs} >= 0 and ${table.eligibleBeforeMs} + ${table.retentionMs} <= ${table.createdAtMs} and ${table.batchLimit} between 1 and 512`, ), check( 'ql3_audit_compaction_result_check', sql`${table.deletedCount} between 0 and ${table.batchLimit} and ${table.deletedPayloadBytes} between 0 and 16777216 and length(${table.recordsDigest}) = 64 and ${table.recordsDigest} not glob '*[^0-9a-f]*' and ((${table.deletedCount} = 0 and ${table.deletedPayloadBytes} = 0 and ${table.firstOccurredAtMs} is null and ${table.firstEventId} is null and ${table.lastOccurredAtMs} is null and ${table.lastEventId} is null) or (${table.deletedCount} > 0 and ${table.deletedPayloadBytes} > 0 and ${table.firstOccurredAtMs} >= 0 and ${table.lastOccurredAtMs} >= ${table.firstOccurredAtMs} and length(${table.firstEventId}) = 36 and length(${table.lastEventId}) = 36))`, ), check( 'ql3_audit_compaction_audit_check', sql`${table.auditEventId} = ${table.mutationId}`, ), check( 'ql3_audit_compaction_time_check', sql`${table.createdAtMs} >= 2592000000`, ), index('ql3_audit_compaction_authority_time_idx').on( table.authorityProjectId, sql`${table.createdAtMs} desc`, sql`${table.mutationId} desc`, ), ], ); export const toolExecutionTraceAnchors = sqliteTable( 'ToolExecutionTraceAnchors', { traceId: text('trace_id').notNull(), spanId: text('span_id').notNull(), parentSpanId: text('parent_span_id'), projectId: text('project_id').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), invocationPlanDigest: text('invocation_plan_digest').notNull(), bindingDigest: text('binding_digest').notNull(), adapterDigest: text('adapter_digest').notNull(), redactionContractDigest: text('redaction_contract_digest').notNull(), auditContractDigest: text('audit_contract_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), traceDigest: text('trace_digest').notNull(), traceJson: text('trace_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ primaryKey({ columns: [table.traceId, table.spanId], name: 'tool_execution_trace_anchors_pkey', }), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_tool_execution_trace_step_fk', }).onDelete('cascade'), check( 'ql3_tool_execution_trace_identity_check', sql`length(${table.traceId}) = 32 and ${table.traceId} not glob '*[^0-9a-f]*' and length(${table.spanId}) = 16 and ${table.spanId} not glob '*[^0-9a-f]*' and (${table.parentSpanId} is null or (length(${table.parentSpanId}) = 16 and ${table.parentSpanId} not glob '*[^0-9a-f]*' and ${table.parentSpanId} <> ${table.spanId})) and length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128`, ), check( 'ql3_tool_execution_trace_digest_check', sql`length(${table.invocationPlanDigest}) = 64 and ${table.invocationPlanDigest} not glob '*[^0-9a-f]*' and length(${table.bindingDigest}) = 64 and ${table.bindingDigest} not glob '*[^0-9a-f]*' and length(${table.adapterDigest}) = 64 and ${table.adapterDigest} not glob '*[^0-9a-f]*' and length(${table.redactionContractDigest}) = 64 and ${table.redactionContractDigest} not glob '*[^0-9a-f]*' and length(${table.auditContractDigest}) = 64 and ${table.auditContractDigest} not glob '*[^0-9a-f]*' and length(${table.traceDigest}) = 64 and ${table.traceDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_execution_trace_time_check', sql`${table.createdAtMs} >= 0`, ), check( 'ql3_tool_execution_trace_json_check', sql`length(cast(${table.traceJson} as blob)) between 2 and 16384 and json_valid(${table.traceJson}) and json_type(${table.traceJson}) = 'object' and json_extract(${table.traceJson}, '$.schema') = 'qinglong/tool-execution-trace-anchor@v1' and json_extract(${table.traceJson}, '$.traceId') = ${table.traceId} and json_extract(${table.traceJson}, '$.spanId') = ${table.spanId} and json_extract(${table.traceJson}, '$.parentSpanId') is ${table.parentSpanId} and json_extract(${table.traceJson}, '$.projectId') = ${table.projectId} and json_extract(${table.traceJson}, '$.runId') = ${table.runId} and json_extract(${table.traceJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.traceJson}, '$.invocationPlanDigest') = ${table.invocationPlanDigest} and json_extract(${table.traceJson}, '$.bindingDigest') = ${table.bindingDigest} and json_extract(${table.traceJson}, '$.adapterDigest') = ${table.adapterDigest} and json_extract(${table.traceJson}, '$.redactionContractDigest') = ${table.redactionContractDigest} and json_extract(${table.traceJson}, '$.auditContractDigest') = ${table.auditContractDigest} and json_extract(${table.traceJson}, '$.createdAtMs') is ${table.createdAtMs} and json_extract(${table.traceJson}, '$.traceDigest') = ${table.traceDigest}`, ), index('ql3_tool_execution_trace_run_idx').on( table.runId, table.createdAtMs, table.traceId, table.spanId, ), index('ql3_tool_execution_trace_step_idx').on( table.runId, table.stepRunId, table.createdAtMs, table.traceId, table.spanId, ), ], ); export const toolExecutionAuditReceipts = sqliteTable( 'ToolExecutionAuditReceipts', { eventId: text('event_id') .primaryKey() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), projectId: text('project_id').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), traceId: text('trace_id').notNull(), spanId: text('span_id').notNull(), traceDigest: text('trace_digest').notNull(), invocationPlanDigest: text('invocation_plan_digest').notNull(), bindingDigest: text('binding_digest').notNull(), auditRecordDigest: text('audit_record_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), receiptDigest: text('receipt_digest').notNull(), auditJson: text('audit_json', { mode: 'json' }) .$type>() .notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.traceId, table.spanId], foreignColumns: [ toolExecutionTraceAnchors.traceId, toolExecutionTraceAnchors.spanId, ], name: 'ql3_tool_execution_audit_trace_fk', }).onDelete('cascade'), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_tool_execution_audit_step_fk', }).onDelete('cascade'), check( 'ql3_tool_execution_audit_identity_check', sql`length(${table.eventId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.traceId}) = 32 and ${table.traceId} not glob '*[^0-9a-f]*' and length(${table.spanId}) = 16 and ${table.spanId} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_execution_audit_digest_check', sql`length(${table.traceDigest}) = 64 and ${table.traceDigest} not glob '*[^0-9a-f]*' and length(${table.invocationPlanDigest}) = 64 and ${table.invocationPlanDigest} not glob '*[^0-9a-f]*' and length(${table.bindingDigest}) = 64 and ${table.bindingDigest} not glob '*[^0-9a-f]*' and length(${table.auditRecordDigest}) = 64 and ${table.auditRecordDigest} not glob '*[^0-9a-f]*' and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_execution_audit_time_check', sql`${table.createdAtMs} >= 0`, ), check( 'ql3_tool_execution_audit_json_check', sql`length(cast(${table.auditJson} as blob)) between 2 and 8192 and json_valid(${table.auditJson}) and json_type(${table.auditJson}) = 'object' and json_extract(${table.auditJson}, '$.eventId') = ${table.eventId} and json_extract(${table.auditJson}, '$.projectId') = ${table.projectId} and json_extract(${table.auditJson}, '$.operationId') = 'tool.invoke.start' and json_extract(${table.auditJson}, '$.outcome') = 'allowed' and json_type(${table.auditJson}, '$.fence') = 'object' and json_extract(${table.auditJson}, '$.occurredAtMs') is ${table.createdAtMs}`, ), check( 'ql3_tool_execution_audit_receipt_json_check', sql`length(cast(${table.receiptJson} as blob)) between 2 and 16384 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/tool-execution-audit-receipt@v1' and json_extract(${table.receiptJson}, '$.eventId') = ${table.eventId} and json_extract(${table.receiptJson}, '$.projectId') = ${table.projectId} and json_extract(${table.receiptJson}, '$.runId') = ${table.runId} and json_extract(${table.receiptJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.receiptJson}, '$.traceId') = ${table.traceId} and json_extract(${table.receiptJson}, '$.spanId') = ${table.spanId} and json_extract(${table.receiptJson}, '$.traceDigest') = ${table.traceDigest} and json_extract(${table.receiptJson}, '$.invocationPlanDigest') = ${table.invocationPlanDigest} and json_extract(${table.receiptJson}, '$.bindingDigest') = ${table.bindingDigest} and json_extract(${table.receiptJson}, '$.auditRecordDigest') = ${table.auditRecordDigest} and json_extract(${table.receiptJson}, '$.createdAtMs') is ${table.createdAtMs} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), uniqueIndex('ql3_tool_execution_audit_trace_uidx').on( table.traceId, table.spanId, ), index('ql3_tool_execution_audit_run_idx').on( table.runId, table.createdAtMs, table.traceId, table.spanId, ), index('ql3_tool_execution_audit_step_idx').on( table.runId, table.stepRunId, table.createdAtMs, table.eventId, ), ], ); export const toolExecutionStartBarriers = sqliteTable( 'ToolExecutionStartBarriers', { startId: text('start_id').primaryKey(), projectId: text('project_id').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), startedStepRunVersion: integer('started_step_run_version').notNull(), stepRunMutationId: text('step_run_mutation_id') .notNull() .references(() => stepRunMutations.mutationId, { onDelete: 'restrict', }), runEventId: text('run_event_id') .notNull() .references(() => runEvents.id, { onDelete: 'restrict' }), traceId: text('trace_id').notNull(), spanId: text('span_id').notNull(), auditEventId: text('audit_event_id') .notNull() .references(() => toolExecutionAuditReceipts.eventId, { onDelete: 'restrict', }), commandDigest: text('command_digest').notNull(), barrierDigest: text('barrier_digest').notNull(), startedAtMs: integer('started_at_ms').notNull(), barrierJson: text('barrier_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_tool_start_step_fk', }).onDelete('restrict'), foreignKey({ columns: [table.traceId, table.spanId], foreignColumns: [ toolExecutionTraceAnchors.traceId, toolExecutionTraceAnchors.spanId, ], name: 'ql3_tool_start_trace_fk', }).onDelete('restrict'), check( 'ql3_tool_start_identity_check', sql`length(${table.startId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.stepRunMutationId}) between 1 and 128 and length(${table.runEventId}) between 1 and 128 and length(${table.traceId}) = 32 and ${table.traceId} not glob '*[^0-9a-f]*' and length(${table.spanId}) = 16 and ${table.spanId} not glob '*[^0-9a-f]*' and length(${table.auditEventId}) between 1 and 128`, ), check( 'ql3_tool_start_version_time_check', sql`${table.startedStepRunVersion} between 2 and 2147483647 and ${table.startedAtMs} >= 0`, ), check( 'ql3_tool_start_digest_check', sql`length(${table.commandDigest}) = 64 and ${table.commandDigest} not glob '*[^0-9a-f]*' and length(${table.barrierDigest}) = 64 and ${table.barrierDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_start_json_check', sql`length(cast(${table.barrierJson} as blob)) between 2 and 16384 and json_valid(${table.barrierJson}) and json_type(${table.barrierJson}) = 'object' and json_extract(${table.barrierJson}, '$.schema') = 'qinglong/tool-execution-start-barrier@v1' and json_extract(${table.barrierJson}, '$.startId') = ${table.startId} and json_extract(${table.barrierJson}, '$.projectId') = ${table.projectId} and json_extract(${table.barrierJson}, '$.runId') = ${table.runId} and json_extract(${table.barrierJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.barrierJson}, '$.startedStepRunVersion') is ${table.startedStepRunVersion} and json_extract(${table.barrierJson}, '$.stepRunMutationId') = ${table.stepRunMutationId} and json_extract(${table.barrierJson}, '$.runEventId') = ${table.runEventId} and json_extract(${table.barrierJson}, '$.traceId') = ${table.traceId} and json_extract(${table.barrierJson}, '$.spanId') = ${table.spanId} and json_extract(${table.barrierJson}, '$.auditEventId') = ${table.auditEventId} and json_extract(${table.barrierJson}, '$.commandDigest') = ${table.commandDigest} and json_extract(${table.barrierJson}, '$.barrierDigest') = ${table.barrierDigest} and json_extract(${table.barrierJson}, '$.startedAtMs') is ${table.startedAtMs}`, ), uniqueIndex('ql3_tool_start_step_version_uidx').on( table.runId, table.stepRunId, table.startedStepRunVersion, ), uniqueIndex('ql3_tool_start_mutation_uidx').on(table.stepRunMutationId), uniqueIndex('ql3_tool_start_event_uidx').on(table.runEventId), uniqueIndex('ql3_tool_start_trace_uidx').on(table.traceId, table.spanId), uniqueIndex('ql3_tool_start_audit_uidx').on(table.auditEventId), index('ql3_tool_start_run_time_idx').on( table.runId, table.startedAtMs, table.startId, ), ], ); export const toolInvocationInputArtifacts = sqliteTable( 'ToolInvocationInputArtifacts', { artifactId: text('artifact_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), actionRef: text('action_ref').notNull(), inputDigest: text('input_digest').notNull(), invocationActionDigest: text('invocation_action_digest').notNull(), artifactDigest: text('artifact_digest').notNull(), keyId: text('key_id').notNull(), algorithm: text('algorithm').notNull(), plaintextBytes: integer('plaintext_bytes').notNull(), sealedAtMs: integer('sealed_at_ms').notNull(), artifactJson: text('artifact_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ check( 'ql3_tool_input_artifact_identity_check', sql`length(${table.artifactId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.actionRef}) between 1 and 255 and length(${table.keyId}) between 1 and 128 and ${table.algorithm} = 'aes-256-gcm'`, ), check( 'ql3_tool_input_artifact_digest_check', sql`length(${table.inputDigest}) = 64 and ${table.inputDigest} not glob '*[^0-9a-f]*' and length(${table.invocationActionDigest}) = 64 and ${table.invocationActionDigest} not glob '*[^0-9a-f]*' and length(${table.artifactDigest}) = 64 and ${table.artifactDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_input_artifact_budget_check', sql`${table.plaintextBytes} between 0 and 65536 and ${table.sealedAtMs} >= 0`, ), check( 'ql3_tool_input_artifact_json_check', sql`length(cast(${table.artifactJson} as blob)) between 2 and 98304 and json_valid(${table.artifactJson}) and json_type(${table.artifactJson}) = 'object' and json_extract(${table.artifactJson}, '$.schema') = 'qinglong/tool-invocation-input-artifact@v1' and json_extract(${table.artifactJson}, '$.artifactId') = ${table.artifactId} and json_extract(${table.artifactJson}, '$.projectId') = ${table.projectId} and json_extract(${table.artifactJson}, '$.actionRef') = ${table.actionRef} and json_extract(${table.artifactJson}, '$.inputDigest') = ${table.inputDigest} and json_extract(${table.artifactJson}, '$.invocationActionDigest') = ${table.invocationActionDigest} and json_extract(${table.artifactJson}, '$.artifactDigest') = ${table.artifactDigest} and json_extract(${table.artifactJson}, '$.keyId') = ${table.keyId} and json_extract(${table.artifactJson}, '$.algorithm') = ${table.algorithm} and json_extract(${table.artifactJson}, '$.plaintextBytes') is ${table.plaintextBytes} and json_extract(${table.artifactJson}, '$.sealedAtMs') is ${table.sealedAtMs}`, ), uniqueIndex('ql3_tool_input_artifact_action_uidx').on( table.projectId, table.actionRef, ), uniqueIndex('ql3_tool_input_artifact_start_binding_uidx').on( table.artifactId, table.artifactDigest, table.projectId, table.actionRef, table.inputDigest, ), index('ql3_tool_input_artifact_project_time_idx').on( table.projectId, table.sealedAtMs, table.artifactId, ), ], ); export const toolInvocationPreviewArtifacts = sqliteTable( 'ToolInvocationPreviewArtifacts', { artifactId: text('artifact_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), actionRef: text('action_ref').notNull(), actionDigest: text('action_digest').notNull(), previewDigest: text('preview_digest').notNull(), redactionContractDigest: text('redaction_contract_digest').notNull(), artifactDigest: text('artifact_digest').notNull(), byteLength: integer('byte_length').notNull(), sealedAtMs: integer('sealed_at_ms').notNull(), artifactJson: text('artifact_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ check( 'ql3_tool_preview_artifact_identity_check', sql`length(${table.artifactId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.actionRef}) between 1 and 255`, ), check( 'ql3_tool_preview_artifact_digest_check', sql`length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and length(${table.previewDigest}) = 64 and ${table.previewDigest} not glob '*[^0-9a-f]*' and length(${table.redactionContractDigest}) = 64 and ${table.redactionContractDigest} not glob '*[^0-9a-f]*' and length(${table.artifactDigest}) = 64 and ${table.artifactDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_preview_artifact_budget_check', sql`${table.byteLength} between 2 and 8192 and ${table.sealedAtMs} >= 0`, ), check( 'ql3_tool_preview_artifact_json_check', sql`length(cast(${table.artifactJson} as blob)) between 2 and 16384 and json_valid(${table.artifactJson}) and json_type(${table.artifactJson}) = 'object' and json_extract(${table.artifactJson}, '$.schema') = 'qinglong/tool-invocation-preview-artifact@v1' and json_extract(${table.artifactJson}, '$.artifactId') = ${table.artifactId} and json_extract(${table.artifactJson}, '$.projectId') = ${table.projectId} and json_extract(${table.artifactJson}, '$.actionRef') = ${table.actionRef} and json_extract(${table.artifactJson}, '$.actionDigest') = ${table.actionDigest} and json_extract(${table.artifactJson}, '$.previewDigest') = ${table.previewDigest} and json_extract(${table.artifactJson}, '$.redactionContractDigest') = ${table.redactionContractDigest} and json_extract(${table.artifactJson}, '$.artifactDigest') = ${table.artifactDigest} and json_extract(${table.artifactJson}, '$.byteLength') is ${table.byteLength} and json_extract(${table.artifactJson}, '$.sealedAtMs') is ${table.sealedAtMs}`, ), uniqueIndex('ql3_tool_preview_artifact_action_uidx').on( table.projectId, table.actionRef, ), uniqueIndex('ql3_tool_preview_artifact_action_digest_uidx').on( table.actionDigest, ), uniqueIndex('ql3_tool_preview_artifact_start_binding_uidx').on( table.artifactId, table.artifactDigest, table.projectId, table.actionRef, table.actionDigest, table.previewDigest, table.redactionContractDigest, ), index('ql3_tool_preview_artifact_project_time_idx').on( table.projectId, table.sealedAtMs, table.artifactId, ), ], ); export const toolExecutionStartArtifactBindings = sqliteTable( 'ToolExecutionStartArtifactBindings', { startId: text('start_id') .primaryKey() .references(() => toolExecutionStartBarriers.startId, { onDelete: 'restrict', }), projectId: text('project_id').notNull(), actionRef: text('action_ref').notNull(), inputArtifactId: text('input_artifact_id').notNull(), inputArtifactDigest: text('input_artifact_digest').notNull(), inputDigest: text('input_digest').notNull(), previewArtifactId: text('preview_artifact_id').notNull(), previewArtifactDigest: text('preview_artifact_digest').notNull(), actionDigest: text('action_digest').notNull(), previewDigest: text('preview_digest').notNull(), redactionContractDigest: text('redaction_contract_digest').notNull(), boundAtMs: integer('bound_at_ms').notNull(), }, (table) => [ foreignKey({ columns: [ table.inputArtifactId, table.inputArtifactDigest, table.projectId, table.actionRef, table.inputDigest, ], foreignColumns: [ toolInvocationInputArtifacts.artifactId, toolInvocationInputArtifacts.artifactDigest, toolInvocationInputArtifacts.projectId, toolInvocationInputArtifacts.actionRef, toolInvocationInputArtifacts.inputDigest, ], name: 'ql3_tool_start_input_artifact_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.previewArtifactId, table.previewArtifactDigest, table.projectId, table.actionRef, table.actionDigest, table.previewDigest, table.redactionContractDigest, ], foreignColumns: [ toolInvocationPreviewArtifacts.artifactId, toolInvocationPreviewArtifacts.artifactDigest, toolInvocationPreviewArtifacts.projectId, toolInvocationPreviewArtifacts.actionRef, toolInvocationPreviewArtifacts.actionDigest, toolInvocationPreviewArtifacts.previewDigest, toolInvocationPreviewArtifacts.redactionContractDigest, ], name: 'ql3_tool_start_preview_artifact_fk', }).onDelete('restrict'), check( 'ql3_tool_start_artifact_identity_check', sql`length(${table.startId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.actionRef}) between 1 and 255 and length(${table.inputArtifactId}) between 1 and 128 and length(${table.previewArtifactId}) between 1 and 128`, ), check( 'ql3_tool_start_artifact_digest_check', sql`length(${table.inputArtifactDigest}) = 64 and ${table.inputArtifactDigest} not glob '*[^0-9a-f]*' and length(${table.inputDigest}) = 64 and ${table.inputDigest} not glob '*[^0-9a-f]*' and length(${table.previewArtifactDigest}) = 64 and ${table.previewArtifactDigest} not glob '*[^0-9a-f]*' and length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and length(${table.previewDigest}) = 64 and ${table.previewDigest} not glob '*[^0-9a-f]*' and length(${table.redactionContractDigest}) = 64 and ${table.redactionContractDigest} not glob '*[^0-9a-f]*'`, ), check('ql3_tool_start_artifact_time_check', sql`${table.boundAtMs} >= 0`), index('ql3_tool_start_artifact_input_idx').on( table.inputArtifactId, table.startId, ), index('ql3_tool_start_artifact_preview_idx').on( table.previewArtifactId, table.startId, ), ], ); export const toolExecutionCompletions = sqliteTable( 'ToolExecutionCompletions', { startId: text('start_id').primaryKey(), artifactId: text('artifact_id').notNull(), projectId: text('project_id').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), startedStepRunVersion: integer('started_step_run_version').notNull(), completedStepRunVersion: integer('completed_step_run_version').notNull(), barrierDigest: text('barrier_digest').notNull(), adapterDigest: text('adapter_digest').notNull(), outputDigest: text('output_digest').notNull(), executionResultDigest: text('execution_result_digest').notNull(), artifactDigest: text('artifact_digest').notNull(), keyId: text('key_id').notNull(), algorithm: text('algorithm').notNull(), plaintextBytes: integer('plaintext_bytes').notNull(), stepRunMutationId: text('step_run_mutation_id').notNull(), stepRunMutationDigest: text('step_run_mutation_digest').notNull(), completedStepRunDigest: text('completed_step_run_digest').notNull(), runEventId: text('run_event_id').notNull(), completedAtMs: integer('completed_at_ms').notNull(), completionDigest: text('completion_digest').notNull(), artifactJson: text('artifact_json', { mode: 'json' }) .$type>() .notNull(), completionJson: text('completion_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.startId], foreignColumns: [toolExecutionStartBarriers.startId], name: 'ql3_tool_completion_start_fk', }).onDelete('restrict'), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_tool_completion_step_fk', }).onDelete('restrict'), foreignKey({ columns: [table.stepRunMutationId], foreignColumns: [stepRunMutations.mutationId], name: 'ql3_tool_completion_mutation_fk', }).onDelete('restrict'), foreignKey({ columns: [table.runEventId], foreignColumns: [runEvents.id], name: 'ql3_tool_completion_event_fk', }).onDelete('restrict'), check( 'ql3_tool_completion_identity_check', sql`length(${table.startId}) between 1 and 128 and length(${table.artifactId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.keyId}) between 1 and 128 and length(${table.stepRunMutationId}) between 1 and 128 and length(${table.runEventId}) between 1 and 128`, ), check( 'ql3_tool_completion_version_check', sql`${table.startedStepRunVersion} between 2 and 2147483646 and ${table.completedStepRunVersion} = ${table.startedStepRunVersion} + 1`, ), check( 'ql3_tool_completion_digest_check', sql`length(${table.barrierDigest}) = 64 and ${table.barrierDigest} not glob '*[^0-9a-f]*' and length(${table.adapterDigest}) = 64 and ${table.adapterDigest} not glob '*[^0-9a-f]*' and length(${table.outputDigest}) = 64 and ${table.outputDigest} not glob '*[^0-9a-f]*' and length(${table.executionResultDigest}) = 64 and ${table.executionResultDigest} not glob '*[^0-9a-f]*' and length(${table.artifactDigest}) = 64 and ${table.artifactDigest} not glob '*[^0-9a-f]*' and length(${table.stepRunMutationDigest}) = 64 and ${table.stepRunMutationDigest} not glob '*[^0-9a-f]*' and length(${table.completedStepRunDigest}) = 64 and ${table.completedStepRunDigest} not glob '*[^0-9a-f]*' and length(${table.completionDigest}) = 64 and ${table.completionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_completion_budget_check', sql`${table.algorithm} = 'aes-256-gcm' and ${table.plaintextBytes} between 0 and 262144 and ${table.completedAtMs} >= 0 and length(cast(${table.artifactJson} as blob)) between 2 and 393216 and length(cast(${table.completionJson} as blob)) between 2 and 24576`, ), check( 'ql3_tool_completion_json_check', sql`json_valid(${table.artifactJson}) and json_type(${table.artifactJson}) = 'object' and json_extract(${table.artifactJson}, '$.schema') = 'qinglong/tool-execution-result-artifact@v1' and json_extract(${table.artifactJson}, '$.artifactId') = ${table.artifactId} and json_extract(${table.artifactJson}, '$.projectId') = ${table.projectId} and json_extract(${table.artifactJson}, '$.startId') = ${table.startId} and json_extract(${table.artifactJson}, '$.runId') = ${table.runId} and json_extract(${table.artifactJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.artifactJson}, '$.barrierDigest') = ${table.barrierDigest} and json_extract(${table.artifactJson}, '$.adapterDigest') = ${table.adapterDigest} and json_extract(${table.artifactJson}, '$.outputDigest') = ${table.outputDigest} and json_extract(${table.artifactJson}, '$.executionResultDigest') = ${table.executionResultDigest} and json_extract(${table.artifactJson}, '$.artifactDigest') = ${table.artifactDigest} and json_extract(${table.artifactJson}, '$.keyId') = ${table.keyId} and json_extract(${table.artifactJson}, '$.algorithm') = ${table.algorithm} and json_extract(${table.artifactJson}, '$.plaintextBytes') = ${table.plaintextBytes} and json_extract(${table.artifactJson}, '$.sealedAtMs') = ${table.completedAtMs} and json_valid(${table.completionJson}) and json_type(${table.completionJson}) = 'object' and json_extract(${table.completionJson}, '$.schema') = 'qinglong/tool-execution-completion@v1' and json_extract(${table.completionJson}, '$.startId') = ${table.startId} and json_extract(${table.completionJson}, '$.projectId') = ${table.projectId} and json_extract(${table.completionJson}, '$.runId') = ${table.runId} and json_extract(${table.completionJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.completionJson}, '$.startedStepRunVersion') = ${table.startedStepRunVersion} and json_extract(${table.completionJson}, '$.completedStepRunVersion') = ${table.completedStepRunVersion} and json_extract(${table.completionJson}, '$.barrierDigest') = ${table.barrierDigest} and json_extract(${table.completionJson}, '$.adapterDigest') = ${table.adapterDigest} and json_extract(${table.completionJson}, '$.resultArtifact.artifactId') = ${table.artifactId} and json_extract(${table.completionJson}, '$.resultArtifact.artifactDigest') = ${table.artifactDigest} and json_extract(${table.completionJson}, '$.resultArtifact.outputDigest') = ${table.outputDigest} and json_extract(${table.completionJson}, '$.resultArtifact.executionResultDigest') = ${table.executionResultDigest} and json_extract(${table.completionJson}, '$.stepRunMutationId') = ${table.stepRunMutationId} and json_extract(${table.completionJson}, '$.stepRunMutationDigest') = ${table.stepRunMutationDigest} and json_extract(${table.completionJson}, '$.completedStepRunDigest') = ${table.completedStepRunDigest} and json_extract(${table.completionJson}, '$.runEventId') = ${table.runEventId} and json_extract(${table.completionJson}, '$.completedAtMs') = ${table.completedAtMs} and json_extract(${table.completionJson}, '$.completionDigest') = ${table.completionDigest}`, ), uniqueIndex('ql3_tool_completion_artifact_uidx').on(table.artifactId), uniqueIndex('ql3_tool_completion_mutation_uidx').on( table.stepRunMutationId, ), uniqueIndex('ql3_tool_completion_event_uidx').on(table.runEventId), uniqueIndex('ql3_tool_completion_step_version_uidx').on( table.runId, table.stepRunId, table.completedStepRunVersion, ), index('ql3_tool_completion_project_time_idx').on( table.projectId, table.completedAtMs, table.startId, ), ], ); export const toolExecutionFailureCompletions = sqliteTable( 'ToolExecutionFailureCompletions', { startId: text('start_id').primaryKey(), projectId: text('project_id').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), startedStepRunVersion: integer('started_step_run_version').notNull(), completedStepRunVersion: integer('completed_step_run_version').notNull(), barrierDigest: text('barrier_digest').notNull(), adapterDigest: text('adapter_digest').notNull(), outcome: text('outcome').notNull(), resultCode: text('result_code').notNull(), errorSummary: text('error_summary').notNull(), stepRunMutationId: text('step_run_mutation_id').notNull(), stepRunMutationDigest: text('step_run_mutation_digest').notNull(), completedStepRunDigest: text('completed_step_run_digest').notNull(), runEventId: text('run_event_id').notNull(), completedAtMs: integer('completed_at_ms').notNull(), completionDigest: text('completion_digest').notNull(), completionJson: text('completion_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.startId], foreignColumns: [toolExecutionStartBarriers.startId], name: 'ql3_tool_failure_completion_start_fk', }).onDelete('restrict'), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_tool_failure_completion_step_fk', }).onDelete('restrict'), foreignKey({ columns: [table.stepRunMutationId], foreignColumns: [stepRunMutations.mutationId], name: 'ql3_tool_failure_completion_mutation_fk', }).onDelete('restrict'), foreignKey({ columns: [table.runEventId], foreignColumns: [runEvents.id], name: 'ql3_tool_failure_completion_event_fk', }).onDelete('restrict'), check( 'ql3_tool_failure_completion_identity_check', sql`length(${table.startId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.stepRunMutationId}) between 1 and 128 and length(${table.runEventId}) between 1 and 128`, ), check( 'ql3_tool_failure_completion_version_check', sql`${table.startedStepRunVersion} between 2 and 2147483646 and ${table.completedStepRunVersion} = ${table.startedStepRunVersion} + 1`, ), check( 'ql3_tool_failure_completion_digest_check', sql`length(${table.barrierDigest}) = 64 and ${table.barrierDigest} not glob '*[^0-9a-f]*' and length(${table.adapterDigest}) = 64 and ${table.adapterDigest} not glob '*[^0-9a-f]*' and length(${table.stepRunMutationDigest}) = 64 and ${table.stepRunMutationDigest} not glob '*[^0-9a-f]*' and length(${table.completedStepRunDigest}) = 64 and ${table.completedStepRunDigest} not glob '*[^0-9a-f]*' and length(${table.completionDigest}) = 64 and ${table.completionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_failure_completion_fact_check', sql`(${table.outcome} = 'failed' and ${table.resultCode} = 'tool_adapter_failed' and ${table.errorSummary} = 'Trusted Tool execution failed') or (${table.outcome} = 'timed_out' and ${table.resultCode} = 'tool_deadline_exceeded' and ${table.errorSummary} = 'Trusted Tool execution deadline exceeded')`, ), check( 'ql3_tool_failure_completion_budget_check', sql`${table.completedAtMs} >= 0 and length(cast(${table.completionJson} as blob)) between 2 and 24576`, ), check( 'ql3_tool_failure_completion_json_check', sql`json_valid(${table.completionJson}) and json_type(${table.completionJson}) = 'object' and json_extract(${table.completionJson}, '$.schema') = 'qinglong/tool-execution-failure-completion@v1' and json_extract(${table.completionJson}, '$.startId') = ${table.startId} and json_extract(${table.completionJson}, '$.projectId') = ${table.projectId} and json_extract(${table.completionJson}, '$.runId') = ${table.runId} and json_extract(${table.completionJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.completionJson}, '$.startedStepRunVersion') = ${table.startedStepRunVersion} and json_extract(${table.completionJson}, '$.completedStepRunVersion') = ${table.completedStepRunVersion} and json_extract(${table.completionJson}, '$.barrierDigest') = ${table.barrierDigest} and json_extract(${table.completionJson}, '$.adapterDigest') = ${table.adapterDigest} and json_extract(${table.completionJson}, '$.outcome') = ${table.outcome} and json_extract(${table.completionJson}, '$.resultCode') = ${table.resultCode} and json_extract(${table.completionJson}, '$.errorSummary') = ${table.errorSummary} and json_extract(${table.completionJson}, '$.stepRunMutationId') = ${table.stepRunMutationId} and json_extract(${table.completionJson}, '$.stepRunMutationDigest') = ${table.stepRunMutationDigest} and json_extract(${table.completionJson}, '$.completedStepRunDigest') = ${table.completedStepRunDigest} and json_extract(${table.completionJson}, '$.runEventId') = ${table.runEventId} and json_extract(${table.completionJson}, '$.completedAtMs') = ${table.completedAtMs} and json_extract(${table.completionJson}, '$.completionDigest') = ${table.completionDigest}`, ), uniqueIndex('ql3_tool_failure_completion_mutation_uidx').on( table.stepRunMutationId, ), uniqueIndex('ql3_tool_failure_completion_event_uidx').on(table.runEventId), uniqueIndex('ql3_tool_failure_completion_step_version_uidx').on( table.runId, table.stepRunId, table.completedStepRunVersion, ), index('ql3_tool_failure_completion_project_time_idx').on( table.projectId, table.completedAtMs, table.startId, ), ], ); export const toolResultKeyCatalogGenerations = sqliteTable( 'ToolResultKeyCatalogGenerations', { authority: text('authority').notNull(), generation: integer('generation').notNull(), previousGeneration: integer('previous_generation'), previousCatalogDigest: text('previous_catalog_digest'), activeKeyId: text('active_key_id'), mutationKind: text('mutation_kind').notNull(), mutationId: text('mutation_id').notNull(), catalogDigest: text('catalog_digest').notNull(), commandDigest: text('command_digest').notNull(), committedAtMs: integer('committed_at_ms').notNull(), catalogJson: text('catalog_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ primaryKey({ columns: [table.authority, table.generation] }), foreignKey({ columns: [ table.authority, table.previousGeneration, table.previousCatalogDigest, ], foreignColumns: [table.authority, table.generation, table.catalogDigest], name: 'ql3_tool_result_key_catalog_previous_fk', }).onDelete('restrict'), check( 'ql3_tool_result_key_catalog_authority_check', sql`${table.authority} = 'trusted-tool-results'`, ), check( 'ql3_tool_result_key_catalog_generation_check', sql`${table.generation} between 1 and 2147483647 and ((${table.generation} = 1 and ${table.previousGeneration} is null and ${table.previousCatalogDigest} is null and ${table.mutationKind} = 'bootstrap') or (${table.generation} > 1 and ${table.previousGeneration} = ${table.generation} - 1 and ${table.previousCatalogDigest} is not null and ${table.mutationKind} in ('rotate', 'retire', 'mark_lost', 'restore')))`, ), check( 'ql3_tool_result_key_catalog_identity_check', sql`${table.activeKeyId} is null or length(${table.activeKeyId}) between 1 and 128 and ${table.activeKeyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.activeKeyId}, 1, 1) glob '[A-Za-z0-9]'`, ), check( 'ql3_tool_result_key_catalog_digest_check', sql`(${table.previousCatalogDigest} is null or length(${table.previousCatalogDigest}) = 64 and ${table.previousCatalogDigest} not glob '*[^0-9a-f]*') and length(${table.catalogDigest}) = 64 and ${table.catalogDigest} not glob '*[^0-9a-f]*' and length(${table.commandDigest}) = 64 and ${table.commandDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_result_key_catalog_budget_check', sql`${table.committedAtMs} >= 0 and length(${table.mutationId}) between 1 and 128 and length(cast(${table.catalogJson} as blob)) between 2 and 65536`, ), check( 'ql3_tool_result_key_catalog_json_check', sql`json_valid(${table.catalogJson}) and json_type(${table.catalogJson}) = 'object' and json_extract(${table.catalogJson}, '$.schema') = 'qinglong/tool-result-key-catalog@v1' and json_extract(${table.catalogJson}, '$.generation') = ${table.generation} and ((${table.previousCatalogDigest} is null and json_type(${table.catalogJson}, '$.previousCatalogDigest') = 'null') or json_extract(${table.catalogJson}, '$.previousCatalogDigest') = ${table.previousCatalogDigest}) and ((${table.activeKeyId} is null and json_type(${table.catalogJson}, '$.activeKeyId') = 'null') or json_extract(${table.catalogJson}, '$.activeKeyId') = ${table.activeKeyId}) and json_extract(${table.catalogJson}, '$.mutationKind') = ${table.mutationKind} and json_extract(${table.catalogJson}, '$.mutationId') = ${table.mutationId} and json_extract(${table.catalogJson}, '$.catalogDigest') = ${table.catalogDigest} and json_extract(${table.catalogJson}, '$.committedAtMs') = ${table.committedAtMs} and json_type(${table.catalogJson}, '$.keys') = 'array' and json_array_length(json_extract(${table.catalogJson}, '$.keys')) between 1 and 64`, ), index('ql3_tool_result_key_catalog_current_idx').on( table.authority, sql`${table.generation} desc`, ), ], ); export const toolExecutionResultKeyBindings = sqliteTable( 'ToolExecutionResultKeyBindings', { startId: text('start_id').primaryKey(), artifactId: text('artifact_id').notNull(), artifactDigest: text('artifact_digest').notNull(), catalogAuthority: text('catalog_authority').notNull(), catalogGeneration: integer('catalog_generation').notNull(), catalogDigest: text('catalog_digest').notNull(), keyId: text('key_id').notNull(), materialProof: text('material_proof').notNull(), bindingDigest: text('binding_digest').notNull(), }, (table) => [ foreignKey({ columns: [table.startId], foreignColumns: [toolExecutionCompletions.startId], name: 'ql3_tool_result_key_binding_completion_fk', }).onDelete('restrict'), foreignKey({ columns: [table.artifactId], foreignColumns: [toolExecutionCompletions.artifactId], name: 'ql3_tool_result_key_binding_artifact_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.catalogAuthority, table.catalogGeneration, table.catalogDigest, ], foreignColumns: [ toolResultKeyCatalogGenerations.authority, toolResultKeyCatalogGenerations.generation, toolResultKeyCatalogGenerations.catalogDigest, ], name: 'ql3_tool_result_key_binding_catalog_fk', }).onDelete('restrict'), check( 'ql3_tool_result_key_binding_authority_check', sql`${table.catalogAuthority} = 'trusted-tool-results'`, ), check( 'ql3_tool_result_key_binding_identity_check', sql`length(${table.startId}) between 1 and 128 and length(${table.artifactId}) between 1 and 128 and length(${table.keyId}) between 1 and 128 and ${table.keyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.keyId}, 1, 1) glob '[A-Za-z0-9]' and ${table.catalogGeneration} between 1 and 2147483647`, ), check( 'ql3_tool_result_key_binding_digest_check', sql`length(${table.artifactDigest}) = 64 and ${table.artifactDigest} not glob '*[^0-9a-f]*' and length(${table.catalogDigest}) = 64 and ${table.catalogDigest} not glob '*[^0-9a-f]*' and length(${table.materialProof}) = 64 and ${table.materialProof} not glob '*[^0-9a-f]*' and length(${table.bindingDigest}) = 64 and ${table.bindingDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_tool_result_key_binding_catalog_idx').on( table.catalogGeneration, table.keyId, table.startId, ), ], ); export const toolExecutionResultRekeyOverlays = sqliteTable( 'ToolExecutionResultRekeyOverlays', { overlayId: text('overlay_id').primaryKey(), artifactId: text('artifact_id').notNull(), sourceBindingDigest: text('source_binding_digest').notNull(), revision: integer('revision').notNull(), previousOverlayDigest: text('previous_overlay_digest'), fromKeyId: text('from_key_id').notNull(), targetCatalogAuthority: text('target_catalog_authority').notNull(), targetCatalogGeneration: integer('target_catalog_generation').notNull(), targetCatalogDigest: text('target_catalog_digest').notNull(), targetKeyId: text('target_key_id').notNull(), targetMaterialProof: text('target_material_proof').notNull(), mutationId: text('mutation_id').notNull().unique(), commandDigest: text('command_digest').notNull(), overlayDigest: text('overlay_digest').notNull().unique(), rekeyedAtMs: integer('rekeyed_at_ms').notNull(), overlayJson: text('overlay_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.artifactId], foreignColumns: [toolExecutionResultKeyBindings.artifactId], name: 'ql3_tool_result_rekey_artifact_fk', }).onDelete('restrict'), foreignKey({ columns: [table.sourceBindingDigest], foreignColumns: [toolExecutionResultKeyBindings.bindingDigest], name: 'ql3_tool_result_rekey_binding_fk', }).onDelete('restrict'), foreignKey({ columns: [table.previousOverlayDigest], foreignColumns: [table.overlayDigest], name: 'ql3_tool_result_rekey_previous_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.targetCatalogAuthority, table.targetCatalogGeneration, table.targetCatalogDigest, ], foreignColumns: [ toolResultKeyCatalogGenerations.authority, toolResultKeyCatalogGenerations.generation, toolResultKeyCatalogGenerations.catalogDigest, ], name: 'ql3_tool_result_rekey_catalog_fk', }).onDelete('restrict'), check( 'ql3_tool_result_rekey_revision_check', sql`${table.revision} between 1 and 2147483647 and ((${table.revision} = 1 and ${table.previousOverlayDigest} is null) or (${table.revision} > 1 and ${table.previousOverlayDigest} is not null))`, ), check( 'ql3_tool_result_rekey_authority_check', sql`${table.targetCatalogAuthority} = 'trusted-tool-results'`, ), check( 'ql3_tool_result_rekey_identity_check', sql`length(${table.overlayId}) between 1 and 128 and length(${table.artifactId}) between 1 and 128 and length(${table.mutationId}) between 1 and 128 and length(${table.fromKeyId}) between 1 and 128 and ${table.fromKeyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.fromKeyId}, 1, 1) glob '[A-Za-z0-9]' and length(${table.targetKeyId}) between 1 and 128 and ${table.targetKeyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.targetKeyId}, 1, 1) glob '[A-Za-z0-9]' and ${table.fromKeyId} <> ${table.targetKeyId} and ${table.targetCatalogGeneration} between 1 and 2147483647`, ), check( 'ql3_tool_result_rekey_digest_check', sql`(${table.previousOverlayDigest} is null or length(${table.previousOverlayDigest}) = 64 and ${table.previousOverlayDigest} not glob '*[^0-9a-f]*') and length(${table.sourceBindingDigest}) = 64 and ${table.sourceBindingDigest} not glob '*[^0-9a-f]*' and length(${table.targetCatalogDigest}) = 64 and ${table.targetCatalogDigest} not glob '*[^0-9a-f]*' and length(${table.targetMaterialProof}) = 64 and ${table.targetMaterialProof} not glob '*[^0-9a-f]*' and length(${table.commandDigest}) = 64 and ${table.commandDigest} not glob '*[^0-9a-f]*' and length(${table.overlayDigest}) = 64 and ${table.overlayDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_result_rekey_budget_check', sql`${table.rekeyedAtMs} >= 0 and length(cast(${table.overlayJson} as blob)) between 2 and 393216`, ), check( 'ql3_tool_result_rekey_json_check', sql`json_valid(${table.overlayJson}) and json_type(${table.overlayJson}) = 'object' and json_extract(${table.overlayJson}, '$.schema') = 'qinglong/tool-execution-result-rekey-overlay@v1' and json_extract(${table.overlayJson}, '$.overlayId') = ${table.overlayId} and json_extract(${table.overlayJson}, '$.sourceArtifact.artifactId') = ${table.artifactId} and json_extract(${table.overlayJson}, '$.sourceBindingDigest') = ${table.sourceBindingDigest} and json_extract(${table.overlayJson}, '$.revision') = ${table.revision} and ((${table.previousOverlayDigest} is null and json_type(${table.overlayJson}, '$.previousOverlayDigest') = 'null') or json_extract(${table.overlayJson}, '$.previousOverlayDigest') = ${table.previousOverlayDigest}) and json_extract(${table.overlayJson}, '$.fromKeyId') = ${table.fromKeyId} and json_extract(${table.overlayJson}, '$.targetCatalogFence.generation') = ${table.targetCatalogGeneration} and json_extract(${table.overlayJson}, '$.targetCatalogFence.catalogDigest') = ${table.targetCatalogDigest} and json_extract(${table.overlayJson}, '$.targetCatalogFence.keyId') = ${table.targetKeyId} and json_extract(${table.overlayJson}, '$.targetCatalogFence.materialProof') = ${table.targetMaterialProof} and json_extract(${table.overlayJson}, '$.rekeyedAtMs') = ${table.rekeyedAtMs} and json_extract(${table.overlayJson}, '$.overlayDigest') = ${table.overlayDigest}`, ), index('ql3_tool_result_rekey_artifact_idx').on( table.artifactId, sql`${table.revision} desc`, ), index('ql3_tool_result_rekey_target_idx').on( table.targetKeyId, table.artifactId, sql`${table.revision} desc`, ), ], ); export const toolExecutionResultRekeyHeads = sqliteTable( 'ToolExecutionResultRekeyHeads', { artifactId: text('artifact_id').primaryKey(), revision: integer('revision').notNull(), overlayId: text('overlay_id').notNull().unique(), overlayDigest: text('overlay_digest').notNull().unique(), targetCatalogGeneration: integer('target_catalog_generation').notNull(), targetCatalogDigest: text('target_catalog_digest').notNull(), targetKeyId: text('target_key_id').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ foreignKey({ columns: [table.artifactId, table.revision, table.overlayDigest], foreignColumns: [ toolExecutionResultRekeyOverlays.artifactId, toolExecutionResultRekeyOverlays.revision, toolExecutionResultRekeyOverlays.overlayDigest, ], name: 'ql3_tool_result_rekey_head_overlay_fk', }).onDelete('restrict'), check( 'ql3_tool_result_rekey_head_identity_check', sql`${table.revision} between 1 and 2147483647 and length(${table.artifactId}) between 1 and 128 and length(${table.overlayId}) between 1 and 128 and length(${table.targetKeyId}) between 1 and 128 and ${table.targetKeyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.targetKeyId}, 1, 1) glob '[A-Za-z0-9]' and ${table.targetCatalogGeneration} between 1 and 2147483647 and ${table.updatedAtMs} >= 0`, ), check( 'ql3_tool_result_rekey_head_digest_check', sql`length(${table.overlayDigest}) = 64 and ${table.overlayDigest} not glob '*[^0-9a-f]*' and length(${table.targetCatalogDigest}) = 64 and ${table.targetCatalogDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_tool_result_rekey_head_target_idx').on( table.targetKeyId, table.artifactId, ), ], ); export const toolResultKeyRetirementReceipts = sqliteTable( 'ToolResultKeyRetirementReceipts', { receiptDigest: text('receipt_digest').primaryKey(), catalogAuthority: text('catalog_authority').notNull(), catalogGeneration: integer('catalog_generation').notNull(), catalogDigest: text('catalog_digest').notNull(), keyId: text('key_id').notNull(), materialProof: text('material_proof').notNull(), mutationId: text('mutation_id').notNull().unique(), commandDigest: text('command_digest').notNull(), bindingCount: integer('binding_count').notNull(), overlayHeadCount: integer('overlay_head_count').notNull(), uncoveredBindingCount: integer('uncovered_binding_count').notNull(), uncoveredOverlayHeadCount: integer( 'uncovered_overlay_head_count', ).notNull(), coverageDigest: text('coverage_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [ table.catalogAuthority, table.catalogGeneration, table.catalogDigest, ], foreignColumns: [ toolResultKeyCatalogGenerations.authority, toolResultKeyCatalogGenerations.generation, toolResultKeyCatalogGenerations.catalogDigest, ], name: 'ql3_tool_result_key_retirement_catalog_fk', }).onDelete('restrict'), check( 'ql3_tool_result_key_retirement_authority_check', sql`${table.catalogAuthority} = 'trusted-tool-results'`, ), check( 'ql3_tool_result_key_retirement_identity_check', sql`${table.catalogGeneration} between 1 and 2147483647 and length(${table.keyId}) between 1 and 128 and ${table.keyId} not glob '*[^A-Za-z0-9._-]*' and substr(${table.keyId}, 1, 1) glob '[A-Za-z0-9]' and length(${table.mutationId}) between 1 and 128`, ), check( 'ql3_tool_result_key_retirement_count_check', sql`${table.bindingCount} between 0 and 2147483647 and ${table.overlayHeadCount} between 0 and 2147483647 and ${table.uncoveredBindingCount} = 0 and ${table.uncoveredOverlayHeadCount} = 0 and ${table.createdAtMs} >= 0`, ), check( 'ql3_tool_result_key_retirement_digest_check', sql`length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*' and length(${table.catalogDigest}) = 64 and ${table.catalogDigest} not glob '*[^0-9a-f]*' and length(${table.materialProof}) = 64 and ${table.materialProof} not glob '*[^0-9a-f]*' and length(${table.commandDigest}) = 64 and ${table.commandDigest} not glob '*[^0-9a-f]*' and length(${table.coverageDigest}) = 64 and ${table.coverageDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_tool_result_key_retirement_json_check', sql`json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/tool-result-key-retirement-receipt@v1' and json_extract(${table.receiptJson}, '$.catalogGeneration') = ${table.catalogGeneration} and json_extract(${table.receiptJson}, '$.catalogDigest') = ${table.catalogDigest} and json_extract(${table.receiptJson}, '$.keyId') = ${table.keyId} and json_extract(${table.receiptJson}, '$.materialProof') = ${table.materialProof} and json_extract(${table.receiptJson}, '$.mutationId') = ${table.mutationId} and json_extract(${table.receiptJson}, '$.bindingCount') = ${table.bindingCount} and json_extract(${table.receiptJson}, '$.overlayHeadCount') = ${table.overlayHeadCount} and json_extract(${table.receiptJson}, '$.uncoveredBindingCount') = 0 and json_extract(${table.receiptJson}, '$.uncoveredOverlayHeadCount') = 0 and json_extract(${table.receiptJson}, '$.coverageDigest') = ${table.coverageDigest} and json_extract(${table.receiptJson}, '$.createdAtMs') = ${table.createdAtMs} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), index('ql3_tool_result_key_retirement_catalog_idx').on( table.catalogGeneration, table.keyId, ), ], ); export const pluginPackageAdmissionReceipts = sqliteTable( 'QingLong3PluginPackageAdmissionReceipts', { dispatchId: text('dispatch_id') .primaryKey() .references(() => approvedActionDispatches.dispatchId, { onDelete: 'restrict', }), dispatchDigest: text('dispatch_digest').notNull(), approvalRequestId: text('approval_request_id') .notNull() .references(() => approvalRequests.requestId, { onDelete: 'restrict' }), actionRef: text('action_ref').notNull(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), packageName: text('package_name').notNull(), installationId: text('installation_id') .notNull() .references(() => pluginPackageInstalls.installationId, { onDelete: 'restrict', }), lockDigest: text('lock_digest').notNull(), recordDigest: text('record_digest').notNull(), mutationId: text('mutation_id').notNull(), mutationDigest: text('mutation_digest').notNull(), auditEventId: text('audit_event_id') .notNull() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), admittedAtMs: integer('admitted_at_ms').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), receiptDigest: text('receipt_digest').notNull(), }, (table) => [ check( 'ql3_plugin_package_admission_identity_check', sql`length(${table.dispatchId}) between 1 and 128 and length(${table.approvalRequestId}) between 1 and 128 and length(${table.actionRef}) between 1 and 255 and length(${table.projectId}) between 1 and 128 and length(${table.packageName}) between 1 and 64 and length(${table.installationId}) between 1 and 128 and length(${table.mutationId}) between 1 and 128 and length(${table.auditEventId}) = 36`, ), check( 'ql3_plugin_package_admission_digest_check', sql`length(${table.dispatchDigest}) = 64 and ${table.dispatchDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.recordDigest}) = 64 and ${table.recordDigest} not glob '*[^0-9a-f]*' and length(${table.mutationDigest}) = 64 and ${table.mutationDigest} not glob '*[^0-9a-f]*' and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_admission_json_check', sql`length(${table.receiptJson}) between 2 and 65536 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-admission-receipt@v1' and json_extract(${table.receiptJson}, '$.dispatchId') = ${table.dispatchId} and json_extract(${table.receiptJson}, '$.dispatchDigest') = ${table.dispatchDigest} and json_extract(${table.receiptJson}, '$.approvalRequestId') = ${table.approvalRequestId} and json_extract(${table.receiptJson}, '$.actionRef') = ${table.actionRef} and json_extract(${table.receiptJson}, '$.projectId') = ${table.projectId} and json_extract(${table.receiptJson}, '$.packageName') = ${table.packageName} and json_extract(${table.receiptJson}, '$.installationId') = ${table.installationId} and json_extract(${table.receiptJson}, '$.lockDigest') = ${table.lockDigest} and json_extract(${table.receiptJson}, '$.recordDigest') = ${table.recordDigest} and json_extract(${table.receiptJson}, '$.mutationId') = ${table.mutationId} and json_extract(${table.receiptJson}, '$.mutationDigest') = ${table.mutationDigest} and json_extract(${table.receiptJson}, '$.auditEventId') = ${table.auditEventId} and json_extract(${table.receiptJson}, '$.admittedAtMs') = ${table.admittedAtMs} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), check( 'ql3_plugin_package_admission_time_check', sql`${table.admittedAtMs} >= 0`, ), uniqueIndex('ql3_plugin_package_admission_install_uidx').on( table.installationId, ), uniqueIndex('ql3_plugin_package_admission_audit_uidx').on( table.auditEventId, ), index('ql3_plugin_package_admission_project_idx').on( table.projectId, table.admittedAtMs, table.dispatchId, ), ], ); export const legacyAdoptions = sqliteTable( 'QingLong3LegacyAdoptions', { mutationId: text('mutation_id').primaryKey(), decisionId: text('decision_id').notNull(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), profile: text('profile').notNull(), planDigest: text('plan_digest').notNull(), inventoryDigest: text('inventory_digest').notNull(), decisionDigest: text('decision_digest').notNull(), receiptDigest: text('receipt_digest').notNull(), authorizationFileDigest: text('authorization_file_digest').notNull(), publicationDigest: text('publication_digest').notNull(), rowCount: integer('row_count').notNull(), adoptedTaskCount: integer('adopted_task_count').notNull(), adoptedTriggerCount: integer('adopted_trigger_count').notNull(), skippedCount: integer('skipped_count').notNull(), auditEventId: text('audit_event_id') .notNull() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_legacy_adoptions_mutation_check', sql`length(${table.mutationId}) = 36 and ${table.auditEventId} = ${table.mutationId}`, ), check( 'ql3_legacy_adoptions_decision_check', sql`length(${table.decisionId}) = 36 and substr(${table.decisionId}, 15, 1) = '7' and replace(${table.decisionId}, '-', '') not glob '*[^0-9a-f]*'`, ), check( 'ql3_legacy_adoptions_profile_check', sql`${table.profile} in ('edge', 'standalone')`, ), check( 'ql3_legacy_adoptions_digest_check', sql`length(${table.planDigest}) = 64 and ${table.planDigest} not glob '*[^0-9a-f]*' and length(${table.inventoryDigest}) = 64 and ${table.inventoryDigest} not glob '*[^0-9a-f]*' and length(${table.decisionDigest}) = 64 and ${table.decisionDigest} not glob '*[^0-9a-f]*' and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*' and length(${table.authorizationFileDigest}) = 64 and ${table.authorizationFileDigest} not glob '*[^0-9a-f]*' and length(${table.publicationDigest}) = 64 and ${table.publicationDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_legacy_adoptions_count_check', sql`${table.rowCount} between 0 and 100000 and ${table.adoptedTaskCount} between 0 and ${table.rowCount} and ${table.skippedCount} between 0 and ${table.rowCount} and ${table.adoptedTaskCount} + ${table.skippedCount} = ${table.rowCount} and ${table.adoptedTriggerCount} between 0 and 500000`, ), check('ql3_legacy_adoptions_created_check', sql`${table.createdAtMs} >= 0`), uniqueIndex('ql3_legacy_adoptions_decision_uidx').on(table.decisionId), index('ql3_legacy_adoptions_project_time_idx').on( table.projectId, sql`${table.createdAtMs} desc`, sql`${table.mutationId} desc`, ), ], ); export const localIdentitySubjects = sqliteTable( 'QingLong3IdentitySubjects', { subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), status: text('status').notNull(), version: integer('version').notNull(), createdAtMs: integer('created_at_ms').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.subjectType, table.subjectId] }), check( 'ql3_local_identity_type_check', sql`${table.subjectType} in ('user','api_app','mcp_client','agent','system','worker')`, ), check( 'ql3_local_identity_id_check', sql`length(${table.subjectId}) between 1 and 255`, ), check( 'ql3_local_identity_status_check', sql`${table.status} in ('active','disabled')`, ), check( 'ql3_local_identity_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_identity_time_check', sql`${table.createdAtMs} >= 0 and ${table.updatedAtMs} >= ${table.createdAtMs}`, ), index('ql3_local_identity_status_idx').on( table.status, table.subjectType, table.subjectId, ), ], ); export const localApiCredentials = sqliteTable( 'QingLong3ApiCredentials', { credentialId: text('credential_id').notNull(), version: integer('version').notNull(), state: text('state').notNull(), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), secretDigest: text('secret_digest').notNull(), createdAtMs: integer('created_at_ms').notNull(), notBeforeAtMs: integer('not_before_at_ms').notNull(), expiresAtMs: integer('expires_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.credentialId, table.version] }), check( 'ql3_local_credentials_id_check', sql`length(${table.credentialId}) between 1 and 64 and ${table.credentialId} not glob '*[^A-Za-z0-9._:-]*'`, ), check( 'ql3_local_credentials_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_credentials_state_check', sql`${table.state} in ('active','revoked')`, ), check( 'ql3_local_credentials_subject_type_check', sql`${table.subjectType} in ('user','api_app','mcp_client','agent')`, ), check( 'ql3_local_credentials_subject_id_check', sql`length(${table.subjectId}) between 1 and 255`, ), check( 'ql3_local_credentials_digest_check', sql`length(${table.secretDigest}) = 64 and ${table.secretDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_credentials_lifetime_check', sql`${table.createdAtMs} >= 0 and ${table.notBeforeAtMs} >= ${table.createdAtMs} and ${table.expiresAtMs} > ${table.notBeforeAtMs}`, ), foreignKey({ columns: [table.subjectType, table.subjectId], foreignColumns: [ localIdentitySubjects.subjectType, localIdentitySubjects.subjectId, ], name: 'ql3_local_credentials_subject_fk', }).onDelete('restrict'), index('ql3_local_credentials_current_idx').on( table.credentialId, sql`${table.version} desc`, ), index('ql3_local_credentials_subject_idx').on( table.subjectType, table.subjectId, table.credentialId, sql`${table.version} desc`, ), ], ); export const localApiCredentialPepperBindings = sqliteTable( 'QingLong3ApiCredentialPepperBindings', { credentialId: text('credential_id').notNull(), credentialVersion: integer('credential_version').notNull(), pepperKeyId: text('pepper_key_id') .notNull() .references(() => localOwnerPepperKeys.pepperKeyId, { onDelete: 'restrict', }), }, (table) => [ primaryKey({ columns: [table.credentialId, table.credentialVersion], }), check( 'ql3_local_credential_pepper_key_id_check', sql`length(${table.pepperKeyId}) between 1 and 64 and ${table.pepperKeyId} not glob '*[^A-Za-z0-9._:-]*'`, ), foreignKey({ columns: [table.credentialId, table.credentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_credential_pepper_binding_credential_fk', }).onDelete('restrict'), index('ql3_local_credential_pepper_key_idx').on( table.pepperKeyId, table.credentialId, table.credentialVersion, ), uniqueIndex('ql3_local_credential_pepper_binding_triple_uidx').on( table.credentialId, table.credentialVersion, table.pepperKeyId, ), ], ); export const localOwnerPepperKeys = sqliteTable( 'QingLong3LocalOwnerPepperKeys', { pepperKeyId: text('pepper_key_id').primaryKey(), materialDigest: text('material_digest'), backupDigest: text('backup_digest'), state: text('state').notNull(), version: integer('version').notNull(), registerMutationId: text('register_mutation_id'), activateMutationId: text('activate_mutation_id'), retireMutationId: text('retire_mutation_id'), registeredAtMs: integer('registered_at_ms').notNull(), activatedAtMs: integer('activated_at_ms'), retiredAtMs: integer('retired_at_ms'), }, (table) => [ check( 'ql3_local_owner_pepper_key_id_check', sql`length(${table.pepperKeyId}) between 1 and 64 and ${table.pepperKeyId} not glob '*[^A-Za-z0-9._:-]*'`, ), check( 'ql3_local_owner_pepper_digest_check', sql`(${table.materialDigest} is null and ${table.backupDigest} is null) or (length(${table.materialDigest}) = 64 and ${table.materialDigest} not glob '*[^0-9a-f]*' and length(${table.backupDigest}) = 64 and ${table.backupDigest} not glob '*[^0-9a-f]*')`, ), check( 'ql3_local_owner_pepper_state_check', sql`${table.state} in ('recovery_required','staged','active','retired')`, ), check( 'ql3_local_owner_pepper_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_owner_pepper_mutation_check', sql`(${table.registerMutationId} is null or length(${table.registerMutationId}) = 36) and (${table.activateMutationId} is null or length(${table.activateMutationId}) = 36) and (${table.retireMutationId} is null or length(${table.retireMutationId}) = 36)`, ), check( 'ql3_local_owner_pepper_time_check', sql`${table.registeredAtMs} >= 0 and (${table.activatedAtMs} is null or ${table.activatedAtMs} >= ${table.registeredAtMs}) and (${table.retiredAtMs} is null or ${table.retiredAtMs} >= ${table.activatedAtMs})`, ), check( 'ql3_local_owner_pepper_shape_check', sql`(${table.state} = 'recovery_required' and ${table.materialDigest} is null and ${table.backupDigest} is null and ${table.registerMutationId} is null and ${table.activateMutationId} is null and ${table.retireMutationId} is null and ${table.activatedAtMs} is null and ${table.retiredAtMs} is null) or (${table.state} = 'staged' and ${table.materialDigest} is not null and ${table.backupDigest} is not null and ${table.registerMutationId} is not null and ${table.activateMutationId} is null and ${table.retireMutationId} is null and ${table.activatedAtMs} is null and ${table.retiredAtMs} is null) or (${table.state} = 'active' and ${table.materialDigest} is not null and ${table.backupDigest} is not null and ${table.registerMutationId} is not null and ${table.activateMutationId} is not null and ${table.retireMutationId} is null and ${table.activatedAtMs} is not null and ${table.retiredAtMs} is null) or (${table.state} = 'retired' and ${table.materialDigest} is not null and ${table.backupDigest} is not null and ${table.registerMutationId} is not null and ${table.activateMutationId} is not null and ${table.retireMutationId} is not null and ${table.activatedAtMs} is not null and ${table.retiredAtMs} is not null)`, ), uniqueIndex('ql3_local_owner_pepper_register_mutation_uidx') .on(table.registerMutationId) .where(sql`${table.registerMutationId} is not null`), uniqueIndex('ql3_local_owner_pepper_single_active_uidx') .on(table.state) .where(sql`${table.state} = 'active'`), index('ql3_local_owner_pepper_state_idx').on( table.state, table.pepperKeyId, ), ], ); export const localOwnerPepperActivations = sqliteTable( 'QingLong3LocalOwnerPepperActivations', { generation: integer('generation').primaryKey(), mutationId: text('mutation_id').notNull(), expectedGeneration: integer('expected_generation').notNull(), previousPepperKeyId: text('previous_pepper_key_id').references( () => localOwnerPepperKeys.pepperKeyId, { onDelete: 'restrict' }, ), activePepperKeyId: text('active_pepper_key_id') .notNull() .references(() => localOwnerPepperKeys.pepperKeyId, { onDelete: 'restrict', }), materialDigest: text('material_digest').notNull(), backupDigest: text('backup_digest').notNull(), activatedAtMs: integer('activated_at_ms').notNull(), }, (table) => [ check( 'ql3_local_owner_pepper_activation_generation_check', sql`${table.generation} between 1 and 2147483647 and ${table.expectedGeneration} = ${table.generation} - 1`, ), check( 'ql3_local_owner_pepper_activation_mutation_check', sql`length(${table.mutationId}) = 36`, ), check( 'ql3_local_owner_pepper_activation_key_check', sql`length(${table.activePepperKeyId}) between 1 and 64 and ${table.activePepperKeyId} not glob '*[^A-Za-z0-9._:-]*' and (${table.previousPepperKeyId} is null or (length(${table.previousPepperKeyId}) between 1 and 64 and ${table.previousPepperKeyId} not glob '*[^A-Za-z0-9._:-]*' and ${table.previousPepperKeyId} <> ${table.activePepperKeyId}))`, ), check( 'ql3_local_owner_pepper_activation_digest_check', sql`length(${table.materialDigest}) = 64 and ${table.materialDigest} not glob '*[^0-9a-f]*' and length(${table.backupDigest}) = 64 and ${table.backupDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_owner_pepper_activation_time_check', sql`${table.activatedAtMs} >= 0`, ), uniqueIndex('ql3_local_owner_pepper_activation_mutation_uidx').on( table.mutationId, ), index('ql3_local_owner_pepper_activation_key_idx').on( table.activePepperKeyId, sql`${table.generation} desc`, ), ], ); export const localIdentityProvisionings = sqliteTable( 'QingLong3LocalIdentityProvisionings', { slot: integer('slot').primaryKey(), mutationId: text('mutation_id').notNull(), requestId: text('request_id').notNull(), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), credentialId: text('credential_id').notNull(), credentialVersion: integer('credential_version').notNull(), issuerAuthenticationId: text('issuer_authentication_id').notNull(), issuerAuthenticatedAtMs: integer('issuer_authenticated_at_ms').notNull(), issuerExpiresAtMs: integer('issuer_expires_at_ms').notNull(), auditEventId: text('audit_event_id').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check('ql3_local_provisioning_singleton_check', sql`${table.slot} = 1`), check( 'ql3_local_provisioning_mutation_check', sql`length(${table.mutationId}) = 36`, ), check( 'ql3_local_provisioning_request_check', sql`length(${table.requestId}) between 1 and 128`, ), check( 'ql3_local_provisioning_subject_check', sql`${table.subjectType} = 'user' and length(${table.subjectId}) between 1 and 255`, ), check( 'ql3_local_provisioning_credential_check', sql`length(${table.credentialId}) between 1 and 64 and ${table.credentialVersion} = 1`, ), check( 'ql3_local_provisioning_issuer_check', sql`length(${table.issuerAuthenticationId}) between 1 and 128 and ${table.issuerAuthenticatedAtMs} <= ${table.createdAtMs} and ${table.issuerExpiresAtMs} > ${table.createdAtMs}`, ), check( 'ql3_local_provisioning_audit_check', sql`${table.auditEventId} = ${table.mutationId}`, ), check('ql3_local_provisioning_time_check', sql`${table.createdAtMs} >= 0`), foreignKey({ columns: [table.subjectType, table.subjectId], foreignColumns: [ localIdentitySubjects.subjectType, localIdentitySubjects.subjectId, ], name: 'ql3_local_provisioning_subject_fk', }).onDelete('restrict'), foreignKey({ columns: [table.credentialId, table.credentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_provisioning_credential_fk', }).onDelete('restrict'), foreignKey({ columns: [table.auditEventId], foreignColumns: [localSecurityAuditEvents.eventId], name: 'ql3_local_provisioning_audit_fk', }).onDelete('restrict'), uniqueIndex('ql3_local_provisioning_mutation_uidx').on(table.mutationId), uniqueIndex('ql3_local_provisioning_subject_uidx').on( table.subjectType, table.subjectId, ), uniqueIndex('ql3_local_provisioning_credential_uidx').on( table.credentialId, table.credentialVersion, ), ], ); export const localOwnerBootstrapChallenges = sqliteTable( 'QingLong3LocalOwnerBootstrapChallenges', { projectId: text('project_id').notNull(), version: integer('version').notNull(), issueMutationId: text('issue_mutation_id').notNull(), issueRequestId: text('issue_request_id').notNull(), challengeId: text('challenge_id').notNull(), tokenDigest: text('token_digest').notNull(), issuerAuthenticationId: text('issuer_authentication_id').notNull(), issuerAuthenticatedAtMs: integer('issuer_authenticated_at_ms').notNull(), issuerExpiresAtMs: integer('issuer_expires_at_ms').notNull(), issuedAtMs: integer('issued_at_ms').notNull(), expiresAtMs: integer('expires_at_ms').notNull(), issueAuditEventId: text('issue_audit_event_id').notNull(), consumedAtMs: integer('consumed_at_ms'), claimMutationId: text('claim_mutation_id'), claimRequestId: text('claim_request_id'), claimedSubjectType: text('claimed_subject_type'), claimedSubjectId: text('claimed_subject_id'), credentialId: text('credential_id'), credentialVersion: integer('credential_version'), claimAuthenticationId: text('claim_authentication_id'), claimAuthenticatedAtMs: integer('claim_authenticated_at_ms'), claimExpiresAtMs: integer('claim_expires_at_ms'), claimAssurance: text('claim_assurance'), claimAuditEventId: text('claim_audit_event_id'), }, (table) => [ primaryKey({ columns: [table.projectId, table.version] }), check( 'ql3_local_owner_challenge_version_check', sql`${table.version} between 1 and 2147483647`, ), check( 'ql3_local_owner_challenge_issue_identity_check', sql`length(${table.issueMutationId}) = 36 and length(${table.issueRequestId}) between 1 and 128 and ${table.issueAuditEventId} = ${table.issueMutationId}`, ), check( 'ql3_local_owner_challenge_id_check', sql`length(${table.challengeId}) = 22 and ${table.challengeId} not glob '*[^A-Za-z0-9_-]*'`, ), check( 'ql3_local_owner_challenge_digest_check', sql`length(${table.tokenDigest}) = 64 and ${table.tokenDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_owner_challenge_issuer_check', sql`length(${table.issuerAuthenticationId}) between 1 and 128 and ${table.issuerAuthenticatedAtMs} <= ${table.issuedAtMs} and ${table.issuerExpiresAtMs} > ${table.issuedAtMs}`, ), check( 'ql3_local_owner_challenge_lifetime_check', sql`${table.issuedAtMs} >= 0 and ${table.expiresAtMs} > ${table.issuedAtMs} and ${table.expiresAtMs} - ${table.issuedAtMs} between 60000 and 1800000`, ), check( 'ql3_local_owner_challenge_claim_shape_check', sql`(${table.consumedAtMs} is null and ${table.claimMutationId} is null and ${table.claimRequestId} is null and ${table.claimedSubjectType} is null and ${table.claimedSubjectId} is null and ${table.credentialId} is null and ${table.credentialVersion} is null and ${table.claimAuthenticationId} is null and ${table.claimAuthenticatedAtMs} is null and ${table.claimExpiresAtMs} is null and ${table.claimAssurance} is null and ${table.claimAuditEventId} is null) or (${table.consumedAtMs} >= ${table.issuedAtMs} and ${table.consumedAtMs} < ${table.expiresAtMs} and length(${table.claimMutationId}) = 36 and length(${table.claimRequestId}) between 1 and 128 and ${table.claimedSubjectType} = 'user' and length(${table.claimedSubjectId}) between 1 and 255 and length(${table.credentialId}) between 1 and 64 and ${table.credentialVersion} between 1 and 2147483647 and length(${table.claimAuthenticationId}) between 1 and 128 and ${table.claimAuthenticatedAtMs} <= ${table.consumedAtMs} and ${table.claimExpiresAtMs} > ${table.consumedAtMs} and ${table.claimAssurance} = 'single_factor' and ${table.claimAuditEventId} = ${table.claimMutationId})`, ), foreignKey({ columns: [table.projectId], foreignColumns: [localProjects.id], name: 'ql3_local_owner_challenge_project_fk', }).onDelete('restrict'), foreignKey({ columns: [table.issueAuditEventId], foreignColumns: [localSecurityAuditEvents.eventId], name: 'ql3_local_owner_challenge_issue_audit_fk', }).onDelete('restrict'), foreignKey({ columns: [table.claimedSubjectType, table.claimedSubjectId], foreignColumns: [ localIdentitySubjects.subjectType, localIdentitySubjects.subjectId, ], name: 'ql3_local_owner_challenge_subject_fk', }).onDelete('restrict'), foreignKey({ columns: [table.credentialId, table.credentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_owner_challenge_credential_fk', }).onDelete('restrict'), foreignKey({ columns: [table.claimAuditEventId], foreignColumns: [localSecurityAuditEvents.eventId], name: 'ql3_local_owner_challenge_claim_audit_fk', }).onDelete('restrict'), uniqueIndex('ql3_local_owner_challenge_issue_mutation_uidx').on( table.issueMutationId, ), uniqueIndex('ql3_local_owner_challenge_id_uidx').on(table.challengeId), uniqueIndex('ql3_local_owner_challenge_claim_mutation_uidx') .on(table.claimMutationId) .where(sql`${table.claimMutationId} is not null`), index('ql3_local_owner_challenge_current_idx').on( table.projectId, sql`${table.version} desc`, ), index('ql3_local_owner_challenge_expiry_idx') .on(table.projectId, table.expiresAtMs, sql`${table.version} desc`) .where(sql`${table.consumedAtMs} is null`), ], ); export const localOwnerDeliveryAcknowledgements = sqliteTable( 'QingLong3LocalOwnerDeliveryAcknowledgements', { mutationId: text('mutation_id').primaryKey(), kind: text('kind').notNull(), requestId: text('request_id').notNull(), projectId: text('project_id'), subjectId: text('subject_id'), credentialId: text('credential_id'), challengeId: text('challenge_id'), factDigest: text('fact_digest').notNull(), deliveryDigest: text('delivery_digest').notNull(), ttlMs: integer('ttl_ms').notNull(), acknowledgedAtMs: integer('acknowledged_at_ms').notNull(), provisioningMutationId: text('provisioning_mutation_id'), challengeMutationId: text('challenge_mutation_id'), }, (table) => [ check( 'ql3_local_owner_delivery_ack_mutation_check', sql`length(${table.mutationId}) = 36`, ), check( 'ql3_local_owner_delivery_ack_request_check', sql`length(${table.requestId}) between 1 and 128`, ), check( 'ql3_local_owner_delivery_ack_digest_check', sql`length(${table.factDigest}) = 64 and ${table.factDigest} not glob '*[^0-9a-f]*' and length(${table.deliveryDigest}) = 64 and ${table.deliveryDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_owner_delivery_ack_time_check', sql`${table.ttlMs} > 0 and ${table.acknowledgedAtMs} >= 0`, ), check( 'ql3_local_owner_delivery_ack_shape_check', sql`(${table.kind} = 'credential' and ${table.projectId} is null and length(${table.subjectId}) = 26 and ${table.subjectId} glob 'usr_*' and ${table.subjectId} not glob '*[^A-Za-z0-9_-]*' and length(${table.credentialId}) = 26 and ${table.credentialId} glob 'own_*' and ${table.credentialId} not glob '*[^A-Za-z0-9_-]*' and ${table.challengeId} is null and ${table.provisioningMutationId} = ${table.mutationId} and ${table.challengeMutationId} is null and ${table.ttlMs} between 600000 and 604800000) or (${table.kind} = 'challenge' and length(${table.projectId}) between 1 and 128 and ${table.subjectId} is null and ${table.credentialId} is null and length(${table.challengeId}) = 22 and ${table.challengeId} not glob '*[^A-Za-z0-9_-]*' and ${table.provisioningMutationId} is null and ${table.challengeMutationId} = ${table.mutationId} and ${table.ttlMs} between 60000 and 1800000)`, ), foreignKey({ columns: [table.provisioningMutationId], foreignColumns: [localIdentityProvisionings.mutationId], name: 'ql3_local_owner_delivery_ack_provisioning_fk', }).onDelete('restrict'), foreignKey({ columns: [table.challengeMutationId], foreignColumns: [localOwnerBootstrapChallenges.issueMutationId], name: 'ql3_local_owner_delivery_ack_challenge_fk', }).onDelete('restrict'), ], ); export const localOwnerDeliveryAcknowledgementGc = sqliteTable( 'QingLong3LocalOwnerDeliveryAcknowledgementGc', { gcMutationId: text('gc_mutation_id').primaryKey(), gcRequestId: text('gc_request_id').notNull(), acknowledgementMutationId: text('acknowledgement_mutation_id').notNull(), acknowledgementKind: text('acknowledgement_kind').notNull(), deliveryDigest: text('delivery_digest').notNull(), acknowledgedAtMs: integer('acknowledged_at_ms').notNull(), acknowledgementSemanticDigest: text( 'acknowledgement_semantic_digest', ).notNull(), bridgeClearEvidenceDigest: text('bridge_clear_evidence_digest').notNull(), retentionPolicyVersion: integer('retention_policy_version').notNull(), replayRetentionMs: integer('replay_retention_ms').notNull(), auditRetentionMs: integer('audit_retention_ms').notNull(), retentionPolicyDigest: text('retention_policy_digest').notNull(), retentionEligibleAtMs: integer('retention_eligible_at_ms').notNull(), compactedAtMs: integer('compacted_at_ms').notNull(), auditEventId: text('audit_event_id') .notNull() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), provisioningMutationId: text('provisioning_mutation_id').references( () => localIdentityProvisionings.mutationId, { onDelete: 'restrict' }, ), challengeMutationId: text('challenge_mutation_id').references( () => localOwnerBootstrapChallenges.issueMutationId, { onDelete: 'restrict' }, ), }, (table) => [ check( 'ql3_local_owner_delivery_ack_gc_mutation_check', sql`length(${table.gcMutationId}) = 36 and ${table.auditEventId} = ${table.gcMutationId} and length(${table.acknowledgementMutationId}) = 36 and ${table.acknowledgementMutationId} <> ${table.gcMutationId}`, ), check( 'ql3_local_owner_delivery_ack_gc_request_check', sql`length(${table.gcRequestId}) between 1 and 128`, ), check( 'ql3_local_owner_delivery_ack_gc_digest_check', sql`length(${table.deliveryDigest}) = 64 and ${table.deliveryDigest} not glob '*[^0-9a-f]*' and length(${table.acknowledgementSemanticDigest}) = 64 and ${table.acknowledgementSemanticDigest} not glob '*[^0-9a-f]*' and length(${table.bridgeClearEvidenceDigest}) = 64 and ${table.bridgeClearEvidenceDigest} not glob '*[^0-9a-f]*' and length(${table.retentionPolicyDigest}) = 64 and ${table.retentionPolicyDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_local_owner_delivery_ack_gc_retention_check', sql`${table.retentionPolicyVersion} = 1 and ${table.replayRetentionMs} between 2592000000 and 315360000000 and ${table.auditRetentionMs} between 2592000000 and 315360000000`, ), check( 'ql3_local_owner_delivery_ack_gc_time_check', sql`${table.acknowledgedAtMs} >= 0 and ${table.retentionEligibleAtMs} <= ${table.compactedAtMs} and ${table.compactedAtMs} >= ${table.acknowledgedAtMs}`, ), check( 'ql3_local_owner_delivery_ack_gc_shape_check', sql`(${table.acknowledgementKind} = 'credential' and ${table.provisioningMutationId} = ${table.acknowledgementMutationId} and ${table.challengeMutationId} is null) or (${table.acknowledgementKind} = 'challenge' and ${table.provisioningMutationId} is null and ${table.challengeMutationId} = ${table.acknowledgementMutationId})`, ), uniqueIndex('ql3_local_owner_delivery_ack_gc_ack_uidx').on( table.acknowledgementMutationId, ), index('ql3_local_owner_delivery_ack_gc_compacted_idx').on( table.acknowledgementKind, table.compactedAtMs, table.acknowledgementMutationId, ), ], ); export const localOwnerCredentialRecoveries = sqliteTable( 'QingLong3LocalOwnerCredentialRecoveries', { issueMutationId: text('issue_mutation_id').primaryKey(), issueRequestId: text('issue_request_id').notNull(), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), previousCredentialId: text('previous_credential_id').notNull(), previousCredentialVersion: integer('previous_credential_version').notNull(), replacementCredentialId: text('replacement_credential_id').notNull(), replacementCredentialVersion: integer( 'replacement_credential_version', ).notNull(), state: text('state').notNull(), issuedAtMs: integer('issued_at_ms').notNull(), issueAuditEventId: text('issue_audit_event_id').notNull(), deliveryDigest: text('delivery_digest'), acknowledgedAtMs: integer('acknowledged_at_ms'), completeMutationId: text('complete_mutation_id'), completeRequestId: text('complete_request_id'), revokedCredentialVersion: integer('revoked_credential_version'), completedAtMs: integer('completed_at_ms'), completeAuditEventId: text('complete_audit_event_id'), }, (table) => [ check( 'ql3_local_owner_recovery_mutation_check', sql`length(${table.issueMutationId}) = 36 and ${table.issueAuditEventId} = ${table.issueMutationId} and (${table.completeMutationId} is null or (length(${table.completeMutationId}) = 36 and ${table.completeAuditEventId} = ${table.completeMutationId} and ${table.completeMutationId} <> ${table.issueMutationId}))`, ), check( 'ql3_local_owner_recovery_request_check', sql`length(${table.issueRequestId}) between 1 and 128 and (${table.completeRequestId} is null or length(${table.completeRequestId}) between 1 and 128)`, ), check( 'ql3_local_owner_recovery_identity_check', sql`${table.subjectType} = 'user' and length(${table.subjectId}) = 26 and ${table.subjectId} glob 'usr_*' and ${table.subjectId} not glob '*[^A-Za-z0-9_-]*'`, ), check( 'ql3_local_owner_recovery_credential_check', sql`length(${table.previousCredentialId}) between 1 and 64 and ${table.previousCredentialId} not glob '*[^A-Za-z0-9._:-]*' and ${table.previousCredentialVersion} between 1 and 2147483646 and length(${table.replacementCredentialId}) between 1 and 64 and ${table.replacementCredentialId} not glob '*[^A-Za-z0-9._:-]*' and ${table.replacementCredentialId} <> ${table.previousCredentialId} and ${table.replacementCredentialVersion} = 1 and (${table.revokedCredentialVersion} is null or ${table.revokedCredentialVersion} = ${table.previousCredentialVersion} + 1)`, ), check( 'ql3_local_owner_recovery_digest_check', sql`${table.deliveryDigest} is null or (length(${table.deliveryDigest}) = 64 and ${table.deliveryDigest} not glob '*[^0-9a-f]*')`, ), check( 'ql3_local_owner_recovery_time_check', sql`${table.issuedAtMs} >= 0 and (${table.acknowledgedAtMs} is null or ${table.acknowledgedAtMs} >= ${table.issuedAtMs}) and (${table.completedAtMs} is null or ${table.completedAtMs} >= ${table.acknowledgedAtMs})`, ), check( 'ql3_local_owner_recovery_shape_check', sql`(${table.state} = 'issued' and ${table.deliveryDigest} is null and ${table.acknowledgedAtMs} is null and ${table.completeMutationId} is null and ${table.completeRequestId} is null and ${table.revokedCredentialVersion} is null and ${table.completedAtMs} is null and ${table.completeAuditEventId} is null) or (${table.state} = 'acknowledged' and ${table.deliveryDigest} is not null and ${table.acknowledgedAtMs} is not null and ${table.completeMutationId} is null and ${table.completeRequestId} is null and ${table.revokedCredentialVersion} is null and ${table.completedAtMs} is null and ${table.completeAuditEventId} is null) or (${table.state} = 'completed' and ${table.deliveryDigest} is not null and ${table.acknowledgedAtMs} is not null and ${table.completeMutationId} is not null and ${table.completeRequestId} is not null and ${table.revokedCredentialVersion} is not null and ${table.completedAtMs} is not null and ${table.completeAuditEventId} is not null)`, ), foreignKey({ columns: [table.subjectType, table.subjectId], foreignColumns: [ localIdentitySubjects.subjectType, localIdentitySubjects.subjectId, ], name: 'ql3_local_owner_recovery_subject_fk', }).onDelete('restrict'), foreignKey({ columns: [table.previousCredentialId, table.previousCredentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_owner_recovery_previous_fk', }).onDelete('restrict'), foreignKey({ columns: [ table.replacementCredentialId, table.replacementCredentialVersion, ], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_owner_recovery_replacement_fk', }).onDelete('restrict'), foreignKey({ columns: [table.previousCredentialId, table.revokedCredentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_local_owner_recovery_revoked_fk', }).onDelete('restrict'), foreignKey({ columns: [table.issueAuditEventId], foreignColumns: [localSecurityAuditEvents.eventId], name: 'ql3_local_owner_recovery_issue_audit_fk', }).onDelete('restrict'), foreignKey({ columns: [table.completeAuditEventId], foreignColumns: [localSecurityAuditEvents.eventId], name: 'ql3_local_owner_recovery_complete_audit_fk', }).onDelete('restrict'), uniqueIndex('ql3_local_owner_recovery_open_subject_uidx') .on(table.subjectId) .where(sql`${table.state} <> 'completed'`), uniqueIndex('ql3_local_owner_recovery_replacement_uidx').on( table.replacementCredentialId, table.replacementCredentialVersion, ), uniqueIndex('ql3_local_owner_recovery_complete_mutation_uidx') .on(table.completeMutationId) .where(sql`${table.completeMutationId} is not null`), index('ql3_local_owner_recovery_previous_idx').on( table.previousCredentialId, table.previousCredentialVersion, table.state, ), ], ); export const localOwnerPepperMaterialGc = sqliteTable( 'QingLong3LocalOwnerPepperMaterialGc', { prepareMutationId: text('prepare_mutation_id').primaryKey(), prepareRequestId: text('prepare_request_id').notNull(), pepperKeyId: text('pepper_key_id') .notNull() .references(() => localOwnerPepperKeys.pepperKeyId, { onDelete: 'restrict', }), materialDigest: text('material_digest').notNull(), backupMaterialDigest: text('backup_material_digest').notNull(), activePepperKeyId: text('active_pepper_key_id') .notNull() .references(() => localOwnerPepperKeys.pepperKeyId, { onDelete: 'restrict', }), activeGeneration: integer('active_generation') .notNull() .references(() => localOwnerPepperActivations.generation, { onDelete: 'restrict', }), activeMaterialDigest: text('active_material_digest').notNull(), retentionPolicyVersion: integer('retention_policy_version').notNull(), acknowledgementRetentionMs: integer( 'acknowledgement_retention_ms', ).notNull(), auditRetentionMs: integer('audit_retention_ms').notNull(), backupRetentionMs: integer('backup_retention_ms').notNull(), retentionPolicyDigest: text('retention_policy_digest').notNull(), referencesInspectedAtMs: integer('references_inspected_at_ms').notNull(), retentionEligibleAtMs: integer('retention_eligible_at_ms').notNull(), preparedAtMs: integer('prepared_at_ms').notNull(), prepareAuditEventId: text('prepare_audit_event_id') .notNull() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), state: text('state').notNull(), completeMutationId: text('complete_mutation_id'), completeRequestId: text('complete_request_id'), destructionProofDigest: text('destruction_proof_digest'), completedAtMs: integer('completed_at_ms'), completeAuditEventId: text('complete_audit_event_id').references( () => localSecurityAuditEvents.eventId, { onDelete: 'restrict' }, ), }, (table) => [ check( 'ql3_local_owner_pepper_gc_mutation_check', sql`length(${table.prepareMutationId}) = 36 and ${table.prepareAuditEventId} = ${table.prepareMutationId} and (${table.completeMutationId} is null or (length(${table.completeMutationId}) = 36 and ${table.completeMutationId} <> ${table.prepareMutationId} and ${table.completeAuditEventId} = ${table.completeMutationId}))`, ), check( 'ql3_local_owner_pepper_gc_request_check', sql`length(${table.prepareRequestId}) between 1 and 128 and (${table.completeRequestId} is null or length(${table.completeRequestId}) between 1 and 128)`, ), check( 'ql3_local_owner_pepper_gc_key_check', sql`length(${table.pepperKeyId}) between 1 and 64 and ${table.pepperKeyId} not glob '*[^A-Za-z0-9._:-]*' and length(${table.activePepperKeyId}) between 1 and 64 and ${table.activePepperKeyId} not glob '*[^A-Za-z0-9._:-]*' and ${table.pepperKeyId} <> ${table.activePepperKeyId} and ${table.activeGeneration} between 1 and 2147483647`, ), check( 'ql3_local_owner_pepper_gc_digest_check', sql`length(${table.materialDigest}) = 64 and ${table.materialDigest} not glob '*[^0-9a-f]*' and length(${table.backupMaterialDigest}) = 64 and ${table.backupMaterialDigest} not glob '*[^0-9a-f]*' and length(${table.activeMaterialDigest}) = 64 and ${table.activeMaterialDigest} not glob '*[^0-9a-f]*' and length(${table.retentionPolicyDigest}) = 64 and ${table.retentionPolicyDigest} not glob '*[^0-9a-f]*' and (${table.destructionProofDigest} is null or (length(${table.destructionProofDigest}) = 64 and ${table.destructionProofDigest} not glob '*[^0-9a-f]*'))`, ), check( 'ql3_local_owner_pepper_gc_retention_check', sql`${table.retentionPolicyVersion} = 1 and ${table.acknowledgementRetentionMs} between 604800000 and 315360000000 and ${table.auditRetentionMs} between 2592000000 and 315360000000 and ${table.backupRetentionMs} between 2592000000 and 315360000000`, ), check( 'ql3_local_owner_pepper_gc_time_check', sql`${table.referencesInspectedAtMs} = ${table.preparedAtMs} and ${table.retentionEligibleAtMs} <= ${table.preparedAtMs} and ${table.preparedAtMs} >= 0 and (${table.completedAtMs} is null or ${table.completedAtMs} >= ${table.preparedAtMs})`, ), check( 'ql3_local_owner_pepper_gc_shape_check', sql`(${table.state} = 'prepared' and ${table.completeMutationId} is null and ${table.completeRequestId} is null and ${table.destructionProofDigest} is null and ${table.completedAtMs} is null and ${table.completeAuditEventId} is null) or (${table.state} = 'completed' and ${table.completeMutationId} is not null and ${table.completeRequestId} is not null and ${table.destructionProofDigest} is not null and ${table.completedAtMs} is not null and ${table.completeAuditEventId} is not null)`, ), uniqueIndex('ql3_local_owner_pepper_gc_key_uidx').on(table.pepperKeyId), uniqueIndex('ql3_local_owner_pepper_gc_open_uidx') .on(table.state) .where(sql`${table.state} = 'prepared'`), uniqueIndex('ql3_local_owner_pepper_gc_complete_mutation_uidx') .on(table.completeMutationId) .where(sql`${table.completeMutationId} is not null`), index('ql3_local_owner_pepper_gc_state_idx').on( table.state, table.retentionEligibleAtMs, table.pepperKeyId, ), ], ); export const localIdentityAdministrationMutations = sqliteTable( 'QingLong3IdentityAdministrationMutations', { mutationId: text('mutation_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), operation: text('operation').notNull(), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), subjectVersion: integer('subject_version').notNull(), expectedPreviousVersion: integer('expected_previous_version').notNull(), status: text('status').notNull(), changedByType: text('changed_by_type').notNull(), changedById: text('changed_by_id').notNull(), auditEventId: text('audit_event_id') .notNull() .unique() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), identityCreatedAtMs: integer('identity_created_at_ms').notNull(), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_identity_admin_mutation_id_check', sql`length(${table.mutationId}) = 36`, ), check( 'ql3_identity_admin_operation_check', sql`${table.operation} in ('register','enable','disable')`, ), check( 'ql3_identity_admin_subject_check', sql`${table.subjectType} in ('user','api_app','mcp_client','agent') and length(${table.subjectId}) between 1 and 255`, ), check( 'ql3_identity_admin_transition_check', sql`${table.subjectVersion} = ${table.expectedPreviousVersion} + 1 and ${table.subjectVersion} between 1 and 2147483647 and ${table.expectedPreviousVersion} between 0 and 2147483646 and ((${table.operation} = 'register' and ${table.expectedPreviousVersion} = 0 and ${table.status} = 'active') or (${table.operation} = 'enable' and ${table.expectedPreviousVersion} > 0 and ${table.status} = 'active') or (${table.operation} = 'disable' and ${table.expectedPreviousVersion} > 0 and ${table.status} = 'disabled'))`, ), check( 'ql3_identity_admin_actor_check', sql`${table.changedByType} = 'user' and length(${table.changedById}) between 1 and 255`, ), check( 'ql3_identity_admin_audit_check', sql`${table.auditEventId} = ${table.mutationId}`, ), check( 'ql3_identity_admin_time_check', sql`${table.identityCreatedAtMs} >= 0 and ${table.createdAtMs} >= ${table.identityCreatedAtMs}`, ), foreignKey({ columns: [table.subjectType, table.subjectId], foreignColumns: [ localIdentitySubjects.subjectType, localIdentitySubjects.subjectId, ], name: 'ql3_identity_admin_subject_fk', }).onDelete('restrict'), index('ql3_identity_admin_subject_idx').on( table.subjectType, table.subjectId, sql`${table.subjectVersion} desc`, ), ], ); export const localApiCredentialAdministrationMutations = sqliteTable( 'QingLong3ApiCredentialAdministrationMutations', { mutationId: text('mutation_id').primaryKey(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), operation: text('operation').notNull(), credentialId: text('credential_id').notNull(), credentialVersion: integer('credential_version').notNull(), expectedPreviousVersion: integer('expected_previous_version').notNull(), subjectType: text('subject_type').notNull(), subjectId: text('subject_id').notNull(), subjectStatus: text('subject_status').notNull(), state: text('state').notNull(), pepperKeyId: text('pepper_key_id').notNull(), secretDigest: text('secret_digest').notNull(), notBeforeAtMs: integer('not_before_at_ms').notNull(), expiresAtMs: integer('expires_at_ms').notNull(), deliveryDigest: text('delivery_digest'), changedByType: text('changed_by_type').notNull(), changedById: text('changed_by_id').notNull(), auditEventId: text('audit_event_id') .notNull() .unique() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), createdAtMs: integer('created_at_ms').notNull(), }, (table) => [ check( 'ql3_credential_admin_mutation_id_check', sql`length(${table.mutationId}) = 36`, ), check( 'ql3_credential_admin_operation_check', sql`${table.operation} in ('issue','rotate','revoke')`, ), check( 'ql3_credential_admin_identity_check', sql`length(${table.credentialId}) between 1 and 64 and ${table.credentialId} not glob '*[^A-Za-z0-9._:-]*' and ${table.subjectType} in ('user','api_app','mcp_client','agent') and length(${table.subjectId}) between 1 and 255 and ${table.subjectStatus} in ('active','disabled')`, ), check( 'ql3_credential_admin_transition_check', sql`${table.credentialVersion} = ${table.expectedPreviousVersion} + 1 and ${table.credentialVersion} between 1 and 2147483647 and ${table.expectedPreviousVersion} between 0 and 2147483646 and ((${table.operation} = 'issue' and ${table.expectedPreviousVersion} = 0 and ${table.state} = 'active') or (${table.operation} = 'rotate' and ${table.expectedPreviousVersion} > 0 and ${table.state} = 'active') or (${table.operation} = 'revoke' and ${table.expectedPreviousVersion} > 0 and ${table.state} = 'revoked'))`, ), check( 'ql3_credential_admin_digest_check', sql`length(${table.pepperKeyId}) between 1 and 64 and ${table.pepperKeyId} not glob '*[^A-Za-z0-9._:-]*' and length(${table.secretDigest}) = 64 and ${table.secretDigest} not glob '*[^0-9a-f]*' and ((${table.operation} in ('issue','rotate') and length(${table.deliveryDigest}) = 64 and ${table.deliveryDigest} not glob '*[^0-9a-f]*') or (${table.operation} = 'revoke' and ${table.deliveryDigest} is null))`, ), check( 'ql3_credential_admin_lifetime_check', sql`${table.createdAtMs} >= 0 and ${table.notBeforeAtMs} >= ${table.createdAtMs} and ${table.expiresAtMs} > ${table.notBeforeAtMs}`, ), check( 'ql3_credential_admin_actor_check', sql`${table.changedByType} = 'user' and length(${table.changedById}) between 1 and 255`, ), check( 'ql3_credential_admin_audit_check', sql`${table.auditEventId} = ${table.mutationId}`, ), foreignKey({ columns: [table.credentialId, table.credentialVersion], foreignColumns: [ localApiCredentials.credentialId, localApiCredentials.version, ], name: 'ql3_credential_admin_credential_fk', }).onDelete('restrict'), foreignKey({ columns: [table.credentialId, table.credentialVersion, table.pepperKeyId], foreignColumns: [ localApiCredentialPepperBindings.credentialId, localApiCredentialPepperBindings.credentialVersion, localApiCredentialPepperBindings.pepperKeyId, ], name: 'ql3_credential_admin_pepper_binding_fk', }).onDelete('restrict'), index('ql3_credential_admin_credential_idx').on( table.credentialId, sql`${table.credentialVersion} desc`, ), index('ql3_credential_admin_subject_idx').on( table.subjectType, table.subjectId, sql`${table.createdAtMs} desc`, ), ], ); export const localApiCredentialDeliveryAcknowledgements = sqliteTable( 'QingLong3ApiCredentialDeliveryAcknowledgements', { credentialMutationId: text('credential_mutation_id') .primaryKey() .references(() => localApiCredentialAdministrationMutations.mutationId, { onDelete: 'restrict', }), acknowledgementMutationId: text('acknowledgement_mutation_id') .notNull() .unique(), projectId: text('project_id') .notNull() .references(() => localProjects.id, { onDelete: 'restrict' }), deliveryDigest: text('delivery_digest').notNull(), acknowledgedByType: text('acknowledged_by_type').notNull(), acknowledgedById: text('acknowledged_by_id').notNull(), auditEventId: text('audit_event_id') .notNull() .unique() .references(() => localSecurityAuditEvents.eventId, { onDelete: 'restrict', }), acknowledgedAtMs: integer('acknowledged_at_ms').notNull(), }, (table) => [ check( 'ql3_credential_delivery_ack_identity_check', sql`length(${table.credentialMutationId}) = 36 and length(${table.acknowledgementMutationId}) = 36 and ${table.credentialMutationId} <> ${table.acknowledgementMutationId}`, ), check( 'ql3_credential_delivery_ack_digest_check', sql`length(${table.deliveryDigest}) = 64 and ${table.deliveryDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_credential_delivery_ack_actor_check', sql`${table.acknowledgedByType} = 'user' and length(${table.acknowledgedById}) between 1 and 255`, ), check( 'ql3_credential_delivery_ack_audit_check', sql`${table.auditEventId} = ${table.acknowledgementMutationId}`, ), check( 'ql3_credential_delivery_ack_time_check', sql`${table.acknowledgedAtMs} >= 0`, ), index('ql3_credential_delivery_ack_project_idx').on( table.projectId, sql`${table.acknowledgedAtMs} desc`, ), ], ); export const pluginPackageLifecycleEvents = sqliteTable( 'QingLong3PluginPackageLifecycleEvents', { eventDigest: text('event_digest').primaryKey(), mutationId: text('mutation_id').notNull(), dispatchId: text('dispatch_id').notNull(), approvedActionType: text('approved_action_type').notNull(), action: text('action').notNull(), projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), lockDigest: text('lock_digest').notNull(), installVersion: integer('install_version').notNull(), installRecordDigest: text('install_record_digest').notNull(), expectedVersion: integer('expected_version').notNull(), expectedDisposition: text('expected_disposition').notNull(), expectedEventDigest: text('expected_event_digest').references( (): AnySQLiteColumn => pluginPackageLifecycleEvents.eventDigest, { onDelete: 'restrict' }, ), generationDigest: text('generation_digest').notNull(), materializedRevisionDigest: text('materialized_revision_digest').notNull(), currentToolSnapshotDigest: text('current_tool_snapshot_digest').notNull(), referenceGraphDigest: text('reference_graph_digest').notNull(), impactDigest: text('impact_digest').notNull(), actionDigest: text('action_digest').notNull(), requestedByType: text('requested_by_type').notNull(), requestedById: text('requested_by_id').notNull(), approvedByType: text('approved_by_type').notNull(), approvedById: text('approved_by_id').notNull(), authorizationMode: text('authorization_mode').notNull(), occurredAtMs: integer('occurred_at_ms').notNull(), eventJson: text('event_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_lifecycle_mutation_uidx').on( table.mutationId, ), uniqueIndex('ql3_plugin_package_lifecycle_dispatch_uidx').on( table.dispatchId, ), uniqueIndex('ql3_plugin_package_lifecycle_target_version_uidx').on( table.projectId, table.packageName, table.installationId, table.lockDigest, table.expectedVersion, ), foreignKey({ columns: [ table.projectId, table.packageName, table.installationId, table.lockDigest, table.installRecordDigest, ], foreignColumns: [ pluginPackageInstalls.projectId, pluginPackageInstalls.packageName, pluginPackageInstalls.installationId, pluginPackageInstalls.lockDigest, pluginPackageInstalls.recordDigest, ], name: 'ql3_plugin_package_lifecycle_install_fk', }) .onDelete('restrict') .onUpdate('restrict'), foreignKey({ columns: [ table.dispatchId, table.projectId, table.approvedActionType, table.actionDigest, table.impactDigest, ], foreignColumns: [ approvedActionDispatches.dispatchId, approvedActionDispatches.projectId, approvedActionDispatches.actionType, approvedActionDispatches.actionDigest, approvedActionDispatches.previewDigest, ], name: 'ql3_plugin_package_lifecycle_dispatch_fk', }) .onDelete('restrict') .onUpdate('restrict'), check( 'ql3_plugin_package_lifecycle_identity_check', sql`length(${table.mutationId}) between 1 and 128 and length(${table.dispatchId}) between 1 and 128 and length(${table.packageName}) between 1 and 63 and length(${table.installationId}) between 1 and 128 and ${table.installVersion} between 1 and 2147483647 and ${table.action} in ('disable','enable','uninstall') and ${table.approvedActionType} = 'plugin_package.lifecycle.' || ${table.action}`, ), check( 'ql3_plugin_package_lifecycle_expectation_check', sql`(${table.action} = 'disable' and ${table.expectedDisposition} = 'active') or (${table.action} in ('enable','uninstall') and ${table.expectedDisposition} = 'disabled')`, ), check( 'ql3_plugin_package_lifecycle_origin_check', sql`(${table.expectedVersion} = 0 and ${table.expectedDisposition} = 'active' and ${table.expectedEventDigest} is null) or (${table.expectedVersion} between 1 and 2147483646 and ${table.expectedEventDigest} is not null)`, ), check( 'ql3_plugin_package_lifecycle_subject_check', sql`${table.requestedByType} = 'user' and ${table.approvedByType} = 'user' and length(${table.requestedById}) between 1 and 255 and length(${table.approvedById}) between 1 and 255 and ${table.authorizationMode} in ('human_confirmation','separation_of_duty') and ((${table.authorizationMode} = 'human_confirmation' and ${table.requestedById} = ${table.approvedById}) or (${table.authorizationMode} = 'separation_of_duty' and ${table.requestedById} <> ${table.approvedById}))`, ), check( 'ql3_plugin_package_lifecycle_digest_check', sql`length(${table.eventDigest}) = 64 and ${table.eventDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.installRecordDigest}) = 64 and ${table.installRecordDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.materializedRevisionDigest}) = 64 and ${table.materializedRevisionDigest} not glob '*[^0-9a-f]*' and length(${table.currentToolSnapshotDigest}) = 64 and ${table.currentToolSnapshotDigest} not glob '*[^0-9a-f]*' and length(${table.referenceGraphDigest}) = 64 and ${table.referenceGraphDigest} not glob '*[^0-9a-f]*' and length(${table.impactDigest}) = 64 and ${table.impactDigest} not glob '*[^0-9a-f]*' and length(${table.actionDigest}) = 64 and ${table.actionDigest} not glob '*[^0-9a-f]*' and (${table.expectedEventDigest} is null or (length(${table.expectedEventDigest}) = 64 and ${table.expectedEventDigest} not glob '*[^0-9a-f]*'))`, ), check( 'ql3_plugin_package_lifecycle_json_check', sql`length(${table.eventJson}) between 2 and 524288 and json_valid(${table.eventJson}) and json_type(${table.eventJson}) = 'object' and json_extract(${table.eventJson}, '$.schema') = 'qinglong/plugin-package-lifecycle-event@v1' and json_extract(${table.eventJson}, '$.mutationId') = ${table.mutationId} and json_extract(${table.eventJson}, '$.dispatchId') = ${table.dispatchId} and json_extract(${table.eventJson}, '$.impact.schema') = 'qinglong/plugin-package-lifecycle-impact@v1' and json_extract(${table.eventJson}, '$.impact.action') = ${table.action} and json_extract(${table.eventJson}, '$.impact.target.projectId') = ${table.projectId} and json_extract(${table.eventJson}, '$.impact.target.packageName') = ${table.packageName} and json_extract(${table.eventJson}, '$.impact.target.installationId') = ${table.installationId} and json_extract(${table.eventJson}, '$.impact.target.lockDigest') = ${table.lockDigest} and json_extract(${table.eventJson}, '$.impact.target.installVersion') = ${table.installVersion} and json_extract(${table.eventJson}, '$.impact.target.installRecordDigest') = ${table.installRecordDigest} and json_extract(${table.eventJson}, '$.impact.expected.version') = ${table.expectedVersion} and json_extract(${table.eventJson}, '$.impact.expected.disposition') = ${table.expectedDisposition} and ((${table.expectedEventDigest} is null and json_type(${table.eventJson}, '$.impact.expected.eventDigest') = 'null') or json_extract(${table.eventJson}, '$.impact.expected.eventDigest') = ${table.expectedEventDigest}) and json_extract(${table.eventJson}, '$.impact.generationDigest') = ${table.generationDigest} and json_extract(${table.eventJson}, '$.impact.materializedRevisionDigest') = ${table.materializedRevisionDigest} and json_extract(${table.eventJson}, '$.impact.currentToolSnapshotDigest') = ${table.currentToolSnapshotDigest} and json_extract(${table.eventJson}, '$.impact.referenceGraphDigest') = ${table.referenceGraphDigest} and json_extract(${table.eventJson}, '$.impact.impactDigest') = ${table.impactDigest} and json_extract(${table.eventJson}, '$.actionDigest') = ${table.actionDigest} and json_extract(${table.eventJson}, '$.requestedBy.type') = ${table.requestedByType} and json_extract(${table.eventJson}, '$.requestedBy.id') = ${table.requestedById} and json_extract(${table.eventJson}, '$.approvedBy.type') = ${table.approvedByType} and json_extract(${table.eventJson}, '$.approvedBy.id') = ${table.approvedById} and json_extract(${table.eventJson}, '$.authorizationMode') = ${table.authorizationMode} and json_extract(${table.eventJson}, '$.occurredAtMs') = ${table.occurredAtMs} and json_extract(${table.eventJson}, '$.eventDigest') = ${table.eventDigest}`, ), check( 'ql3_plugin_package_lifecycle_time_check', sql`${table.occurredAtMs} >= 0`, ), index('ql3_plugin_package_lifecycle_project_idx').on( table.projectId, table.packageName, table.occurredAtMs, table.eventDigest, ), ], ); export const pluginPackageLifecycleHeads = sqliteTable( 'QingLong3PluginPackageLifecycleHeads', { projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), lockDigest: text('lock_digest').notNull(), installRecordDigest: text('install_record_digest').notNull(), version: integer('version').notNull(), disposition: text('disposition').notNull(), eventDigest: text('event_digest') .notNull() .references(() => pluginPackageLifecycleEvents.eventDigest, { onDelete: 'restrict', }), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.packageName] }), uniqueIndex('ql3_plugin_package_lifecycle_head_event_uidx').on( table.eventDigest, ), foreignKey({ columns: [ table.projectId, table.packageName, table.installationId, table.lockDigest, table.installRecordDigest, ], foreignColumns: [ pluginPackageInstalls.projectId, pluginPackageInstalls.packageName, pluginPackageInstalls.installationId, pluginPackageInstalls.lockDigest, pluginPackageInstalls.recordDigest, ], name: 'ql3_plugin_package_lifecycle_head_install_fk', }) .onDelete('restrict') .onUpdate('restrict'), check( 'ql3_plugin_package_lifecycle_head_state_check', sql`${table.version} between 1 and 2147483647 and ${table.disposition} in ('active','disabled','uninstalled') and ${table.updatedAtMs} >= 0`, ), check( 'ql3_plugin_package_lifecycle_head_digest_check', sql`length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.installRecordDigest}) = 64 and ${table.installRecordDigest} not glob '*[^0-9a-f]*' and length(${table.eventDigest}) = 64 and ${table.eventDigest} not glob '*[^0-9a-f]*'`, ), ], ); export const pluginPackageLifecycleReceipts = sqliteTable( 'QingLong3PluginPackageLifecycleReceipts', { eventDigest: text('event_digest') .primaryKey() .references(() => pluginPackageLifecycleEvents.eventDigest, { onDelete: 'restrict', }), receiptDigest: text('receipt_digest').notNull(), projectId: text('project_id').notNull(), action: text('action').notNull(), capabilityStatus: text('capability_status').notNull(), taskCount: integer('task_count').notNull(), previousActiveVectorDigest: text('previous_active_vector_digest').notNull(), currentActiveVectorDigest: text('current_active_vector_digest').notNull(), currentToolSnapshotDigest: text('current_tool_snapshot_digest').notNull(), retainedSourceCount: integer('retained_source_count').notNull(), committedAtMs: integer('committed_at_ms').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_lifecycle_receipt_uidx').on( table.receiptDigest, ), foreignKey({ columns: [ table.projectId, table.currentActiveVectorDigest, table.currentToolSnapshotDigest, ], foreignColumns: [ projectToolDefinitionSnapshots.projectId, projectToolDefinitionSnapshots.activeVectorDigest, projectToolDefinitionSnapshots.snapshotDigest, ], name: 'ql3_plugin_package_lifecycle_receipt_snapshot_fk', }).onDelete('restrict'), check( 'ql3_plugin_package_lifecycle_receipt_state_check', sql`(${table.action} = 'disable' and ${table.capabilityStatus} = 'withdrawn' and ${table.previousActiveVectorDigest} <> ${table.currentActiveVectorDigest}) or (${table.action} = 'enable' and ${table.capabilityStatus} = 'restored' and ${table.previousActiveVectorDigest} <> ${table.currentActiveVectorDigest}) or (${table.action} = 'uninstall' and ${table.capabilityStatus} = 'retired' and ${table.taskCount} = 0 and ${table.previousActiveVectorDigest} = ${table.currentActiveVectorDigest})`, ), check( 'ql3_plugin_package_lifecycle_receipt_bounds_check', sql`${table.taskCount} between 0 and 128 and ${table.retainedSourceCount} between 0 and 128 and ${table.committedAtMs} >= 0`, ), check( 'ql3_plugin_package_lifecycle_receipt_digest_check', sql`length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*' and length(${table.previousActiveVectorDigest}) = 64 and ${table.previousActiveVectorDigest} not glob '*[^0-9a-f]*' and length(${table.currentActiveVectorDigest}) = 64 and ${table.currentActiveVectorDigest} not glob '*[^0-9a-f]*' and length(${table.currentToolSnapshotDigest}) = 64 and ${table.currentToolSnapshotDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_lifecycle_receipt_json_check', sql`length(${table.receiptJson}) between 2 and 524288 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-lifecycle-receipt@v1' and json_extract(${table.receiptJson}, '$.eventDigest') = ${table.eventDigest} and json_extract(${table.receiptJson}, '$.action') = ${table.action} and json_extract(${table.receiptJson}, '$.target.projectId') = ${table.projectId} and json_extract(${table.receiptJson}, '$.capability.status') = ${table.capabilityStatus} and json_array_length(json_extract(${table.receiptJson}, '$.capability.taskTransitions')) = ${table.taskCount} and json_extract(${table.receiptJson}, '$.capability.previousActiveVectorDigest') = ${table.previousActiveVectorDigest} and json_extract(${table.receiptJson}, '$.capability.currentActiveVectorDigest') = ${table.currentActiveVectorDigest} and json_extract(${table.receiptJson}, '$.capability.currentToolSnapshotDigest') = ${table.currentToolSnapshotDigest} and json_extract(${table.receiptJson}, '$.capability.retainedSourceCount') = ${table.retainedSourceCount} and json_extract(${table.receiptJson}, '$.committedAtMs') = ${table.committedAtMs} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest}`, ), index('ql3_plugin_package_lifecycle_receipt_snapshot_idx').on( table.projectId, table.currentActiveVectorDigest, table.eventDigest, ), ], ); export const pluginPackageLifecycleTasks = sqliteTable( 'QingLong3PluginPackageLifecycleTasks', { eventDigest: text('event_digest') .notNull() .references(() => pluginPackageLifecycleReceipts.eventDigest, { onDelete: 'restrict', }), projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), previousRevision: integer('previous_revision').notNull(), currentRevision: integer('current_revision').notNull(), previousContentDigest: text('previous_content_digest').notNull(), currentContentDigest: text('current_content_digest').notNull(), previousEnabled: integer('previous_enabled').notNull(), currentEnabled: integer('current_enabled').notNull(), }, (table) => [ primaryKey({ columns: [table.eventDigest, table.taskId] }), foreignKey({ columns: [table.projectId, table.taskId, table.previousRevision], foreignColumns: [ taskDefinitionRevisions.projectId, taskDefinitionRevisions.taskId, taskDefinitionRevisions.revision, ], name: 'ql3_plugin_package_lifecycle_task_previous_fk', }).onDelete('restrict'), foreignKey({ columns: [table.projectId, table.taskId, table.currentRevision], foreignColumns: [ taskDefinitionRevisions.projectId, taskDefinitionRevisions.taskId, taskDefinitionRevisions.revision, ], name: 'ql3_plugin_package_lifecycle_task_current_fk', }).onDelete('restrict'), check( 'ql3_plugin_package_lifecycle_task_transition_check', sql`${table.currentRevision} = ${table.previousRevision} + 1 and ${table.previousEnabled} in (0, 1) and ${table.currentEnabled} in (0, 1) and ${table.previousEnabled} <> ${table.currentEnabled}`, ), check( 'ql3_plugin_package_lifecycle_task_digest_check', sql`length(${table.previousContentDigest}) = 64 and ${table.previousContentDigest} not glob '*[^0-9a-f]*' and length(${table.currentContentDigest}) = 64 and ${table.currentContentDigest} not glob '*[^0-9a-f]*'`, ), index('ql3_plugin_package_lifecycle_task_idx').on( table.projectId, table.taskId, table.eventDigest, ), ], ); export const pluginPackageAutomationPublications = sqliteTable( 'QingLong3PluginPackageAutomationPublications', { publicationDigest: text('publication_digest').primaryKey(), projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), lockDigest: text('lock_digest').notNull(), generation: integer('generation').notNull(), generationDigest: text('generation_digest') .notNull() .references(() => pluginPackageMaterializedRevisions.generationDigest, { onDelete: 'restrict', onUpdate: 'restrict', }), materializedRevisionDigest: text('materialized_revision_digest').notNull(), state: text('state').notNull(), version: integer('version').notNull(), previousPublicationDigest: text('previous_publication_digest').references( (): AnySQLiteColumn => pluginPackageAutomationPublications.publicationDigest, { onDelete: 'restrict', onUpdate: 'restrict' }, ), lifecycleEventDigest: text('lifecycle_event_digest').references( () => pluginPackageLifecycleEvents.eventDigest, { onDelete: 'restrict', onUpdate: 'restrict' }, ), publishedAtMs: integer('published_at_ms').notNull(), publicationJson: text('publication_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_automation_publication_version_uidx').on( table.projectId, table.packageName, table.version, ), uniqueIndex('ql3_plugin_package_automation_publication_previous_uidx') .on(table.previousPublicationDigest) .where(sql`${table.previousPublicationDigest} is not null`), index('ql3_plugin_package_automation_publication_generation_idx').on( table.generationDigest, table.publicationDigest, ), check( 'ql3_plugin_package_automation_publication_identity_check', sql`length(${table.projectId}) between 1 and 128 and length(${table.packageName}) between 1 and 63 and length(${table.installationId}) between 1 and 128 and ${table.generation} between 1 and 2147483647 and ${table.state} in ('active','withdrawn','absent') and ${table.version} between 1 and 2147483647 and ${table.publishedAtMs} >= 0 and ((${table.version} = 1 and ${table.state} in ('active','absent') and ${table.previousPublicationDigest} is null and ${table.lifecycleEventDigest} is null) or (${table.version} > 1 and ${table.previousPublicationDigest} is not null)) and (${table.state} <> 'withdrawn' or ${table.lifecycleEventDigest} is not null)`, ), check( 'ql3_plugin_package_automation_publication_digest_check', sql`length(${table.publicationDigest}) = 64 and ${table.publicationDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.materializedRevisionDigest}) = 64 and ${table.materializedRevisionDigest} not glob '*[^0-9a-f]*' and (${table.previousPublicationDigest} is null or (length(${table.previousPublicationDigest}) = 64 and ${table.previousPublicationDigest} not glob '*[^0-9a-f]*')) and (${table.lifecycleEventDigest} is null or (length(${table.lifecycleEventDigest}) = 64 and ${table.lifecycleEventDigest} not glob '*[^0-9a-f]*'))`, ), check( 'ql3_plugin_package_automation_publication_json_check', sql`length(cast(${table.publicationJson} as blob)) between 2 and 12582912 and json_valid(${table.publicationJson}) and json_type(${table.publicationJson}) = 'object' and json_extract(${table.publicationJson}, '$.schema') = 'qinglong/plugin-package-automation-publication@v1' and json_extract(${table.publicationJson}, '$.target.projectId') = ${table.projectId} and json_extract(${table.publicationJson}, '$.target.packageName') = ${table.packageName} and json_extract(${table.publicationJson}, '$.target.installationId') = ${table.installationId} and json_extract(${table.publicationJson}, '$.target.lockDigest') = ${table.lockDigest} and json_extract(${table.publicationJson}, '$.target.generation') = ${table.generation} and json_extract(${table.publicationJson}, '$.target.generationDigest') = ${table.generationDigest} and json_extract(${table.publicationJson}, '$.target.materializedRevisionDigest') = ${table.materializedRevisionDigest} and json_extract(${table.publicationJson}, '$.state') = ${table.state} and json_extract(${table.publicationJson}, '$.version') = ${table.version} and ((${table.previousPublicationDigest} is null and json_type(${table.publicationJson}, '$.previousPublicationDigest') = 'null') or json_extract(${table.publicationJson}, '$.previousPublicationDigest') = ${table.previousPublicationDigest}) and ((${table.lifecycleEventDigest} is null and json_type(${table.publicationJson}, '$.lifecycleEventDigest') = 'null') or json_extract(${table.publicationJson}, '$.lifecycleEventDigest') = ${table.lifecycleEventDigest}) and json_extract(${table.publicationJson}, '$.publishedAtMs') = ${table.publishedAtMs} and json_extract(${table.publicationJson}, '$.publicationDigest') = ${table.publicationDigest} and json_type(${table.publicationJson}, '$.definitions.workflows') = 'array' and json_type(${table.publicationJson}, '$.definitions.prompts') = 'array' and ((${table.state} = 'absent' and json_array_length(json_extract(${table.publicationJson}, '$.definitions.workflows')) + json_array_length(json_extract(${table.publicationJson}, '$.definitions.prompts')) = 0) or (${table.state} <> 'absent' and json_array_length(json_extract(${table.publicationJson}, '$.definitions.workflows')) + json_array_length(json_extract(${table.publicationJson}, '$.definitions.prompts')) > 0))`, ), ], ); export const pluginPackageAutomationPublicationHeads = sqliteTable( 'QingLong3PluginPackageAutomationPublicationHeads', { projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), publicationDigest: text('publication_digest') .notNull() .references(() => pluginPackageAutomationPublications.publicationDigest, { onDelete: 'restrict', onUpdate: 'restrict', }), generationDigest: text('generation_digest').notNull(), state: text('state').notNull(), version: integer('version').notNull(), updatedAtMs: integer('updated_at_ms').notNull(), }, (table) => [ primaryKey({ columns: [table.projectId, table.packageName] }), uniqueIndex( 'ql3_plugin_package_automation_publication_head_digest_uidx', ).on(table.publicationDigest), check( 'ql3_plugin_package_automation_publication_head_state_check', sql`length(${table.projectId}) between 1 and 128 and length(${table.packageName}) between 1 and 63 and length(${table.publicationDigest}) = 64 and ${table.publicationDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and ${table.state} in ('active','withdrawn','absent') and ${table.version} between 1 and 2147483647 and ${table.updatedAtMs} >= 0`, ), ], ); export const pluginPackageWorkflowAdmissions = sqliteTable( 'QingLong3PluginPackageWorkflowAdmissions', { planDigest: text('plan_digest').primaryKey(), planId: text('plan_id').notNull(), runId: text('run_id') .notNull() .references(() => runs.id, { onDelete: 'restrict', onUpdate: 'restrict', }), projectId: text('project_id').notNull(), packageName: text('package_name').notNull(), installationId: text('installation_id').notNull(), lockDigest: text('lock_digest').notNull(), generation: integer('generation').notNull(), generationDigest: text('generation_digest').notNull(), materializedRevisionDigest: text('materialized_revision_digest').notNull(), publicationDigest: text('publication_digest') .notNull() .references(() => pluginPackageAutomationPublications.publicationDigest, { onDelete: 'restrict', onUpdate: 'restrict', }), workflowId: text('workflow_id').notNull(), workflowDefinitionDigest: text('workflow_definition_digest').notNull(), stepCount: integer('step_count').notNull(), admittedAtMs: integer('admitted_at_ms').notNull(), finalRunVersion: integer('final_run_version').notNull(), finalRunEventSequence: integer('final_run_event_sequence').notNull(), receiptDigest: text('receipt_digest').notNull(), planJson: text('plan_json', { mode: 'json' }) .$type>() .notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ uniqueIndex('ql3_plugin_package_workflow_admission_plan_uidx').on( table.planId, ), uniqueIndex('ql3_plugin_package_workflow_admission_run_uidx').on( table.runId, ), uniqueIndex('ql3_plugin_package_workflow_admission_receipt_uidx').on( table.receiptDigest, ), uniqueIndex('ql3_plugin_package_workflow_admission_plan_run_uidx').on( table.planDigest, table.runId, ), index('ql3_plugin_package_workflow_admission_target_idx').on( table.projectId, table.packageName, table.admittedAtMs, table.planDigest, ), index('ql3_plugin_package_workflow_admission_workflow_history_idx').on( table.projectId, table.packageName, table.workflowId, table.admittedAtMs, table.runId, ), check( 'ql3_plugin_package_workflow_admission_identity_check', sql`length(${table.planId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.packageName}) between 1 and 63 and length(${table.installationId}) between 1 and 128 and length(${table.workflowId}) between 1 and 63 and ${table.generation} between 1 and 2147483647 and ${table.stepCount} between 1 and 128 and ${table.admittedAtMs} >= 0 and ${table.finalRunVersion} = ${table.stepCount} + 1 and ${table.finalRunEventSequence} = ${table.stepCount} + 1`, ), check( 'ql3_plugin_package_workflow_admission_digest_check', sql`length(${table.planDigest}) = 64 and ${table.planDigest} not glob '*[^0-9a-f]*' and length(${table.lockDigest}) = 64 and ${table.lockDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.materializedRevisionDigest}) = 64 and ${table.materializedRevisionDigest} not glob '*[^0-9a-f]*' and length(${table.publicationDigest}) = 64 and ${table.publicationDigest} not glob '*[^0-9a-f]*' and length(${table.workflowDefinitionDigest}) = 64 and ${table.workflowDefinitionDigest} not glob '*[^0-9a-f]*' and length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_workflow_admission_plan_json_check', sql`length(cast(${table.planJson} as blob)) between 2 and 262144 and json_valid(${table.planJson}) and json_type(${table.planJson}) = 'object' and json_extract(${table.planJson}, '$.schema') = 'qinglong/plugin-package-workflow-execution-plan@v1' and json_extract(${table.planJson}, '$.planId') = ${table.planId} and json_extract(${table.planJson}, '$.planDigest') = ${table.planDigest} and json_extract(${table.planJson}, '$.runId') = ${table.runId} and json_extract(${table.planJson}, '$.target.projectId') = ${table.projectId} and json_extract(${table.planJson}, '$.target.packageName') = ${table.packageName} and json_extract(${table.planJson}, '$.target.installationId') = ${table.installationId} and json_extract(${table.planJson}, '$.target.lockDigest') = ${table.lockDigest} and json_extract(${table.planJson}, '$.target.generation') = ${table.generation} and json_extract(${table.planJson}, '$.target.generationDigest') = ${table.generationDigest} and json_extract(${table.planJson}, '$.target.materializedRevisionDigest') = ${table.materializedRevisionDigest} and json_extract(${table.planJson}, '$.target.publicationDigest') = ${table.publicationDigest} and json_extract(${table.planJson}, '$.target.workflowId') = ${table.workflowId} and json_extract(${table.planJson}, '$.target.workflowDefinitionDigest') = ${table.workflowDefinitionDigest} and json_extract(${table.planJson}, '$.plannedAtMs') = ${table.admittedAtMs} and json_array_length(json_extract(${table.planJson}, '$.steps')) = ${table.stepCount}`, ), check( 'ql3_plugin_package_workflow_admission_receipt_json_check', sql`length(cast(${table.receiptJson} as blob)) between 2 and 262144 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-workflow-admission-receipt@v1' and json_extract(${table.receiptJson}, '$.planId') = ${table.planId} and json_extract(${table.receiptJson}, '$.planDigest') = ${table.planDigest} and json_extract(${table.receiptJson}, '$.runId') = ${table.runId} and json_extract(${table.receiptJson}, '$.publicationDigest') = ${table.publicationDigest} and json_extract(${table.receiptJson}, '$.workflowId') = ${table.workflowId} and json_extract(${table.receiptJson}, '$.admittedAtMs') = ${table.admittedAtMs} and json_extract(${table.receiptJson}, '$.finalRunVersion') = ${table.finalRunVersion} and json_extract(${table.receiptJson}, '$.finalRunEventSequence') = ${table.finalRunEventSequence} and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest} and json_array_length(json_extract(${table.receiptJson}, '$.steps')) = ${table.stepCount}`, ), ], ); export const pluginPackageWorkflowAdmissionSteps = sqliteTable( 'QingLong3PluginPackageWorkflowAdmissionSteps', { planDigest: text('plan_digest').notNull(), runId: text('run_id').notNull(), stepKey: text('step_key').notNull(), stepRunId: text('step_run_id').notNull(), taskId: text('task_id').notNull(), taskDefinitionRef: text('task_definition_ref').notNull(), taskDefinitionDigest: text('task_definition_digest').notNull(), needsJson: text('needs_json', { mode: 'json' }) .$type() .notNull(), initialStatus: text('initial_status').notNull(), mutationId: text('mutation_id') .notNull() .references(() => stepRunMutations.mutationId, { onDelete: 'restrict', onUpdate: 'restrict', }), eventId: text('event_id') .notNull() .references(() => runEvents.id, { onDelete: 'restrict', onUpdate: 'restrict', }), }, (table) => [ primaryKey({ columns: [table.planDigest, table.stepKey] }), foreignKey({ columns: [table.planDigest, table.runId], foreignColumns: [ pluginPackageWorkflowAdmissions.planDigest, pluginPackageWorkflowAdmissions.runId, ], name: 'ql3_plugin_package_workflow_admission_step_admission_fk', }) .onDelete('restrict') .onUpdate('restrict'), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_plugin_package_workflow_admission_step_run_fk', }) .onDelete('restrict') .onUpdate('restrict'), uniqueIndex('ql3_plugin_package_workflow_admission_step_run_uidx').on( table.stepRunId, ), uniqueIndex('ql3_plugin_package_workflow_admission_step_mutation_uidx').on( table.mutationId, ), uniqueIndex('ql3_plugin_package_workflow_admission_step_event_uidx').on( table.eventId, ), index('ql3_plugin_package_workflow_admission_step_task_idx').on( table.taskId, table.taskDefinitionDigest, table.planDigest, ), check( 'ql3_plugin_package_workflow_admission_step_identity_check', sql`length(${table.runId}) between 1 and 128 and length(${table.stepKey}) between 1 and 63 and length(${table.stepRunId}) between 1 and 128 and length(${table.taskId}) between 1 and 63 and length(cast(${table.taskDefinitionRef} as blob)) between 1 and 512 and length(${table.mutationId}) between 1 and 128 and length(${table.eventId}) between 1 and 128 and ${table.initialStatus} in ('pending','ready')`, ), check( 'ql3_plugin_package_workflow_admission_step_digest_check', sql`length(${table.planDigest}) = 64 and ${table.planDigest} not glob '*[^0-9a-f]*' and length(${table.taskDefinitionDigest}) = 64 and ${table.taskDefinitionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_workflow_admission_step_needs_check', sql`length(cast(${table.needsJson} as blob)) between 2 and 8192 and json_valid(${table.needsJson}) and json_type(${table.needsJson}) = 'array' and json_array_length(${table.needsJson}) between 0 and 127`, ), ], ); export const pluginPackageWorkflowTaskAttemptAdmissions = sqliteTable( 'QingLong3PluginPackageWorkflowTaskAttemptAdmissions', { receiptDigest: text('receipt_digest').primaryKey(), attemptId: text('attempt_id') .notNull() .references(() => runAttempts.id, { onDelete: 'restrict', onUpdate: 'restrict', }), planDigest: text('plan_digest').notNull(), runId: text('run_id').notNull(), stepRunId: text('step_run_id').notNull(), stepRunVersion: integer('step_run_version').notNull(), stepRunDigest: text('step_run_digest').notNull(), generationDigest: text('generation_digest').notNull(), resourceTaskId: text('resource_task_id').notNull(), taskReconciliationReceiptDigest: text( 'task_reconciliation_receipt_digest', ).notNull(), projectId: text('project_id').notNull(), taskId: text('task_id').notNull(), taskRevision: text('task_revision').notNull(), taskDefinitionDigest: text('task_definition_digest').notNull(), executorType: text('executor_type').notNull(), executionDigest: text('execution_digest').notNull(), attemptNumber: integer('attempt_number').notNull(), eventId: text('event_id') .notNull() .references(() => runEvents.id, { onDelete: 'restrict', onUpdate: 'restrict', }), runVersion: integer('run_version').notNull(), runEventSequence: integer('run_event_sequence').notNull(), admittedAtMs: integer('admitted_at_ms').notNull(), receiptJson: text('receipt_json', { mode: 'json' }) .$type>() .notNull(), }, (table) => [ foreignKey({ columns: [table.planDigest, table.runId], foreignColumns: [ pluginPackageWorkflowAdmissions.planDigest, pluginPackageWorkflowAdmissions.runId, ], name: 'ql3_plugin_package_workflow_task_attempt_admission_plan_fk', }) .onDelete('restrict') .onUpdate('restrict'), foreignKey({ columns: [table.runId, table.stepRunId], foreignColumns: [stepRuns.runId, stepRuns.id], name: 'ql3_plugin_package_workflow_task_attempt_admission_step_fk', }) .onDelete('restrict') .onUpdate('restrict'), foreignKey({ columns: [table.generationDigest, table.taskReconciliationReceiptDigest], foreignColumns: [ pluginPackageTaskReconciliations.generationDigest, pluginPackageTaskReconciliations.receiptDigest, ], name: 'ql3_plugin_package_workflow_task_attempt_admission_reconciliation_fk', }) .onDelete('restrict') .onUpdate('restrict'), foreignKey({ columns: [table.projectId, table.taskId, table.taskRevision], foreignColumns: [ localTaskExecutionRevisions.projectId, localTaskExecutionRevisions.taskId, localTaskExecutionRevisions.taskRevision, ], name: 'ql3_plugin_package_workflow_task_attempt_admission_execution_fk', }) .onDelete('restrict') .onUpdate('restrict'), uniqueIndex( 'ql3_plugin_package_workflow_task_attempt_admission_attempt_uidx', ).on(table.attemptId), uniqueIndex( 'ql3_plugin_package_workflow_task_attempt_admission_event_uidx', ).on(table.eventId), uniqueIndex( 'ql3_plugin_package_workflow_task_attempt_admission_epoch_uidx', ).on(table.runId, table.stepRunId, table.stepRunVersion), uniqueIndex( 'ql3_plugin_package_workflow_task_attempt_admission_number_uidx', ).on(table.runId, table.attemptNumber), index( 'ql3_plugin_package_workflow_task_attempt_admission_candidate_idx', ).on(table.runId, table.stepRunId, table.admittedAtMs), check( 'ql3_plugin_package_workflow_task_attempt_admission_identity_check', sql`length(${table.attemptId}) between 1 and 128 and length(${table.runId}) between 1 and 128 and length(${table.stepRunId}) between 1 and 128 and length(${table.resourceTaskId}) between 1 and 128 and length(${table.projectId}) between 1 and 128 and length(${table.taskId}) between 1 and 128 and length(${table.taskRevision}) between 1 and 128 and length(${table.eventId}) between 1 and 128 and ${table.executorType} = 'local_process'`, ), check( 'ql3_plugin_package_workflow_task_attempt_admission_counter_check', sql`${table.stepRunVersion} between 1 and 2147483647 and ${table.attemptNumber} between 1 and 8192 and ${table.runVersion} between 1 and 2147483647 and ${table.runEventSequence} = ${table.runVersion} and ${table.admittedAtMs} >= 0`, ), check( 'ql3_plugin_package_workflow_task_attempt_admission_digest_check', sql`length(${table.receiptDigest}) = 64 and ${table.receiptDigest} not glob '*[^0-9a-f]*' and length(${table.planDigest}) = 64 and ${table.planDigest} not glob '*[^0-9a-f]*' and length(${table.stepRunDigest}) = 64 and ${table.stepRunDigest} not glob '*[^0-9a-f]*' and length(${table.generationDigest}) = 64 and ${table.generationDigest} not glob '*[^0-9a-f]*' and length(${table.taskReconciliationReceiptDigest}) = 64 and ${table.taskReconciliationReceiptDigest} not glob '*[^0-9a-f]*' and length(${table.taskDefinitionDigest}) = 64 and ${table.taskDefinitionDigest} not glob '*[^0-9a-f]*' and length(${table.executionDigest}) = 64 and ${table.executionDigest} not glob '*[^0-9a-f]*'`, ), check( 'ql3_plugin_package_workflow_task_attempt_admission_json_check', sql`length(cast(${table.receiptJson} as blob)) between 2 and 16384 and json_valid(${table.receiptJson}) and json_type(${table.receiptJson}) = 'object' and json_extract(${table.receiptJson}, '$.schema') = 'qinglong/plugin-package-workflow-task-attempt-admission@v1' and json_extract(${table.receiptJson}, '$.receiptDigest') = ${table.receiptDigest} and json_extract(${table.receiptJson}, '$.attemptId') = ${table.attemptId} and json_extract(${table.receiptJson}, '$.planDigest') = ${table.planDigest} and json_extract(${table.receiptJson}, '$.runId') = ${table.runId} and json_extract(${table.receiptJson}, '$.stepRunId') = ${table.stepRunId} and json_extract(${table.receiptJson}, '$.stepRunVersion') = ${table.stepRunVersion} and json_extract(${table.receiptJson}, '$.stepRunDigest') = ${table.stepRunDigest} and json_extract(${table.receiptJson}, '$.resourceTaskId') = ${table.resourceTaskId} and json_extract(${table.receiptJson}, '$.taskReconciliationReceiptDigest') = ${table.taskReconciliationReceiptDigest} and json_extract(${table.receiptJson}, '$.taskId') = ${table.taskId} and json_extract(${table.receiptJson}, '$.taskRevision') = ${table.taskRevision} and json_extract(${table.receiptJson}, '$.taskDefinitionDigest') = ${table.taskDefinitionDigest} and json_extract(${table.receiptJson}, '$.executorType') = ${table.executorType} and json_extract(${table.receiptJson}, '$.executionDigest') = ${table.executionDigest} and json_extract(${table.receiptJson}, '$.attemptNumber') = ${table.attemptNumber} and json_extract(${table.receiptJson}, '$.eventId') = ${table.eventId} and json_extract(${table.receiptJson}, '$.runVersion') = ${table.runVersion} and json_extract(${table.receiptJson}, '$.runEventSequence') = ${table.runEventSequence} and json_extract(${table.receiptJson}, '$.admittedAtMs') = ${table.admittedAtMs}`, ), ], ); export const localSqliteSchema = Object.freeze({ localSchemaMigrations, localSchemaCapabilities, runs, stepRuns, runAttempts, runEvents, stepRunMutations, runRetryPolicies, localCompletionReceiptJournal, runAttemptLogArtifactTombstones, runAttemptLogRetentionState, localExecutionContextRecipes, localTaskExecutionRevisions, localSecretEnvelopes, localProjects, approvalRequests, approvedActionDispatches, approvedActionExecutions, pluginPackageInstallProposals, pluginPackageInstalls, pluginPackageInstallHeads, pluginPackageInstallMutations, pluginPackageMaterializedRevisions, pluginPackageQuarantineEvents, pluginPackageWithdrawalReceipts, pluginPackageWithdrawalTasks, pluginPackageLifecycleEvents, pluginPackageLifecycleHeads, pluginPackageLifecycleReceipts, pluginPackageLifecycleTasks, pluginPackageAutomationPublications, pluginPackageAutomationPublicationHeads, pluginPackageWorkflowAdmissions, pluginPackageWorkflowAdmissionSteps, pluginPackageWorkflowTaskAttemptAdmissions, projectToolDefinitionSnapshots, projectToolDefinitionSnapshotSources, pluginPackageTaskOwnerships, pluginPackageTaskReconciliations, pluginPackageTaskReconciliationItems, pluginPackageAdmissionReceipts, taskDefinitions, taskDefinitionRevisions, triggers, triggerRevisions, localTriggerSchedules, localProjectRoleBindings, localSecurityAuditEvents, localProjectAdministrationMutations, localSecurityAuditCompactions, toolExecutionTraceAnchors, toolExecutionAuditReceipts, toolExecutionStartBarriers, toolInvocationInputArtifacts, toolInvocationPreviewArtifacts, toolExecutionStartArtifactBindings, toolExecutionCompletions, toolExecutionFailureCompletions, toolResultKeyCatalogGenerations, toolExecutionResultKeyBindings, toolExecutionResultRekeyOverlays, toolExecutionResultRekeyHeads, toolResultKeyRetirementReceipts, legacyAdoptions, localIdentitySubjects, localApiCredentials, localApiCredentialPepperBindings, localIdentityAdministrationMutations, localApiCredentialAdministrationMutations, localApiCredentialDeliveryAcknowledgements, localOwnerPepperKeys, localOwnerPepperActivations, localIdentityProvisionings, localOwnerBootstrapChallenges, localOwnerDeliveryAcknowledgements, localOwnerDeliveryAcknowledgementGc, localOwnerCredentialRecoveries, localOwnerPepperMaterialGc, });