Files
dify/knowledge-fs/packages/database/migrations/0018_versioned_space_profiles.postgres.sql
Jyong 4ee43b8afc chore: migrate knowledge-fs source tree
Import the committed KnowledgeFS snapshot dc4072ee302317145612087ce7440851dc329fd0 under knowledge-fs/ without its Git history, local IDE settings, or build artifacts.
2026-07-20 04:54:20 -04:00

200 lines
8.0 KiB
SQL

-- Knowledge Platform schema migration
-- Migration id: 0018_versioned_space_profiles
-- Dialect: postgres
-- Profile snapshots are append-only. The small mutable state surface records activation outcome;
-- repository transitions never update snapshot, digest, capability, or model identity columns.
CREATE TABLE IF NOT EXISTS "knowledge_space_profile_revisions" (
"id" UUID PRIMARY KEY NOT NULL,
"tenant_id" VARCHAR(255) NOT NULL,
"knowledge_space_id" UUID NOT NULL,
"kind" VARCHAR(16) NOT NULL,
"revision" INTEGER NOT NULL,
"state" VARCHAR(16) NOT NULL,
"snapshot" JSONB NOT NULL,
"snapshot_digest" CHAR(64) NOT NULL,
"capability_snapshot" JSONB NOT NULL,
"capability_snapshot_digest" CHAR(64) NOT NULL,
"plugin_id" VARCHAR(256) NOT NULL,
"provider" VARCHAR(256) NOT NULL,
"model" VARCHAR(256) NOT NULL,
"vector_space_id" VARCHAR(87),
"dimension" INTEGER,
"created_by_subject_id" VARCHAR(255) NOT NULL,
"failure_code" VARCHAR(64),
"failure_message" TEXT,
"created_at" TIMESTAMPTZ NOT NULL,
"updated_at" TIMESTAMPTZ NOT NULL,
"activated_at" TIMESTAMPTZ,
"superseded_at" TIMESTAMPTZ,
"failed_at" TIMESTAMPTZ,
CONSTRAINT "knowledge_space_profile_revisions_scope_revision_uq"
UNIQUE ("tenant_id", "knowledge_space_id", "kind", "revision"),
CONSTRAINT "knowledge_space_profile_revisions_head_fk_uq"
UNIQUE ("tenant_id", "knowledge_space_id", "kind", "id", "revision"),
CONSTRAINT "knowledge_space_profile_revisions_attempt_fk_uq"
UNIQUE (
"tenant_id", "knowledge_space_id", "kind", "id", "revision", "snapshot_digest"
),
CONSTRAINT "knowledge_space_profile_revisions_kind_ck"
CHECK ("kind" IN ('embedding', 'retrieval')),
CONSTRAINT "knowledge_space_profile_revisions_state_ck"
CHECK ("state" IN ('candidate', 'active', 'superseded', 'failed')),
CONSTRAINT "knowledge_space_profile_revisions_positive_ck"
CHECK ("revision" >= 1 AND ("dimension" IS NULL OR "dimension" >= 1)),
CONSTRAINT "knowledge_space_profile_revisions_vector_shape_ck"
CHECK (
(
"kind" = 'embedding'
AND "vector_space_id" IS NOT NULL
AND "dimension" IS NOT NULL
AND "dimension" >= 1
)
OR ("kind" = 'retrieval' AND "vector_space_id" IS NULL AND "dimension" IS NULL)
),
CONSTRAINT "knowledge_space_profile_revisions_lifecycle_ck"
CHECK (
(
"state" = 'candidate'
AND "activated_at" IS NULL AND "superseded_at" IS NULL AND "failed_at" IS NULL
AND "failure_code" IS NULL AND "failure_message" IS NULL
)
OR (
"state" = 'active'
AND "activated_at" IS NOT NULL AND "superseded_at" IS NULL AND "failed_at" IS NULL
AND "failure_code" IS NULL AND "failure_message" IS NULL
)
OR (
"state" = 'superseded'
AND "activated_at" IS NOT NULL AND "superseded_at" IS NOT NULL AND "failed_at" IS NULL
AND "failure_code" IS NULL AND "failure_message" IS NULL
)
OR (
"state" = 'failed'
AND "activated_at" IS NULL AND "superseded_at" IS NULL AND "failed_at" IS NOT NULL
AND "failure_code" IS NOT NULL AND "failure_message" IS NOT NULL
)
),
FOREIGN KEY ("tenant_id", "knowledge_space_id")
REFERENCES "knowledge_spaces" ("tenant_id", "id") ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "knowledge_space_profile_revisions_scope_state_idx"
ON "knowledge_space_profile_revisions" (
"tenant_id", "knowledge_space_id", "kind", "state", "revision", "id"
);
-- The head is the only active-profile pointer. Activation is a CAS transaction that supersedes the
-- previous active revision, activates the candidate, and advances this row together.
CREATE TABLE IF NOT EXISTS "knowledge_space_profile_heads" (
"id" UUID PRIMARY KEY NOT NULL,
"tenant_id" VARCHAR(255) NOT NULL,
"knowledge_space_id" UUID NOT NULL,
"kind" VARCHAR(16) NOT NULL,
"profile_revision_id" UUID NOT NULL,
"active_revision" INTEGER NOT NULL,
"row_version" INTEGER NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL,
"updated_at" TIMESTAMPTZ NOT NULL,
CONSTRAINT "knowledge_space_profile_heads_kind_ck"
CHECK ("kind" IN ('embedding', 'retrieval')),
CONSTRAINT "knowledge_space_profile_heads_positive_ck"
CHECK ("active_revision" >= 1 AND "row_version" >= 1),
FOREIGN KEY ("tenant_id", "knowledge_space_id")
REFERENCES "knowledge_spaces" ("tenant_id", "id") ON DELETE CASCADE,
FOREIGN KEY (
"tenant_id", "knowledge_space_id", "kind", "profile_revision_id", "active_revision"
) REFERENCES "knowledge_space_profile_revisions" (
"tenant_id", "knowledge_space_id", "kind", "id", "revision"
) ON DELETE RESTRICT
);
CREATE UNIQUE INDEX IF NOT EXISTS "knowledge_space_profile_heads_scope_uq"
ON "knowledge_space_profile_heads" ("tenant_id", "knowledge_space_id", "kind");
-- Discovery writes immutable source snapshots into this durable ledger. Workers are fenced by both
-- lease token and row version, then revalidate the locked manifest before installing an initial
-- head. No unbounded or network-dependent backfill runs inside the schema migration.
CREATE TABLE IF NOT EXISTS "knowledge_space_profile_backfills" (
"id" UUID PRIMARY KEY NOT NULL,
"tenant_id" VARCHAR(255) NOT NULL,
"knowledge_space_id" UUID NOT NULL,
"kind" VARCHAR(16) NOT NULL,
"source_manifest_version" INTEGER NOT NULL,
"source_snapshot" JSONB NOT NULL,
"source_snapshot_digest" CHAR(64) NOT NULL,
"run_state" VARCHAR(16) NOT NULL,
"execution_attempts" INTEGER NOT NULL,
"max_execution_attempts" INTEGER NOT NULL,
"worker_id" VARCHAR(255),
"lease_token" UUID,
"lease_expires_at" TIMESTAMPTZ,
"heartbeat_at" TIMESTAMPTZ,
"row_version" INTEGER NOT NULL,
"last_error_code" VARCHAR(64),
"last_error_message" TEXT,
"created_at" TIMESTAMPTZ NOT NULL,
"updated_at" TIMESTAMPTZ NOT NULL,
"completed_at" TIMESTAMPTZ,
CONSTRAINT "knowledge_space_profile_backfills_kind_ck"
CHECK ("kind" IN ('embedding', 'retrieval')),
CONSTRAINT "knowledge_space_profile_backfills_state_ck"
CHECK ("run_state" IN ('queued', 'running', 'succeeded', 'failed')),
CONSTRAINT "knowledge_space_profile_backfills_positive_ck"
CHECK (
"source_manifest_version" >= 1
AND "execution_attempts" >= 0
AND "max_execution_attempts" >= 1
AND "execution_attempts" <= "max_execution_attempts"
AND "row_version" >= 1
),
CONSTRAINT "knowledge_space_profile_backfills_lease_ck"
CHECK (
(
"run_state" = 'running'
AND "worker_id" IS NOT NULL AND "lease_token" IS NOT NULL
AND "lease_expires_at" IS NOT NULL AND "heartbeat_at" IS NOT NULL
)
OR (
"run_state" <> 'running'
AND "worker_id" IS NULL AND "lease_token" IS NULL
AND "lease_expires_at" IS NULL AND "heartbeat_at" IS NULL
)
),
CONSTRAINT "knowledge_space_profile_backfills_lifecycle_ck"
CHECK (
(
"run_state" IN ('queued', 'running')
AND "completed_at" IS NULL
AND "last_error_code" IS NULL AND "last_error_message" IS NULL
)
OR (
"run_state" = 'succeeded'
AND "completed_at" IS NOT NULL
AND "last_error_code" IS NULL AND "last_error_message" IS NULL
)
OR (
"run_state" = 'failed'
AND "completed_at" IS NOT NULL
AND "last_error_code" IS NOT NULL AND "last_error_message" IS NOT NULL
)
),
CONSTRAINT "knowledge_space_profile_backfills_lease_token_ck"
CHECK (
"lease_token" IS NULL
OR "lease_token" <> '00000000-0000-0000-0000-000000000000'::uuid
),
FOREIGN KEY ("tenant_id", "knowledge_space_id")
REFERENCES "knowledge_spaces" ("tenant_id", "id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "knowledge_space_profile_backfills_source_uq"
ON "knowledge_space_profile_backfills" (
"tenant_id", "knowledge_space_id", "kind",
"source_manifest_version", "source_snapshot_digest"
);
CREATE INDEX IF NOT EXISTS "knowledge_space_profile_backfills_claim_idx"
ON "knowledge_space_profile_backfills" (
"run_state", "lease_expires_at", "updated_at", "id"
);