Publish DevRunbook source
Managed validation / full (push) Successful in 3m18s

This commit is contained in:
DevRunbook release export
2026-09-03 04:09:17 +02:00
commit cfd2804e27
928 changed files with 161642 additions and 0 deletions
@@ -0,0 +1,511 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto;
--> statement-breakpoint
CREATE TABLE "audit_events" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"occurred_at" timestamp with time zone DEFAULT now() NOT NULL,
"actor_user_id" uuid,
"workspace_id" uuid,
"action" text NOT NULL,
"resource_type" text NOT NULL,
"resource_id" text,
"request_id" text,
"outcome" text NOT NULL,
"metadata_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
CONSTRAINT "audit_events_outcome_check" CHECK ("audit_events"."outcome" in ('success', 'denied', 'failed'))
);
--> statement-breakpoint
CREATE TABLE "auth_sessions" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"token_hash" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"last_seen_at" timestamp with time zone DEFAULT now() NOT NULL,
"idle_expires_at" timestamp with time zone NOT NULL,
"absolute_expires_at" timestamp with time zone NOT NULL,
"revoked_at" timestamp with time zone,
"source_ip_hash" text,
"user_agent_summary" text,
CONSTRAINT "auth_sessions_token_hash_uq" UNIQUE("token_hash")
);
--> statement-breakpoint
CREATE TABLE "collection_items" (
"collection_id" uuid NOT NULL,
"playbook_id" uuid NOT NULL,
"position" integer DEFAULT 0 NOT NULL,
"added_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "collection_items_pkey" PRIMARY KEY("collection_id","playbook_id")
);
--> statement-breakpoint
CREATE TABLE "collections" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid NOT NULL,
"name" text NOT NULL,
"description" text DEFAULT '' NOT NULL,
"created_by" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "collections_workspace_name_uq" UNIQUE("workspace_id","name")
);
--> statement-breakpoint
CREATE TABLE "composition_drafts" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid NOT NULL,
"playbook_version_id" uuid NOT NULL,
"repository_profile_revision_id" uuid,
"input_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"scope_override_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"autonomy_level" text NOT NULL,
"work_mode" text NOT NULL,
"last_render_digest" text,
"created_by" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "evaluation_cases" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"playbook_version_id" uuid NOT NULL,
"logical_case_id" text NOT NULL,
"fixture_version" text NOT NULL,
"case_json" jsonb NOT NULL,
"case_digest" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "evaluation_cases_identity_uq" UNIQUE("playbook_version_id","logical_case_id","fixture_version")
);
--> statement-breakpoint
CREATE TABLE "evaluation_results" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"evaluation_case_id" uuid NOT NULL,
"environment_json" jsonb NOT NULL,
"status" text NOT NULL,
"dimension_scores_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"evidence_artifact_id" uuid,
"executed_by" uuid,
"executed_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "evaluation_results_status_check" CHECK ("evaluation_results"."status" in ('passed', 'failed', 'error', 'skipped', 'stale'))
);
--> statement-breakpoint
CREATE TABLE "favorites" (
"workspace_id" uuid NOT NULL,
"user_id" uuid NOT NULL,
"playbook_id" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "favorites_pkey" PRIMARY KEY("workspace_id","user_id","playbook_id")
);
--> statement-breakpoint
CREATE TABLE "generated_artifacts" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"run_id" uuid NOT NULL,
"artifact_type" text NOT NULL,
"storage_key" text NOT NULL,
"filename" text NOT NULL,
"media_type" text NOT NULL,
"size_bytes" bigint NOT NULL,
"sha256" text NOT NULL,
"expires_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "generated_artifacts_storage_key_uq" UNIQUE("storage_key"),
CONSTRAINT "generated_artifacts_type_check" CHECK ("generated_artifacts"."artifact_type" in ('prompt_text', 'markdown', 'run_pack_zip', 'agents_suggestion', 'support_bundle')),
CONSTRAINT "generated_artifacts_size_check" CHECK ("generated_artifacts"."size_bytes" >= 0)
);
--> statement-breakpoint
CREATE TABLE "generated_runs" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid NOT NULL,
"source_draft_id" uuid,
"playbook_version_id" uuid NOT NULL,
"playbook_snapshot_json" jsonb NOT NULL,
"repository_profile_snapshot_json" jsonb,
"normalized_input_json" jsonb NOT NULL,
"policy_snapshot_json" jsonb NOT NULL,
"provenance_json" jsonb NOT NULL,
"lint_result_json" jsonb NOT NULL,
"rendered_prompt" text NOT NULL,
"render_digest" text NOT NULL,
"idempotency_key" text,
"generated_by" uuid NOT NULL,
"generated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "generated_runs_workspace_idempotency_uq" UNIQUE("workspace_id","idempotency_key")
);
--> statement-breakpoint
CREATE TABLE "instance_settings" (
"singleton" boolean PRIMARY KEY DEFAULT true NOT NULL,
"setup_completed_at" timestamp with time zone,
"owner_user_id" uuid,
"config_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"config_digest" text,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "instance_settings_singleton_check" CHECK ("instance_settings"."singleton")
);
--> statement-breakpoint
CREATE TABLE "integration_secrets" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"integration_id" uuid NOT NULL,
"secret_kind" text NOT NULL,
"envelope_version" integer NOT NULL,
"key_version" text NOT NULL,
"nonce" bytea NOT NULL,
"ciphertext" bytea NOT NULL,
"auth_tag" bytea NOT NULL,
"last_four" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"rotated_at" timestamp with time zone,
CONSTRAINT "integration_secrets_integration_kind_uq" UNIQUE("integration_id","secret_kind")
);
--> statement-breakpoint
CREATE TABLE "integrations" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid NOT NULL,
"type" text NOT NULL,
"display_name" text NOT NULL,
"base_url" text NOT NULL,
"status" text DEFAULT 'configured' NOT NULL,
"capabilities_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"last_checked_at" timestamp with time zone,
"created_by" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "integrations_workspace_type_base_url_uq" UNIQUE("workspace_id","type","base_url"),
CONSTRAINT "integrations_type_check" CHECK ("integrations"."type" in ('gitea')),
CONSTRAINT "integrations_status_check" CHECK ("integrations"."status" in ('configured', 'healthy', 'degraded', 'disabled'))
);
--> statement-breakpoint
CREATE TABLE "invitations" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"email" text NOT NULL,
"token_hash" text NOT NULL,
"instance_role" text NOT NULL,
"workspace_id" uuid,
"workspace_role" text,
"expires_at" timestamp with time zone NOT NULL,
"accepted_at" timestamp with time zone,
"created_by" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "invitations_token_hash_uq" UNIQUE("token_hash"),
CONSTRAINT "invitations_instance_role_check" CHECK ("invitations"."instance_role" in ('instance_admin', 'user')),
CONSTRAINT "invitations_workspace_role_check" CHECK ("invitations"."workspace_role" is null or "invitations"."workspace_role" in ('owner', 'editor', 'viewer'))
);
--> statement-breakpoint
CREATE TABLE "jobs" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid,
"type" text NOT NULL,
"state" text NOT NULL,
"idempotency_key" text,
"payload_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"progress_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"attempt_count" integer DEFAULT 0 NOT NULL,
"max_attempts" integer DEFAULT 3 NOT NULL,
"lease_owner" text,
"lease_expires_at" timestamp with time zone,
"available_at" timestamp with time zone DEFAULT now() NOT NULL,
"started_at" timestamp with time zone,
"finished_at" timestamp with time zone,
"error_code" text,
"error_detail_redacted" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "jobs_state_check" CHECK ("jobs"."state" in ('queued', 'running', 'succeeded', 'failed', 'cancelled')),
CONSTRAINT "jobs_attempt_count_check" CHECK ("jobs"."attempt_count" >= 0),
CONSTRAINT "jobs_max_attempts_check" CHECK ("jobs"."max_attempts" > 0)
);
--> statement-breakpoint
CREATE TABLE "password_reset_tokens" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"token_hash" text NOT NULL,
"expires_at" timestamp with time zone NOT NULL,
"used_at" timestamp with time zone,
"created_by" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "password_reset_tokens_token_hash_uq" UNIQUE("token_hash")
);
--> statement-breakpoint
CREATE TABLE "playbook_versions" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"playbook_id" uuid NOT NULL,
"semantic_version" text NOT NULL,
"lifecycle" text NOT NULL,
"package_api_version" text NOT NULL,
"title" text NOT NULL,
"summary" text NOT NULL,
"category" text NOT NULL,
"risk_tier" text NOT NULL,
"package_json" jsonb NOT NULL,
"template_text" text NOT NULL,
"content_digest" text NOT NULL,
"search_document" tsvector,
"published_at" timestamp with time zone,
"supersedes_version_id" uuid,
"created_by" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "playbook_versions_playbook_semver_uq" UNIQUE("playbook_id","semantic_version"),
CONSTRAINT "playbook_versions_lifecycle_check" CHECK ("playbook_versions"."lifecycle" in ('draft', 'reviewed', 'validated', 'battle-tested', 'deprecated')),
CONSTRAINT "playbook_versions_risk_tier_check" CHECK ("playbook_versions"."risk_tier" in ('low', 'moderate', 'high', 'critical'))
);
--> statement-breakpoint
CREATE TABLE "playbooks" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid,
"logical_id" text NOT NULL,
"slug" text NOT NULL,
"namespace" text NOT NULL,
"source_type" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "playbooks_namespace_logical_id_uq" UNIQUE("namespace","logical_id"),
CONSTRAINT "playbooks_namespace_slug_uq" UNIQUE("namespace","slug"),
CONSTRAINT "playbooks_source_type_check" CHECK ("playbooks"."source_type" in ('built_in', 'private', 'imported', 'remote_registry'))
);
--> statement-breakpoint
CREATE TABLE "repositories" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"workspace_id" uuid NOT NULL,
"display_name" text NOT NULL,
"source_type" text NOT NULL,
"external_owner" text,
"external_name" text,
"external_id" text,
"integration_id" uuid,
"default_branch" text,
"archived" boolean DEFAULT false NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "repositories_source_type_check" CHECK ("repositories"."source_type" in ('manual', 'gitea'))
);
--> statement-breakpoint
CREATE TABLE "repository_findings" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"snapshot_id" uuid NOT NULL,
"rule_id" text NOT NULL,
"severity" text NOT NULL,
"title" text NOT NULL,
"rationale" text NOT NULL,
"evidence_pointer" text NOT NULL,
"recommended_playbook_slug" text,
"status" text DEFAULT 'open' NOT NULL,
"resolution_note" text,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "repository_findings_evidence_uq" UNIQUE("snapshot_id","rule_id","evidence_pointer"),
CONSTRAINT "repository_findings_severity_check" CHECK ("repository_findings"."severity" in ('info', 'low', 'medium', 'high', 'critical')),
CONSTRAINT "repository_findings_status_check" CHECK ("repository_findings"."status" in ('open', 'dismissed', 'resolved'))
);
--> statement-breakpoint
CREATE TABLE "repository_profile_revisions" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"repository_id" uuid NOT NULL,
"revision_number" integer NOT NULL,
"profile_json" jsonb NOT NULL,
"source_snapshot_id" uuid,
"content_digest" text NOT NULL,
"created_by" uuid NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "repository_profile_revisions_repository_number_uq" UNIQUE("repository_id","revision_number"),
CONSTRAINT "repository_profile_revisions_repository_digest_uq" UNIQUE("repository_id","content_digest")
);
--> statement-breakpoint
CREATE TABLE "repository_snapshots" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"repository_id" uuid NOT NULL,
"integration_id" uuid,
"state" text NOT NULL,
"captured_at" timestamp with time zone,
"capability_snapshot_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"evidence_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"evidence_digest" text,
"sync_job_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "repository_snapshots_state_check" CHECK ("repository_snapshots"."state" in ('collecting', 'complete', 'failed', 'cancelled'))
);
--> statement-breakpoint
CREATE TABLE "run_feedback" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"run_id" uuid NOT NULL,
"user_id" uuid NOT NULL,
"rating" text,
"notes" text DEFAULT '' NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "run_feedback_run_user_uq" UNIQUE("run_id","user_id"),
CONSTRAINT "run_feedback_rating_check" CHECK ("run_feedback"."rating" is null or "run_feedback"."rating" in ('helpful', 'mixed', 'unhelpful'))
);
--> statement-breakpoint
CREATE TABLE "users" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"email" text NOT NULL,
"display_name" text NOT NULL,
"password_hash" text NOT NULL,
"instance_role" text NOT NULL,
"status" text DEFAULT 'active' NOT NULL,
"password_changed_at" timestamp with time zone DEFAULT now() NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
"deleted_at" timestamp with time zone,
CONSTRAINT "users_instance_role_check" CHECK ("users"."instance_role" in ('instance_owner', 'instance_admin', 'user')),
CONSTRAINT "users_status_check" CHECK ("users"."status" in ('active', 'disabled', 'pending_deletion'))
);
--> statement-breakpoint
CREATE TABLE "workspace_memberships" (
"workspace_id" uuid NOT NULL,
"user_id" uuid NOT NULL,
"role" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "workspace_memberships_pkey" PRIMARY KEY("workspace_id","user_id"),
CONSTRAINT "workspace_memberships_role_check" CHECK ("workspace_memberships"."role" in ('owner', 'editor', 'viewer'))
);
--> statement-breakpoint
CREATE TABLE "workspaces" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text NOT NULL,
"type" text DEFAULT 'personal' NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
"deleted_at" timestamp with time zone,
CONSTRAINT "workspaces_type_check" CHECK ("workspaces"."type" in ('personal', 'team'))
);
--> statement-breakpoint
ALTER TABLE "audit_events" ADD CONSTRAINT "audit_events_actor_user_fk" FOREIGN KEY ("actor_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "audit_events" ADD CONSTRAINT "audit_events_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "auth_sessions" ADD CONSTRAINT "auth_sessions_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "collection_items" ADD CONSTRAINT "collection_items_collection_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "collection_items" ADD CONSTRAINT "collection_items_playbook_fk" FOREIGN KEY ("playbook_id") REFERENCES "public"."playbooks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "collections" ADD CONSTRAINT "collections_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "collections" ADD CONSTRAINT "collections_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_playbook_version_fk" FOREIGN KEY ("playbook_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_profile_revision_fk" FOREIGN KEY ("repository_profile_revision_id") REFERENCES "public"."repository_profile_revisions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD CONSTRAINT "evaluation_cases_playbook_version_fk" FOREIGN KEY ("playbook_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_case_fk" FOREIGN KEY ("evaluation_case_id") REFERENCES "public"."evaluation_cases"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_artifact_fk" FOREIGN KEY ("evidence_artifact_id") REFERENCES "public"."generated_artifacts"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_executed_by_fk" FOREIGN KEY ("executed_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_playbook_fk" FOREIGN KEY ("playbook_id") REFERENCES "public"."playbooks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "generated_artifacts" ADD CONSTRAINT "generated_artifacts_run_fk" FOREIGN KEY ("run_id") REFERENCES "public"."generated_runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_source_draft_fk" FOREIGN KEY ("source_draft_id") REFERENCES "public"."composition_drafts"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_playbook_version_fk" FOREIGN KEY ("playbook_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_generated_by_fk" FOREIGN KEY ("generated_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "instance_settings" ADD CONSTRAINT "instance_settings_owner_user_fk" FOREIGN KEY ("owner_user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_integration_fk" FOREIGN KEY ("integration_id") REFERENCES "public"."integrations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitations" ADD CONSTRAINT "invitations_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitations" ADD CONSTRAINT "invitations_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "jobs" ADD CONSTRAINT "jobs_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_playbook_fk" FOREIGN KEY ("playbook_id") REFERENCES "public"."playbooks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_supersedes_fk" FOREIGN KEY ("supersedes_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "playbooks" ADD CONSTRAINT "playbooks_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repositories" ADD CONSTRAINT "repositories_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repositories" ADD CONSTRAINT "repositories_integration_fk" FOREIGN KEY ("integration_id") REFERENCES "public"."integrations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_findings" ADD CONSTRAINT "repository_findings_snapshot_fk" FOREIGN KEY ("snapshot_id") REFERENCES "public"."repository_snapshots"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_profile_revisions" ADD CONSTRAINT "repository_profile_revisions_repository_fk" FOREIGN KEY ("repository_id") REFERENCES "public"."repositories"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_profile_revisions" ADD CONSTRAINT "repository_profile_revisions_snapshot_fk" FOREIGN KEY ("source_snapshot_id") REFERENCES "public"."repository_snapshots"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_profile_revisions" ADD CONSTRAINT "repository_profile_revisions_created_by_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_snapshots" ADD CONSTRAINT "repository_snapshots_repository_fk" FOREIGN KEY ("repository_id") REFERENCES "public"."repositories"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_snapshots" ADD CONSTRAINT "repository_snapshots_integration_fk" FOREIGN KEY ("integration_id") REFERENCES "public"."integrations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_snapshots" ADD CONSTRAINT "repository_snapshots_job_fk" FOREIGN KEY ("sync_job_id") REFERENCES "public"."jobs"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "run_feedback" ADD CONSTRAINT "run_feedback_run_fk" FOREIGN KEY ("run_id") REFERENCES "public"."generated_runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "run_feedback" ADD CONSTRAINT "run_feedback_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_memberships" ADD CONSTRAINT "workspace_memberships_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_memberships" ADD CONSTRAINT "workspace_memberships_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "audit_events_workspace_time_idx" ON "audit_events" USING btree ("workspace_id","occurred_at" DESC NULLS LAST);--> statement-breakpoint
CREATE INDEX "audit_events_action_time_idx" ON "audit_events" USING btree ("action","occurred_at" DESC NULLS LAST);--> statement-breakpoint
CREATE INDEX "auth_sessions_user_active_idx" ON "auth_sessions" USING btree ("user_id","absolute_expires_at") WHERE "auth_sessions"."revoked_at" is null;--> statement-breakpoint
CREATE INDEX "composition_drafts_workspace_updated_idx" ON "composition_drafts" USING btree ("workspace_id","updated_at" DESC NULLS LAST);--> statement-breakpoint
CREATE UNIQUE INDEX "generated_runs_digest_actor_uq" ON "generated_runs" USING btree ("workspace_id","generated_by","render_digest","generated_at");--> statement-breakpoint
CREATE INDEX "generated_runs_workspace_time_idx" ON "generated_runs" USING btree ("workspace_id","generated_at" DESC NULLS LAST);--> statement-breakpoint
CREATE UNIQUE INDEX "jobs_workspace_type_idempotency_uq" ON "jobs" USING btree ("workspace_id","type","idempotency_key") WHERE "jobs"."workspace_id" is not null and "jobs"."idempotency_key" is not null;--> statement-breakpoint
CREATE UNIQUE INDEX "jobs_global_type_idempotency_uq" ON "jobs" USING btree ("type","idempotency_key") WHERE "jobs"."workspace_id" is null and "jobs"."idempotency_key" is not null;--> statement-breakpoint
CREATE INDEX "jobs_claim_idx" ON "jobs" USING btree ("state","available_at","created_at") WHERE "jobs"."state" = 'queued';--> statement-breakpoint
CREATE INDEX "jobs_lease_idx" ON "jobs" USING btree ("state","lease_expires_at") WHERE "jobs"."state" = 'running';--> statement-breakpoint
CREATE INDEX "playbook_versions_search_idx" ON "playbook_versions" USING gin ("search_document");--> statement-breakpoint
CREATE INDEX "playbook_versions_filters_idx" ON "playbook_versions" USING btree ("category","risk_tier","lifecycle","published_at" DESC NULLS LAST);--> statement-breakpoint
CREATE INDEX "playbooks_workspace_idx" ON "playbooks" USING btree ("workspace_id");--> statement-breakpoint
CREATE UNIQUE INDEX "repositories_external_uq" ON "repositories" USING btree ("workspace_id","integration_id","external_id") WHERE "repositories"."external_id" is not null;--> statement-breakpoint
CREATE INDEX "repository_snapshots_repo_time_idx" ON "repository_snapshots" USING btree ("repository_id","captured_at" DESC NULLS LAST);--> statement-breakpoint
CREATE UNIQUE INDEX "users_email_ci_uq" ON "users" USING btree (lower("email")) WHERE "users"."deleted_at" is null;--> statement-breakpoint
CREATE INDEX "workspace_memberships_user_idx" ON "workspace_memberships" USING btree ("user_id");
--> statement-breakpoint
-- The singleton exists before setup so concurrent callers have a stable row to
-- inspect after taking the transaction-scoped advisory lock.
INSERT INTO "instance_settings" ("singleton") VALUES (true)
ON CONFLICT ("singleton") DO NOTHING;
--> statement-breakpoint
CREATE FUNCTION devrunbook_try_setup_advisory_lock()
RETURNS boolean
LANGUAGE sql
VOLATILE
PARALLEL UNSAFE
AS $$
SELECT pg_try_advisory_xact_lock(hashtextextended('devrunbook:first-run-setup', 0));
$$;
--> statement-breakpoint
COMMENT ON FUNCTION devrunbook_try_setup_advisory_lock() IS
'Acquire the transaction-scoped first-run setup lock; call inside the setup transaction.';
--> statement-breakpoint
CREATE FUNCTION devrunbook_reject_immutable_update()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
-- Allow PostgreSQL referential actions (for example ON DELETE SET NULL) to
-- preserve the deletion contract while rejecting direct application writes.
IF pg_trigger_depth() > 1 THEN
RETURN NEW;
END IF;
RAISE EXCEPTION USING
ERRCODE = '55000',
MESSAGE = format('%I is immutable', TG_TABLE_NAME);
END;
$$;
--> statement-breakpoint
CREATE FUNCTION devrunbook_reject_append_only_mutation()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF pg_trigger_depth() > 1 THEN
RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;
END IF;
RAISE EXCEPTION USING
ERRCODE = '55000',
MESSAGE = format('%I is append-only', TG_TABLE_NAME);
END;
$$;
--> statement-breakpoint
CREATE TRIGGER playbook_versions_published_immutable_trg
BEFORE UPDATE ON "playbook_versions"
FOR EACH ROW
WHEN (OLD."published_at" IS NOT NULL)
EXECUTE FUNCTION devrunbook_reject_immutable_update();
--> statement-breakpoint
CREATE TRIGGER repository_profile_revisions_immutable_trg
BEFORE UPDATE ON "repository_profile_revisions"
FOR EACH ROW
EXECUTE FUNCTION devrunbook_reject_immutable_update();
--> statement-breakpoint
CREATE TRIGGER repository_snapshots_complete_immutable_trg
BEFORE UPDATE ON "repository_snapshots"
FOR EACH ROW
WHEN (OLD."state" = 'complete')
EXECUTE FUNCTION devrunbook_reject_immutable_update();
--> statement-breakpoint
CREATE TRIGGER generated_runs_immutable_trg
BEFORE UPDATE ON "generated_runs"
FOR EACH ROW
EXECUTE FUNCTION devrunbook_reject_immutable_update();
--> statement-breakpoint
CREATE TRIGGER evaluation_results_immutable_trg
BEFORE UPDATE ON "evaluation_results"
FOR EACH ROW
EXECUTE FUNCTION devrunbook_reject_immutable_update();
--> statement-breakpoint
CREATE TRIGGER audit_events_append_only_trg
BEFORE UPDATE OR DELETE ON "audit_events"
FOR EACH ROW
EXECUTE FUNCTION devrunbook_reject_append_only_mutation();
@@ -0,0 +1,2 @@
ALTER TABLE "users" ADD COLUMN "email_verified" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "users" ADD COLUMN "image" text;
@@ -0,0 +1,3 @@
CREATE INDEX "repositories_workspace_updated_idx" ON "repositories" USING btree ("workspace_id","archived","updated_at" DESC NULLS LAST,"id");--> statement-breakpoint
ALTER TABLE "repository_profile_revisions" ADD CONSTRAINT "repository_profile_revisions_revision_positive_check" CHECK ("repository_profile_revisions"."revision_number" > 0);--> statement-breakpoint
ALTER TABLE "repository_profile_revisions" ADD CONSTRAINT "repository_profile_revisions_content_digest_check" CHECK ("repository_profile_revisions"."content_digest" ~ '^[0-9a-f]{64}$');
@@ -0,0 +1,11 @@
ALTER TABLE "composition_drafts" ADD COLUMN "policy_override_json" jsonb DEFAULT '{}'::jsonb NOT NULL;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD COLUMN "output_format" text DEFAULT 'prompt' NOT NULL;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD COLUMN "revision" integer DEFAULT 1 NOT NULL;--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_revision_positive_check" CHECK ("composition_drafts"."revision" > 0);--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_autonomy_check" CHECK ("composition_drafts"."autonomy_level" in ('observe', 'diagnose', 'plan', 'implement', 'verify', 'repair'));--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_work_mode_check" CHECK ("composition_drafts"."work_mode" in ('inspect', 'plan', 'guided', 'execute', 'recovery'));--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_output_format_check" CHECK ("composition_drafts"."output_format" in ('prompt', 'markdown', 'run-pack'));--> statement-breakpoint
ALTER TABLE "composition_drafts" ADD CONSTRAINT "composition_drafts_last_render_digest_check" CHECK ("composition_drafts"."last_render_digest" is null or "composition_drafts"."last_render_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_render_digest_check" CHECK ("generated_runs"."render_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "generated_runs" ALTER COLUMN "idempotency_key" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "generated_runs" ADD CONSTRAINT "generated_runs_idempotency_key_check" CHECK (length("generated_runs"."idempotency_key") between 1 and 255 and btrim("generated_runs"."idempotency_key") = "generated_runs"."idempotency_key");
@@ -0,0 +1,19 @@
ALTER TABLE "integrations" ADD COLUMN "allow_private_http" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "integrations" ADD COLUMN "request_timeout_ms" integer DEFAULT 15000 NOT NULL;--> statement-breakpoint
ALTER TABLE "integrations" ADD COLUMN "server_version" text;--> statement-breakpoint
ALTER TABLE "integrations" ADD COLUMN "remote_identity_id" text;--> statement-breakpoint
ALTER TABLE "integrations" ADD COLUMN "remote_identity_login" text;--> statement-breakpoint
ALTER TABLE "integrations" ADD COLUMN "health_code" text;--> statement-breakpoint
CREATE INDEX "integrations_workspace_status_idx" ON "integrations" USING btree ("workspace_id","status","updated_at" DESC NULLS LAST);--> statement-breakpoint
CREATE UNIQUE INDEX "repository_snapshots_sync_job_uq" ON "repository_snapshots" USING btree ("sync_job_id") WHERE "repository_snapshots"."sync_job_id" is not null;--> statement-breakpoint
CREATE INDEX "repository_snapshots_integration_state_idx" ON "repository_snapshots" USING btree ("integration_id","state","created_at" DESC NULLS LAST);--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_envelope_version_check" CHECK ("integration_secrets"."envelope_version" = 1);--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_key_version_check" CHECK (length(btrim("integration_secrets"."key_version")) between 1 and 64);--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_secret_kind_check" CHECK ("integration_secrets"."secret_kind" = 'access_token');--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_nonce_length_check" CHECK (octet_length("integration_secrets"."nonce") = 12);--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_auth_tag_length_check" CHECK (octet_length("integration_secrets"."auth_tag") = 16);--> statement-breakpoint
ALTER TABLE "integration_secrets" ADD CONSTRAINT "integration_secrets_last_four_check" CHECK ("integration_secrets"."last_four" is null or length("integration_secrets"."last_four") = 4);--> statement-breakpoint
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_request_timeout_check" CHECK ("integrations"."request_timeout_ms" between 1000 and 60000);--> statement-breakpoint
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_remote_identity_check" CHECK (("integrations"."remote_identity_id" is null) = ("integrations"."remote_identity_login" is null));--> statement-breakpoint
ALTER TABLE "integrations" ADD CONSTRAINT "integrations_health_code_check" CHECK ("integrations"."health_code" is null or "integrations"."health_code" in ('AUTH_INVALID', 'PERMISSION_MISSING', 'CAPABILITY_UNSUPPORTED', 'RATE_LIMITED', 'NETWORK_BLOCKED', 'TLS_ERROR', 'REMOTE_UNAVAILABLE', 'CONTENT_TOO_LARGE'));--> statement-breakpoint
ALTER TABLE "repository_snapshots" ADD CONSTRAINT "repository_snapshots_complete_integrity_check" CHECK ("repository_snapshots"."state" <> 'complete' or ("repository_snapshots"."captured_at" is not null and "repository_snapshots"."evidence_digest" ~ '^[0-9a-f]{64}$'));
@@ -0,0 +1,74 @@
CREATE TABLE "playbook_package_files" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"playbook_version_id" uuid NOT NULL,
"path" text NOT NULL,
"role" text NOT NULL,
"content" "bytea" NOT NULL,
"size_bytes" bigint NOT NULL,
"sha256" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "playbook_package_files_version_path_uq" UNIQUE("playbook_version_id","path"),
CONSTRAINT "playbook_package_files_path_check" CHECK (length("playbook_package_files"."path") between 1 and 512 and "playbook_package_files"."path" = btrim("playbook_package_files"."path") and "playbook_package_files"."path" !~ '(^/|\\|//|(^|/)\.\.?(/|$))'),
CONSTRAINT "playbook_package_files_role_check" CHECK ("playbook_package_files"."role" in ('manifest', 'template', 'partial', 'documentation', 'changelog', 'example', 'evaluation', 'resource', 'run-pack-resource')),
CONSTRAINT "playbook_package_files_size_check" CHECK ("playbook_package_files"."size_bytes" between 0 and 5242880 and octet_length("playbook_package_files"."content") = "playbook_package_files"."size_bytes"),
CONSTRAINT "playbook_package_files_sha256_check" CHECK ("playbook_package_files"."sha256" ~ '^[0-9a-f]{64}$' and encode(digest("playbook_package_files"."content", 'sha256'), 'hex') = "playbook_package_files"."sha256")
);
--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD COLUMN "draft_revision" integer DEFAULT 1 NOT NULL;--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD COLUMN "draft_digest" text DEFAULT repeat('0', 64) NOT NULL;--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD COLUMN "draft_validation_json" jsonb DEFAULT '{"valid":true,"issues":[]}'::jsonb NOT NULL;--> statement-breakpoint
DROP TRIGGER "playbook_versions_published_immutable_trg" ON "playbook_versions";--> statement-breakpoint
UPDATE "playbook_versions" SET "draft_digest" = "content_digest";--> statement-breakpoint
CREATE TRIGGER playbook_versions_published_immutable_trg
BEFORE UPDATE ON "playbook_versions"
FOR EACH ROW
WHEN (OLD."published_at" IS NOT NULL)
EXECUTE FUNCTION devrunbook_reject_immutable_update();--> statement-breakpoint
ALTER TABLE "playbook_package_files" ADD CONSTRAINT "playbook_package_files_version_fk" FOREIGN KEY ("playbook_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "playbook_package_files_version_idx" ON "playbook_package_files" USING btree ("playbook_version_id");--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_draft_revision_check" CHECK ("playbook_versions"."draft_revision" > 0);--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_draft_digest_check" CHECK ("playbook_versions"."draft_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "playbook_versions" ADD CONSTRAINT "playbook_versions_draft_validation_check" CHECK (jsonb_typeof("playbook_versions"."draft_validation_json") = 'object');--> statement-breakpoint
CREATE FUNCTION normalize_playbook_version_draft_digest() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
IF NEW.draft_digest = repeat('0', 64) THEN
NEW.draft_digest := NEW.content_digest;
END IF;
RETURN NEW;
END;
$$;--> statement-breakpoint
CREATE TRIGGER playbook_versions_normalize_draft_digest
BEFORE INSERT ON playbook_versions
FOR EACH ROW EXECUTE FUNCTION normalize_playbook_version_draft_digest();--> statement-breakpoint
CREATE FUNCTION reject_published_playbook_file_mutation() RETURNS trigger
LANGUAGE plpgsql AS $$
DECLARE
target_version_id uuid;
target_published_at timestamptz;
BEGIN
target_version_id := CASE WHEN TG_OP = 'DELETE' THEN OLD.playbook_version_id ELSE NEW.playbook_version_id END;
SELECT published_at INTO target_published_at
FROM playbook_versions
WHERE id = target_version_id
FOR SHARE;
IF target_published_at IS NOT NULL THEN
RAISE EXCEPTION 'published playbook package files are immutable'
USING ERRCODE = '55000';
END IF;
IF TG_OP = 'UPDATE' AND OLD.playbook_version_id <> NEW.playbook_version_id THEN
SELECT published_at INTO target_published_at
FROM playbook_versions
WHERE id = OLD.playbook_version_id
FOR SHARE;
IF target_published_at IS NOT NULL THEN
RAISE EXCEPTION 'published playbook package files are immutable'
USING ERRCODE = '55000';
END IF;
END IF;
RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;
END;
$$;--> statement-breakpoint
CREATE TRIGGER playbook_package_files_immutable_when_published
BEFORE INSERT OR UPDATE OR DELETE ON playbook_package_files
FOR EACH ROW EXECUTE FUNCTION reject_published_playbook_file_mutation();
@@ -0,0 +1,38 @@
CREATE TABLE "playbook_review_attestations" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"playbook_version_id" uuid NOT NULL,
"reviewed_by" uuid NOT NULL,
"attested_digest" text NOT NULL,
"schema_and_semantic_validation_passed" boolean NOT NULL,
"blocking_lint_finding_count" integer NOT NULL,
"limitations_documented" boolean NOT NULL,
"unresolved_safety_regression" boolean NOT NULL,
"review_json" jsonb DEFAULT '{}'::jsonb NOT NULL,
"reviewed_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "playbook_review_attestations_lint_count_check" CHECK ("playbook_review_attestations"."blocking_lint_finding_count" >= 0),
CONSTRAINT "playbook_review_attestations_digest_check" CHECK ("playbook_review_attestations"."attested_digest" ~ '^[0-9a-f]{64}$')
);
--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD COLUMN "case_version" text;--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD COLUMN "target_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD COLUMN "fixture_id" text;--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD COLUMN "fixture_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD COLUMN "environment_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD COLUMN "target_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD COLUMN "fixture_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD COLUMN "environment_digest" text;--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD COLUMN "result_json" jsonb;--> statement-breakpoint
ALTER TABLE "playbook_review_attestations" ADD CONSTRAINT "playbook_review_attestations_version_fk" FOREIGN KEY ("playbook_version_id") REFERENCES "public"."playbook_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "playbook_review_attestations" ADD CONSTRAINT "playbook_review_attestations_reviewer_fk" FOREIGN KEY ("reviewed_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "playbook_review_attestations_version_time_idx" ON "playbook_review_attestations" USING btree ("playbook_version_id","reviewed_at" DESC NULLS LAST);--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD CONSTRAINT "evaluation_cases_target_digest_check" CHECK ("evaluation_cases"."target_digest" is null or "evaluation_cases"."target_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD CONSTRAINT "evaluation_cases_fixture_digest_check" CHECK ("evaluation_cases"."fixture_digest" is null or "evaluation_cases"."fixture_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "evaluation_cases" ADD CONSTRAINT "evaluation_cases_environment_digest_check" CHECK ("evaluation_cases"."environment_digest" is null or "evaluation_cases"."environment_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_target_digest_check" CHECK ("evaluation_results"."target_digest" is null or "evaluation_results"."target_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_fixture_digest_check" CHECK ("evaluation_results"."fixture_digest" is null or "evaluation_results"."fixture_digest" ~ '^[0-9a-f]{64}$');--> statement-breakpoint
ALTER TABLE "evaluation_results" ADD CONSTRAINT "evaluation_results_environment_digest_check" CHECK ("evaluation_results"."environment_digest" is null or "evaluation_results"."environment_digest" ~ '^[0-9a-f]{64}$');
--> statement-breakpoint
CREATE TRIGGER playbook_review_attestations_immutable_trg
BEFORE UPDATE OR DELETE ON "playbook_review_attestations"
FOR EACH ROW
EXECUTE FUNCTION devrunbook_reject_append_only_mutation();
@@ -0,0 +1,5 @@
ALTER TABLE "collections" DROP CONSTRAINT "collections_workspace_name_uq";--> statement-breakpoint
ALTER TABLE "collections" ADD CONSTRAINT "collections_owner_name_uq" UNIQUE("workspace_id","created_by","name");--> statement-breakpoint
ALTER TABLE "collection_items" ADD CONSTRAINT "collection_items_position_check" CHECK ("collection_items"."position" >= 0);--> statement-breakpoint
ALTER TABLE "collections" ADD CONSTRAINT "collections_name_check" CHECK (char_length("collections"."name") between 1 and 80 and "collections"."name" = btrim("collections"."name") and "collections"."name" !~ '[[:cntrl:]]');--> statement-breakpoint
ALTER TABLE "collections" ADD CONSTRAINT "collections_description_check" CHECK (char_length("collections"."description") <= 500);
@@ -0,0 +1,15 @@
CREATE TABLE "repository_preferences" (
"workspace_id" uuid NOT NULL,
"user_id" uuid NOT NULL,
"repository_id" uuid NOT NULL,
"favorite" boolean DEFAULT false NOT NULL,
"last_used_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "repository_preferences_pkey" PRIMARY KEY("workspace_id","user_id","repository_id")
);
--> statement-breakpoint
ALTER TABLE "repository_preferences" ADD CONSTRAINT "repository_preferences_workspace_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_preferences" ADD CONSTRAINT "repository_preferences_user_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "repository_preferences" ADD CONSTRAINT "repository_preferences_repository_fk" FOREIGN KEY ("repository_id") REFERENCES "public"."repositories"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "repository_preferences_user_rank_idx" ON "repository_preferences" USING btree ("workspace_id","user_id","favorite","last_used_at" DESC NULLS LAST);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+69
View File
@@ -0,0 +1,69 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1785110204324,
"tag": "0000_jittery_wind_dancer",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1785111368997,
"tag": "0001_daily_mystique",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1785131801172,
"tag": "0002_wild_wraith",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1785137671077,
"tag": "0003_polite_kronos",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1785146174147,
"tag": "0004_gitea_persistence_hardening",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1785152317539,
"tag": "0005_luxuriant_changeling",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1785153820590,
"tag": "0006_worried_prodigy",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1785159158743,
"tag": "0007_lean_jack_power",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1785359005075,
"tag": "0008_third_menace",
"breakpoints": true
}
]
}