@phtngyn/cms 0.1.0-beta.5 → 0.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -5
- package/package.json +11 -1
- package/src/ApplicationTypes.d.ts +82 -0
- package/src/ApplicationTypes.js +1 -0
- package/src/{Configuration-CDMYfTre.js → Configuration-CjVUBBwa.js} +3 -3
- package/src/{Configuration-CDMYfTre.js.map → Configuration-CjVUBBwa.js.map} +1 -1
- package/src/Configuration.d.ts +9 -4
- package/src/Configuration.js.map +1 -1
- package/src/Content.d.ts +67 -0
- package/src/Content.js +291 -0
- package/src/Content.js.map +1 -0
- package/src/ContentTransfer-CRQet3QJ.d.ts +48 -0
- package/src/{ContentTransfer-C3Av9sWz.js → ContentTransfer-CTzGGKFV.js} +8 -4
- package/src/ContentTransfer-CTzGGKFV.js.map +1 -0
- package/src/{DocumentEngine-J7g-emdf.js → DocumentEngine-BbhfnTAc.js} +4 -4
- package/src/{DocumentEngine-J7g-emdf.js.map → DocumentEngine-BbhfnTAc.js.map} +1 -1
- package/src/DocumentModel.d.ts +8 -1
- package/src/DocumentModel.js +29 -2
- package/src/DocumentModel.js.map +1 -1
- package/src/{Forms-Dj6NuW66.js → Forms-02-p8qEw.js} +2 -2
- package/src/{Forms-Dj6NuW66.js.map → Forms-02-p8qEw.js.map} +1 -1
- package/src/{Forms-BsJMev5_.d.ts → Forms-BorTcIlp.d.ts} +2 -5
- package/src/Forms.d.ts +25 -14
- package/src/Forms.js.map +1 -1
- package/src/I18n-BXlVunfa.d.ts +27 -0
- package/src/I18n.d.ts +2 -20
- package/src/Module.js +14 -5
- package/src/Module.js.map +1 -1
- package/src/{S3MediaObjects-CpPSzJto.js → S3MediaObjects-DC0c8sYC.js} +54 -35
- package/src/{S3MediaObjects-CpPSzJto.js.map → S3MediaObjects-DC0c8sYC.js.map} +1 -1
- package/src/cli/content.js +63 -221
- package/src/cli/content.js.map +1 -1
- package/src/cli.js +93 -4
- package/src/cli.js.map +1 -1
- package/src/{connection-CBAy2qGy.js → connection-BPf4BQUZ.js} +2 -2
- package/src/{connection-CBAy2qGy.js.map → connection-BPf4BQUZ.js.map} +1 -1
- package/src/dev-lifecycle-vQLxwCFq.js +428 -0
- package/src/dev-lifecycle-vQLxwCFq.js.map +1 -0
- package/src/{installation-CNfIriVm.js → installation-DsGst1BH.js} +578 -457
- package/src/installation-DsGst1BH.js.map +1 -0
- package/src/internal/application-types.js +43 -0
- package/src/internal/application-types.js.map +1 -0
- package/src/internal/authoring-catalog.js +9 -4
- package/src/internal/authoring-catalog.js.map +1 -1
- package/src/internal/authoring-metadata.js +1 -1
- package/src/internal/configuration.js +10 -6
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/dev-lifecycle.js +3 -0
- package/src/internal/document-model.js +2 -2
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/i18n.js +21 -0
- package/src/internal/i18n.js.map +1 -1
- package/src/{location-BTqdfIzX.js → location-BgYhXEZp.js} +2 -2
- package/src/{location-BTqdfIzX.js.map → location-BgYhXEZp.js.map} +1 -1
- package/src/{models-Bah5B3bT.js → models-DgkGTFus.js} +6 -1
- package/src/models-DgkGTFus.js.map +1 -0
- package/src/{models-B4IoTmp7.js → models-k2nXyD6q.js} +2 -2
- package/src/{models-B4IoTmp7.js.map → models-k2nXyD6q.js.map} +1 -1
- package/src/runtime/delivery/context.js +1 -1
- package/src/runtime/delivery/plugin.js +27 -5
- package/src/runtime/delivery/plugin.js.map +1 -1
- package/src/runtime/delivery/preview.d.ts +1 -1
- package/src/runtime/delivery/types.d.ts +2 -85
- package/src/runtime/delivery/useCmsDocumentSeo.d.ts +8 -1
- package/src/runtime/delivery/useCmsDocumentSeo.js +19 -7
- package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -1
- package/src/runtime/delivery/useDocument.d.ts +2 -2
- package/src/runtime/delivery/useDocument.js.map +1 -1
- package/src/runtime/delivery/useDocumentQuery.d.ts +3 -3
- package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
- package/src/runtime/forms/document.js +1 -1
- package/src/runtime/forms/useCmsForm.js +81 -41
- package/src/runtime/forms/useCmsForm.js.map +1 -1
- package/src/runtime/i18n/useCmsI18n.d.ts +9 -7
- package/src/runtime/i18n/useCmsI18n.js +5 -4
- package/src/runtime/i18n/useCmsI18n.js.map +1 -1
- package/src/runtime/installation.js +2 -2
- package/src/runtime/plugin.js +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +2 -2
- package/src/runtime/preview/plugin.client.js +3 -3
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/sitemap.js +1 -1
- package/src/scalars-CA6kyipS.d.ts +7 -0
- package/src/{store-b2CSXgMt.js → store-BYgSt7E3.js} +3 -3
- package/src/{store-b2CSXgMt.js.map → store-BYgSt7E3.js.map} +1 -1
- package/src/types-DutFRtaG.d.ts +90 -0
- package/studio/{CreateDocumentDialog-GGey1uBc.js → CreateDocumentDialog-BdiM77bb.js} +1 -1
- package/studio/{documentPlanning-DRErYmBU.js → documentPlanning-B7fyUj9r.js} +7072 -7065
- package/studio/host.js +2 -2
- package/src/ContentTransfer-C3Av9sWz.js.map +0 -1
- package/src/installation-CNfIriVm.js.map +0 -1
- package/src/models-Bah5B3bT.js.map +0 -1
|
@@ -1,42 +1,548 @@
|
|
|
1
1
|
import { a as EditorNodeId, c as RevisionId, d as SourcePath, i as DocumentVersion, r as DocumentId, t as DocumentGeneration } from "./scalars-B2lgGUnj.js";
|
|
2
|
-
import {
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
5
|
-
import { $ as DocumentRevision, A as StudioBadRequest, B as User, C as DocumentStore, D as CurrentStudioRequest, E as defaultAccessControlLayer, F as studioInternalError, G as UserSelfRemovalDenied, H as UserAlreadyExists, I as InitializationAlreadyCompleted, J as CollaborationServerMessage, K as UserSelfRoleChangeDenied, L as InitializationProofInvalid, M as StudioRequestConflict, N as StudioSchemaError, O as StudioApi, P as StudioInternalError, Q as DocumentHistoryInvalidCursor, R as InitializationState, S as DocumentPersistenceError, T as AccessControl, U as UserNotFound, V as UserAdministrationDenied, W as UserPage, X as StateVector, Y as CollaborationTicket, Z as DocumentHistoryComparisonTooLarge, _ as Documents, a as mediaObjectPrefix, at as ActivityEntry, b as cursorCodec, c as Seo, ct as ActivityPage, d as seoDeliveryLayer, dt as DocumentMediaUnavailable, et as ACTIVITY_ACTIONS, f as seoLayer, ft as DocumentNotFound, g as DocumentPreviews, gt as PublishedDocumentNotFound, h as DocumentMaintenance, ht as DocumentVersionConflict, i as MediaObjectStore, it as ActivityCursorInvalid, k as StudioAuthentication, l as SeoDelivery, lt as ActivityTarget, m as SeoStore, mt as DocumentValidationFailed, n as s3MediaObjectStoreLayer, nt as ActivityContext, o as PreviewSeo, ot as ActivityEntryDraft, p as SeoPersistenceError, pt as DocumentPathConflict, q as CollaborationClientMessage, r as MediaPersistenceError, rt as ActivityCursor, s as PublishedSeo, st as ActivityId, tt as ActivityAction, u as makeDefaultSeoOptions, ut as ActivityTargetKind, v as PublishedDocuments, w as renderEditorMarkdown, x as DocumentGenerationConflict, y as documentsLayer, z as CreateUserInput } from "./S3MediaObjects-CpPSzJto.js";
|
|
2
|
+
import { $ as StudioActor, A as UnpublishDocumentInput, B as SeoMediaUnavailable, D as RemoveDocumentInput, Et as RequestId, H as SeoRevision, J as AccessDenied, K as SeoVersionConflict, O as RestoreDocumentInput, Q as Role, S as PublishDocumentInput, Y as AuthenticationRequired, _t as MediaReference, a as DOCUMENT_REVISION_ACTIONS, at as MediaCleanupReport, b as MarkdownNode, bt as MediaTooLarge, ct as MediaFolder, dt as MediaInvalid, et as StudioEntryDenied, ft as MediaName, ht as MediaPage, it as MediaByteSize, j as UpdateDocumentInput, k as UndeleteDocumentInput, l as DocumentMutationResult, lt as MediaId, m as DocumentSource, mt as MediaObjectKey, n as CmsMarkdownDocument, nt as ImageMimeType, o as DeletedDocument, ot as MediaConflict, p as DocumentRevisionAction, pt as MediaNotFound, rt as MediaAsset, st as MediaCursor, tt as StudioRequestContext, ut as MediaIntegrityReport, vt as MediaReferenced, x as MoveDocumentInput, xt as MediaUpload, y as DuplicateDocumentInput, yt as MediaStatus, z as SeoConfirmationRequired } from "./models-DgkGTFus.js";
|
|
3
|
+
import { $ as DocumentRevision, A as StudioBadRequest, B as User, C as DocumentStore, D as CurrentStudioRequest, E as defaultAccessControlLayer, F as studioInternalError, G as UserSelfRemovalDenied, H as UserAlreadyExists, I as InitializationAlreadyCompleted, J as CollaborationServerMessage, K as UserSelfRoleChangeDenied, L as InitializationProofInvalid, M as StudioRequestConflict, N as StudioSchemaError, O as StudioApi, P as StudioInternalError, Q as DocumentHistoryInvalidCursor, R as InitializationState, S as DocumentPersistenceError, T as AccessControl, U as UserNotFound, V as UserAdministrationDenied, W as UserPage, X as StateVector, Y as CollaborationTicket, Z as DocumentHistoryComparisonTooLarge, _ as Documents, a as mediaObjectPrefix, at as ActivityEntry, b as cursorCodec, c as Seo, ct as ActivityPage, d as seoDeliveryLayer, dt as DocumentMediaUnavailable, et as ACTIVITY_ACTIONS, f as seoLayer, ft as DocumentNotFound, g as DocumentPreviews, gt as PublishedDocumentNotFound, h as DocumentMaintenance, ht as DocumentVersionConflict, i as MediaObjectStore, it as ActivityCursorInvalid, k as StudioAuthentication, l as SeoDelivery, lt as ActivityTarget, m as SeoStore, mt as DocumentValidationFailed, n as s3MediaObjectStoreLayer, nt as ActivityContext, o as PreviewSeo, ot as ActivityEntryDraft, p as SeoPersistenceError, pt as DocumentPathConflict, q as CollaborationClientMessage, r as MediaPersistenceError, rt as ActivityCursor, s as PublishedSeo, st as ActivityId, tt as ActivityAction, u as makeDefaultSeoOptions, ut as ActivityTargetKind, v as PublishedDocuments, w as renderEditorMarkdown, x as DocumentGenerationConflict, y as documentsLayer, z as CreateUserInput } from "./S3MediaObjects-DC0c8sYC.js";
|
|
4
|
+
import { o as ContentTransferConflict } from "./ContentTransfer-CTzGGKFV.js";
|
|
6
5
|
import { a as CMS_FORM_SUBMIT_PATH, l as CMS_READINESS_PATH, o as CMS_LIVENESS_PATH, p as STUDIO_COLLABORATION_PATH, t as CMS_AUTHENTICATION_PATH, u as STUDIO_API_PATH } from "./HttpPaths-c9nLZ9H2.js";
|
|
6
|
+
import { i as FormResult, n as FORM_SUBMISSION_MAX_BYTES } from "./Forms-CfcI3tPU.js";
|
|
7
|
+
import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, i as validateFormValues, t as documentForms } from "./Forms-02-p8qEw.js";
|
|
7
8
|
import { a as createEditorNodeId, o as editorNodeId, r as identifiedAttributes, t as assertCanonicalEditorContent } from "./metadata-BEZPWh-3.js";
|
|
8
|
-
import { C as finiteNumberAttribute, S as compactJsonAttributes, _ as comarkTagForEditorMark, b as encodeEditorImageAttributes, g as EDITOR_MARK_TYPES, h as comarkToEditor, u as EditorDocumentInvalid, v as isEditorMark, w as nonEmptyStringAttribute, x as normalizeEditorImageLayout, y as EDITOR_IMAGE_LAYOUT_ATTRIBUTE } from "./Configuration-
|
|
9
|
-
import { o as ContentTransferConflict } from "./ContentTransfer-C3Av9sWz.js";
|
|
9
|
+
import { C as finiteNumberAttribute, S as compactJsonAttributes, _ as comarkTagForEditorMark, b as encodeEditorImageAttributes, g as EDITOR_MARK_TYPES, h as comarkToEditor, u as EditorDocumentInvalid, v as isEditorMark, w as nonEmptyStringAttribute, x as normalizeEditorImageLayout, y as EDITOR_IMAGE_LAYOUT_ATTRIBUTE } from "./Configuration-CjVUBBwa.js";
|
|
10
10
|
import { Cause, Clock, Context, Crypto, Data, DateTime, Deferred, Effect, Encoding, Exit, Fiber, Layer, Option, Predicate, PubSub, Pull, Queue, Redacted, Ref, Result, Schedule, Schema, Scope, Semaphore, Stream, flow } from "effect";
|
|
11
11
|
import { Extension, Node, getSchema, mergeAttributes } from "@tiptap/core";
|
|
12
12
|
import { prosemirrorJSONToYDoc, ySyncPluginKey, yXmlFragmentToProseMirrorRootNode } from "@tiptap/y-tiptap";
|
|
13
13
|
import { FindMyWay, HttpEffect, HttpMiddleware, HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse, Multipart } from "effect/unstable/http";
|
|
14
14
|
import { HttpApiBuilder, HttpApiMiddleware } from "effect/unstable/httpapi";
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
15
|
+
import { Pool } from "pg";
|
|
16
|
+
import { PgClient, PgPool } from "@effect/sql-pg";
|
|
17
|
+
import * as PgDrizzle from "drizzle-orm/effect-postgres";
|
|
18
|
+
import { migrate } from "drizzle-orm/pg-core/effect/session";
|
|
19
|
+
import { and, asc, count, desc, eq, gt, inArray, lt, lte, ne, or, sql } from "drizzle-orm";
|
|
20
|
+
import { alias, bigint, boolean, bytea, check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
|
|
21
|
+
import * as Client from "effect/unstable/sql/SqlClient";
|
|
22
|
+
import * as Statement from "effect/unstable/sql/Statement";
|
|
17
23
|
import { betterAuth } from "better-auth";
|
|
18
24
|
import { createAccessControl } from "better-auth/plugins/access";
|
|
19
25
|
import { admin } from "better-auth/plugins/admin";
|
|
20
26
|
import { defaultStatements } from "better-auth/plugins/admin/access";
|
|
27
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto";
|
|
28
|
+
import { createAuthMiddleware, getSessionFromCtx, isAPIError } from "better-auth/api";
|
|
21
29
|
import { Hocuspocus, IncomingMessage, MessageType, shouldSkipStoreHooks } from "@hocuspocus/server";
|
|
22
30
|
import StarterKit from "@tiptap/starter-kit";
|
|
23
31
|
import * as Y from "yjs";
|
|
24
32
|
import { Doc, applyUpdate, encodeStateAsUpdate, encodeStateVector } from "yjs";
|
|
25
33
|
import { RateLimiter } from "effect/unstable/persistence";
|
|
26
|
-
import { PgClient } from "@effect/sql-pg";
|
|
27
34
|
import { isDeepStrictEqual } from "node:util";
|
|
28
|
-
import { and, asc, count, desc, eq, gt, inArray, lt, lte, ne, or, sql } from "drizzle-orm";
|
|
29
|
-
import * as PgDrizzle from "drizzle-orm/effect-postgres";
|
|
30
35
|
import { createInsertSchema, createSelectSchema } from "drizzle-orm/effect-schema";
|
|
31
|
-
import { alias, bigint, boolean, bytea, check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
|
|
32
|
-
import { migrate } from "drizzle-orm/pg-core/effect/session";
|
|
33
36
|
import { EffectDrizzleQueryError } from "drizzle-orm/effect-core";
|
|
34
37
|
import * as Cause$1 from "effect/Cause";
|
|
35
38
|
import * as Option$1 from "effect/Option";
|
|
36
39
|
import * as SqlError from "effect/unstable/sql/SqlError";
|
|
37
40
|
import { Buffer } from "node:buffer";
|
|
38
|
-
import { Pool } from "pg";
|
|
39
41
|
|
|
42
|
+
//#region ../sql-pg/src/internal/database/embedded-migrations.generated.ts
|
|
43
|
+
const embeddedMigrations = [
|
|
44
|
+
{
|
|
45
|
+
sql: [
|
|
46
|
+
"CREATE TABLE \"activity_entries\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"action\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text NOT NULL,\n \"target_id\" text,\n \"details\" jsonb DEFAULT '{}' NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'user')),\n CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" <> 'media-library' AND \"target_id\" IS NOT NULL)),\n CONSTRAINT \"activity_entries_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"activity_entries_details_check\" CHECK (jsonb_typeof(\"details\") = 'object')\n);\n",
|
|
47
|
+
"\nCREATE TABLE \"auth_accounts\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"issuer\" text NOT NULL,\n \"account_id\" text NOT NULL,\n \"provider_id\" text NOT NULL,\n \"user_id\" uuid NOT NULL,\n \"access_token\" text,\n \"refresh_token\" text,\n \"id_token\" text,\n \"access_token_expires_at\" timestamp with time zone,\n \"refresh_token_expires_at\" timestamp with time zone,\n \"scope\" text,\n \"password\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
|
|
48
|
+
"\nCREATE TABLE \"auth_rate_limits\" (\n \"key\" text PRIMARY KEY,\n \"count\" bigint NOT NULL,\n \"last_request\" bigint NOT NULL\n);\n",
|
|
49
|
+
"\nCREATE TABLE \"auth_sessions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"expires_at\" timestamp with time zone NOT NULL,\n \"token\" text NOT NULL UNIQUE,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"ip_address\" text,\n \"user_agent\" text,\n \"user_id\" uuid NOT NULL,\n \"impersonated_by\" text\n);\n",
|
|
50
|
+
"\nCREATE TABLE \"auth_users\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"name\" text NOT NULL,\n \"email\" text NOT NULL UNIQUE,\n \"email_verified\" boolean DEFAULT false NOT NULL,\n \"image\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"role\" text DEFAULT 'editor' NOT NULL,\n \"banned\" boolean DEFAULT false NOT NULL,\n \"ban_reason\" text,\n \"ban_expires\" timestamp with time zone,\n \"cms_creation_change_id\" uuid UNIQUE,\n \"cms_sessions_revoked_change_id\" uuid UNIQUE,\n CONSTRAINT \"auth_users_role_check\" CHECK (\"role\" in ('administrator', 'editor', 'viewer'))\n);\n",
|
|
51
|
+
"\nCREATE TABLE \"auth_verifications\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"identifier\" text NOT NULL,\n \"value\" text NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
|
|
52
|
+
"\nCREATE TABLE \"change_receipts\" (\n \"change_id\" uuid PRIMARY KEY,\n \"fingerprint\" text NOT NULL,\n \"outcome\" text NOT NULL,\n \"activity_id\" uuid UNIQUE,\n \"completed_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"change_receipts_outcome_check\" CHECK ((\"outcome\" = 'applied' AND \"activity_id\" IS NOT NULL)\n OR (\"outcome\" = 'cancelled' AND \"activity_id\" IS NULL))\n);\n",
|
|
53
|
+
"\nCREATE TABLE \"cms_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"generation\" bigint DEFAULT 0 NOT NULL,\n CONSTRAINT \"cms_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"cms_state_generation_check\" CHECK (\"generation\" >= 0)\n);\n",
|
|
54
|
+
"\nCREATE TABLE \"document_heads\" (\n \"document_id\" uuid PRIMARY KEY,\n \"authored_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid\n);\n",
|
|
55
|
+
"\nCREATE TABLE \"document_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"object_key\" text NOT NULL,\n \"path\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"node_path\" integer[] NOT NULL,\n CONSTRAINT \"document_media_references_identity_unique\" UNIQUE(\"document_id\",\"source_path\",\"node_path\",\"object_key\"),\n CONSTRAINT \"document_media_references_object_key_check\" CHECK (char_length(\"object_key\") between 1 and 1024\n AND btrim(\"object_key\") = \"object_key\"\n AND \"object_key\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"object_key\") = 0),\n CONSTRAINT \"document_media_references_node_path_check\" CHECK (array_position(\"node_path\", NULL) IS NULL AND 0 <= ALL(\"node_path\"))\n);\n",
|
|
56
|
+
"\nCREATE TABLE \"document_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"action\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"markdown\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"activity_details\" jsonb DEFAULT '{}' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"document_revisions_document_id_unique\" UNIQUE(\"document_id\",\"id\"),\n CONSTRAINT \"document_revisions_action_check\" CHECK (\"action\" in ('document.create', 'document.move', 'document.remove', 'document.restore', 'document.undelete', 'document.update'))\n);\n",
|
|
57
|
+
"\nCREATE TABLE \"documents\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"source_path\" text NOT NULL,\n \"deleted_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL\n);\n",
|
|
58
|
+
"\nCREATE TABLE \"initialization_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"state\" text DEFAULT 'uninitialized' NOT NULL,\n \"change_id\" uuid,\n \"claim\" jsonb,\n CONSTRAINT \"initialization_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"initialization_state_state_check\" CHECK (\"state\" in ('uninitialized', 'claiming', 'ready')),\n CONSTRAINT \"initialization_state_claim_check\" CHECK ((\"state\" = 'claiming' AND \"change_id\" IS NOT NULL AND jsonb_typeof(\"claim\") = 'object')\n OR (\"state\" <> 'claiming' AND \"change_id\" IS NULL AND \"claim\" IS NULL))\n);\n",
|
|
59
|
+
"\nCREATE TABLE \"media_assets\" (\n \"id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text DEFAULT '' NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"status\" text DEFAULT 'uploading' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_assets_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_assets_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_assets_status_check\" CHECK (\"status\" in ('uploading', 'ready', 'deleting')),\n CONSTRAINT \"media_assets_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_assets_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_assets_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$')\n);\n",
|
|
60
|
+
"\nCREATE TABLE \"media_replacements\" (\n \"media_id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL,\n \"staging_object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"staged\" boolean DEFAULT false NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_replacements_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_replacements_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_replacements_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_replacements_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_replacements_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_staging_object_key_check\" CHECK (\"staging_object_key\" ~ '^media/replacements/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_distinct_object_keys_check\" CHECK (\"staging_object_key\" <> \"object_key\")\n);\n",
|
|
61
|
+
"\nCREATE TABLE \"pending_changes\" (\n \"id\" uuid PRIMARY KEY,\n \"action\" text NOT NULL,\n \"subject\" text NOT NULL,\n \"scope\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text,\n \"target_id\" text,\n \"intent\" jsonb NOT NULL,\n \"fingerprint\" text NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"pending_changes_scope_check\" CHECK (\"scope\" in ('initialization', 'media', 'users')),\n CONSTRAINT \"pending_changes_subject_check\" CHECK (char_length(\"subject\") between 1 and 1024 AND btrim(\"subject\") = \"subject\"),\n CONSTRAINT \"pending_changes_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"pending_changes_intent_check\" CHECK (jsonb_typeof(\"intent\") = 'object'),\n CONSTRAINT \"pending_changes_target_check\" CHECK ((\"target_kind\" IS NULL AND \"target_id\" IS NULL)\n OR (\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" in ('document', 'media', 'user')\n AND \"target_id\" IS NOT NULL))\n);\n",
|
|
62
|
+
"\nCREATE TABLE \"working_document_publish_attempts\" (\n \"id\" uuid PRIMARY KEY,\n \"activity\" jsonb NOT NULL,\n \"document_id\" uuid NOT NULL,\n \"expected_generation\" uuid NOT NULL,\n \"expected_version\" uuid NOT NULL,\n \"high_watermark\" bigint NOT NULL,\n \"markdown_hash\" text NOT NULL,\n \"state\" bytea NOT NULL,\n \"state_vector\" bytea NOT NULL,\n \"checkpoint_version\" uuid,\n \"phase\" text DEFAULT 'pending' NOT NULL,\n \"failure\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_publish_attempts_phase_check\" CHECK (\"phase\" in ('pending', 'checkpointed', 'published', 'failed')),\n CONSTRAINT \"working_document_publish_attempts_high_watermark_check\" CHECK (\"high_watermark\" between 0 and 9007199254740991),\n CONSTRAINT \"working_document_publish_attempts_markdown_hash_check\" CHECK (char_length(\"markdown_hash\") between 1 and 128),\n CONSTRAINT \"working_document_publish_attempts_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_document_publish_attempts_state_vector_check\" CHECK (octet_length(\"state_vector\") > 0),\n CONSTRAINT \"working_document_publish_attempts_payload_check\" CHECK ((\n \"phase\" = 'pending'\n AND \"checkpoint_version\" IS NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" in ('checkpointed', 'published')\n AND \"checkpoint_version\" IS NOT NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" = 'failed'\n AND \"checkpoint_version\" IS NULL\n AND char_length(\"failure\") between 1 and 128\n ))\n);\n",
|
|
63
|
+
"\nCREATE TABLE \"working_document_updates\" (\n \"document_id\" uuid,\n \"generation_id\" uuid NOT NULL,\n \"sequence\" bigint,\n \"update\" bytea NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_updates_pkey\" PRIMARY KEY(\"document_id\",\"sequence\"),\n CONSTRAINT \"working_document_updates_sequence_check\" CHECK (\"sequence\" between 1 and 9007199254740991),\n CONSTRAINT \"working_document_updates_update_check\" CHECK (octet_length(\"update\") > 0)\n);\n",
|
|
64
|
+
"\nCREATE TABLE \"working_documents\" (\n \"document_id\" uuid PRIMARY KEY,\n \"format_version\" integer NOT NULL,\n \"generation_id\" uuid NOT NULL,\n \"state\" bytea NOT NULL,\n \"saved_state_vector\" bytea NOT NULL,\n \"saved_version\" uuid NOT NULL,\n \"next_update_sequence\" bigint DEFAULT 1 NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_documents_generation_unique\" UNIQUE(\"document_id\",\"generation_id\"),\n CONSTRAINT \"working_documents_format_version_check\" CHECK (\"format_version\" = 1),\n CONSTRAINT \"working_documents_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_documents_saved_state_vector_check\" CHECK (octet_length(\"saved_state_vector\") > 0),\n CONSTRAINT \"working_documents_next_update_sequence_check\" CHECK (\"next_update_sequence\" between 1 and 9007199254740991)\n);\n",
|
|
65
|
+
"\nCREATE INDEX \"activity_entries_history\" ON \"activity_entries\" (\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
66
|
+
"\nCREATE INDEX \"activity_entries_actor\" ON \"activity_entries\" (\"actor_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
67
|
+
"\nCREATE INDEX \"activity_entries_target\" ON \"activity_entries\" (\"target_kind\",\"target_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
68
|
+
"\nCREATE INDEX \"activity_entries_request\" ON \"activity_entries\" (\"request_id\");",
|
|
69
|
+
"\nCREATE INDEX \"auth_accounts_user_id\" ON \"auth_accounts\" (\"user_id\");",
|
|
70
|
+
"\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"issuer\",\"account_id\");",
|
|
71
|
+
"\nCREATE INDEX \"auth_sessions_user_id\" ON \"auth_sessions\" (\"user_id\");",
|
|
72
|
+
"\nCREATE INDEX \"auth_verifications_identifier\" ON \"auth_verifications\" (\"identifier\");",
|
|
73
|
+
"\nCREATE INDEX \"change_receipts_activity\" ON \"change_receipts\" (\"activity_id\");",
|
|
74
|
+
"\nCREATE INDEX \"document_media_references_object_key\" ON \"document_media_references\" (\"object_key\");",
|
|
75
|
+
"\nCREATE INDEX \"document_revisions_history\" ON \"document_revisions\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
76
|
+
"\nCREATE UNIQUE INDEX \"documents_active_path\" ON \"documents\" (\"source_path\") WHERE \"deleted_at\" is null;",
|
|
77
|
+
"\nCREATE INDEX \"media_assets_catalog\" ON \"media_assets\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
|
|
78
|
+
"\nCREATE INDEX \"media_assets_folder\" ON \"media_assets\" (\"folder\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
|
|
79
|
+
"\nCREATE INDEX \"media_assets_recovery\" ON \"media_assets\" (\"updated_at\",\"id\") WHERE \"status\" <> 'ready';",
|
|
80
|
+
"\nCREATE INDEX \"media_replacements_recovery\" ON \"media_replacements\" (\"updated_at\",\"media_id\");",
|
|
81
|
+
"\nCREATE UNIQUE INDEX \"pending_changes_subject\" ON \"pending_changes\" (\"subject\");",
|
|
82
|
+
"\nCREATE INDEX \"pending_changes_recovery\" ON \"pending_changes\" (\"scope\",\"updated_at\",\"id\");",
|
|
83
|
+
"\nCREATE UNIQUE INDEX \"working_document_publish_attempts_active\" ON \"working_document_publish_attempts\" (\"document_id\") WHERE \"phase\" in ('pending', 'checkpointed');",
|
|
84
|
+
"\nCREATE INDEX \"working_document_publish_attempts_recovery\" ON \"working_document_publish_attempts\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
85
|
+
"\nALTER TABLE \"auth_accounts\" ADD CONSTRAINT \"auth_accounts_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
|
|
86
|
+
"\nALTER TABLE \"auth_sessions\" ADD CONSTRAINT \"auth_sessions_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
|
|
87
|
+
"\nALTER TABLE \"change_receipts\" ADD CONSTRAINT \"change_receipts_activity_id_activity_entries_id_fkey\" FOREIGN KEY (\"activity_id\") REFERENCES \"activity_entries\"(\"id\") ON DELETE RESTRICT;",
|
|
88
|
+
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
|
|
89
|
+
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_authored_revision_fkey\" FOREIGN KEY (\"document_id\",\"authored_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
90
|
+
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_published_revision_fkey\" FOREIGN KEY (\"document_id\",\"published_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
91
|
+
"\nALTER TABLE \"document_media_references\" ADD CONSTRAINT \"document_media_references_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
|
|
92
|
+
"\nALTER TABLE \"document_revisions\" ADD CONSTRAINT \"document_revisions_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
|
|
93
|
+
"\nALTER TABLE \"media_replacements\" ADD CONSTRAINT \"media_replacements_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
|
|
94
|
+
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"expected_generation\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
|
|
95
|
+
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_expected_version_fkey\" FOREIGN KEY (\"document_id\",\"expected_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
96
|
+
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_checkpoint_version_fkey\" FOREIGN KEY (\"document_id\",\"checkpoint_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
97
|
+
"\nALTER TABLE \"working_document_updates\" ADD CONSTRAINT \"working_document_updates_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"generation_id\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
|
|
98
|
+
"\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
|
|
99
|
+
"\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_saved_version_fkey\" FOREIGN KEY (\"document_id\",\"saved_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;"
|
|
100
|
+
],
|
|
101
|
+
bps: true,
|
|
102
|
+
folderMillis: 1788466567e3,
|
|
103
|
+
hash: "943a4996ef8c4324bd58280a80103e5a1632b088880164904b3857686e26f33e",
|
|
104
|
+
name: "20260903201607_cms_baseline"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
sql: [
|
|
108
|
+
"ALTER TABLE \"auth_rate_limits\" ADD COLUMN \"id\" uuid DEFAULT gen_random_uuid();",
|
|
109
|
+
"\nALTER TABLE \"auth_rate_limits\" DROP CONSTRAINT \"auth_rate_limits_pkey\";",
|
|
110
|
+
"\nALTER TABLE \"auth_rate_limits\" ADD PRIMARY KEY (\"id\");",
|
|
111
|
+
"\nALTER TABLE \"auth_rate_limits\" ADD CONSTRAINT \"auth_rate_limits_key_key\" UNIQUE(\"key\");"
|
|
112
|
+
],
|
|
113
|
+
bps: true,
|
|
114
|
+
folderMillis: 1788587191e3,
|
|
115
|
+
hash: "78b837c6b72a3de22d68e8db90bd211e61a0b97ff29bf8d16a0bba245eefa7ed",
|
|
116
|
+
name: "20260905054631_burly_northstar"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
sql: ["ALTER TABLE \"auth_accounts\" DROP COLUMN \"issuer\";", "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"provider_id\",\"account_id\");"],
|
|
120
|
+
bps: true,
|
|
121
|
+
folderMillis: 178875937e4,
|
|
122
|
+
hash: "e442485fa6c2d611e3dae508a12d245481bc5ec8f2dd4f5d853910df34484787",
|
|
123
|
+
name: "20260907053610_fancy_lady_deathstrike"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
sql: ["ALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));", "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"],
|
|
127
|
+
bps: true,
|
|
128
|
+
folderMillis: 1788866265e3,
|
|
129
|
+
hash: "24c56a37796caf8d76c0a97128a382b31e71808aa5b0ca7e5bac96795f9e16c7",
|
|
130
|
+
name: "20260908111745_classy_johnny_storm"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
sql: [
|
|
134
|
+
"CREATE TABLE \"seo_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"scope\" text NOT NULL,\n \"media_id\" uuid NOT NULL,\n CONSTRAINT \"seo_media_references_scope_media_unique\" UNIQUE(\"scope\",\"media_id\"),\n CONSTRAINT \"seo_media_references_scope_check\" CHECK (\"scope\" in ('working', 'published'))\n);\n",
|
|
135
|
+
"\nCREATE TABLE \"seo_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"settings\" jsonb NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"seo_revisions_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"seo_revisions_settings_check\" CHECK (jsonb_typeof(\"settings\") = 'object')\n);\n",
|
|
136
|
+
"\nCREATE TABLE \"seo_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"working_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid NOT NULL,\n CONSTRAINT \"seo_state_singleton_check\" CHECK (\"singleton\")\n);\n",
|
|
137
|
+
"\nCREATE INDEX \"seo_media_references_media\" ON \"seo_media_references\" (\"media_id\");",
|
|
138
|
+
"\nCREATE INDEX \"seo_revisions_history\" ON \"seo_revisions\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
139
|
+
"\nALTER TABLE \"seo_media_references\" ADD CONSTRAINT \"seo_media_references_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
|
|
140
|
+
"\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_working_revision_fkey\" FOREIGN KEY (\"working_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
|
|
141
|
+
"\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_published_revision_fkey\" FOREIGN KEY (\"published_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
|
|
142
|
+
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));",
|
|
143
|
+
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_kind_check\", ADD CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'seo', 'user'));",
|
|
144
|
+
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_check\", ADD CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" in ('media-library', 'seo') AND \"target_id\" IS NULL)\n OR (\"target_kind\" not in ('media-library', 'seo') AND \"target_id\" IS NOT NULL));",
|
|
145
|
+
"\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"
|
|
146
|
+
],
|
|
147
|
+
bps: true,
|
|
148
|
+
folderMillis: 1789233351e3,
|
|
149
|
+
hash: "8e6a6abf5385ab3ecf8eb083c1923ac9c74d72aa71bd1d444b7402d3e7e77000",
|
|
150
|
+
name: "20260912171551_charming_valkyrie"
|
|
151
|
+
}
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region ../sql-pg/src/internal/database/table-helpers.ts
|
|
156
|
+
const transactionTimestamp = sql`transaction_timestamp()`;
|
|
157
|
+
function isOneOf(column, values) {
|
|
158
|
+
return sql`${column} in (${sql.join(values.map((value) => sql`${value}`), sql`, `)})`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region ../sql-pg/src/internal/documents/tables.ts
|
|
163
|
+
const cmsState = pgTable("cms_state", {
|
|
164
|
+
singleton: boolean().default(true).primaryKey(),
|
|
165
|
+
generation: bigint({ mode: "bigint" }).default(sql`0`).notNull()
|
|
166
|
+
}, (table) => [check("cms_state_singleton_check", sql`${table.singleton}`), check("cms_state_generation_check", sql`${table.generation} >= 0`)]);
|
|
167
|
+
const documentsTable = pgTable("documents", {
|
|
168
|
+
id: uuid().defaultRandom().primaryKey(),
|
|
169
|
+
sourcePath: text("source_path").notNull(),
|
|
170
|
+
deletedAt: timestamp("deleted_at", {
|
|
171
|
+
mode: "string",
|
|
172
|
+
withTimezone: true
|
|
173
|
+
}),
|
|
174
|
+
createdAt: timestamp("created_at", {
|
|
175
|
+
mode: "string",
|
|
176
|
+
withTimezone: true
|
|
177
|
+
}).default(transactionTimestamp).notNull(),
|
|
178
|
+
updatedAt: timestamp("updated_at", {
|
|
179
|
+
mode: "string",
|
|
180
|
+
withTimezone: true
|
|
181
|
+
}).default(transactionTimestamp).notNull()
|
|
182
|
+
}, (table) => [uniqueIndex("documents_active_path").on(table.sourcePath).where(sql`${table.deletedAt} is null`)]);
|
|
183
|
+
const documentRevisions = pgTable("document_revisions", {
|
|
184
|
+
id: uuid().defaultRandom().primaryKey(),
|
|
185
|
+
documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "restrict" }),
|
|
186
|
+
action: text({ enum: DOCUMENT_REVISION_ACTIONS }).notNull(),
|
|
187
|
+
sourcePath: text("source_path").notNull(),
|
|
188
|
+
markdown: text().notNull(),
|
|
189
|
+
actorId: text("actor_id").notNull(),
|
|
190
|
+
actorEmail: text("actor_email").notNull(),
|
|
191
|
+
actorName: text("actor_name").notNull(),
|
|
192
|
+
actorRoles: jsonb("actor_roles").$type().notNull(),
|
|
193
|
+
requestId: uuid("request_id").notNull(),
|
|
194
|
+
reason: text(),
|
|
195
|
+
activityDetails: jsonb("activity_details").$type().default({}).notNull(),
|
|
196
|
+
createdAt: timestamp("created_at", {
|
|
197
|
+
mode: "string",
|
|
198
|
+
withTimezone: true
|
|
199
|
+
}).default(transactionTimestamp).notNull()
|
|
200
|
+
}, (table) => [
|
|
201
|
+
check("document_revisions_action_check", isOneOf(table.action, DOCUMENT_REVISION_ACTIONS)),
|
|
202
|
+
unique("document_revisions_document_id_unique").on(table.documentId, table.id),
|
|
203
|
+
index("document_revisions_history").on(table.documentId, table.createdAt.desc(), table.id.desc())
|
|
204
|
+
]);
|
|
205
|
+
const documentHeads = pgTable("document_heads", {
|
|
206
|
+
documentId: uuid("document_id").primaryKey().references(() => documentsTable.id, { onDelete: "restrict" }),
|
|
207
|
+
authoredRevisionId: uuid("authored_revision_id").notNull(),
|
|
208
|
+
publishedRevisionId: uuid("published_revision_id")
|
|
209
|
+
}, (table) => [foreignKey({
|
|
210
|
+
columns: [table.documentId, table.authoredRevisionId],
|
|
211
|
+
foreignColumns: [documentRevisions.documentId, documentRevisions.id],
|
|
212
|
+
name: "document_heads_authored_revision_fkey"
|
|
213
|
+
}).onDelete("restrict"), foreignKey({
|
|
214
|
+
columns: [table.documentId, table.publishedRevisionId],
|
|
215
|
+
foreignColumns: [documentRevisions.documentId, documentRevisions.id],
|
|
216
|
+
name: "document_heads_published_revision_fkey"
|
|
217
|
+
}).onDelete("restrict")]);
|
|
218
|
+
const documentMediaReferences = pgTable("document_media_references", {
|
|
219
|
+
id: uuid().defaultRandom().primaryKey(),
|
|
220
|
+
documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "cascade" }),
|
|
221
|
+
objectKey: text("object_key").notNull(),
|
|
222
|
+
path: text().notNull(),
|
|
223
|
+
sourcePath: text("source_path").notNull(),
|
|
224
|
+
nodePath: integer("node_path").array().notNull()
|
|
225
|
+
}, (table) => [
|
|
226
|
+
unique("document_media_references_identity_unique").on(table.documentId, table.sourcePath, table.nodePath, table.objectKey),
|
|
227
|
+
check("document_media_references_object_key_check", sql`char_length(${table.objectKey}) between 1 and 1024
|
|
228
|
+
AND btrim(${table.objectKey}) = ${table.objectKey}
|
|
229
|
+
AND ${table.objectKey} !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'
|
|
230
|
+
AND position(chr(92) in ${table.objectKey}) = 0`),
|
|
231
|
+
check("document_media_references_node_path_check", sql`array_position(${table.nodePath}, NULL) IS NULL AND 0 <= ALL(${table.nodePath})`),
|
|
232
|
+
index("document_media_references_object_key").on(table.objectKey)
|
|
233
|
+
]);
|
|
234
|
+
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region ../sql-pg/src/internal/initialization/tables.ts
|
|
237
|
+
const INITIALIZATION_STATES = [
|
|
238
|
+
"uninitialized",
|
|
239
|
+
"claiming",
|
|
240
|
+
"ready"
|
|
241
|
+
];
|
|
242
|
+
const initializationState = pgTable("initialization_state", {
|
|
243
|
+
singleton: boolean().default(true).primaryKey(),
|
|
244
|
+
state: text({ enum: INITIALIZATION_STATES }).default("uninitialized").notNull(),
|
|
245
|
+
changeId: uuid("change_id"),
|
|
246
|
+
claim: jsonb().$type()
|
|
247
|
+
}, (table) => [
|
|
248
|
+
check("initialization_state_singleton_check", sql`${table.singleton}`),
|
|
249
|
+
check("initialization_state_state_check", isOneOf(table.state, INITIALIZATION_STATES)),
|
|
250
|
+
check("initialization_state_claim_check", sql`(${table.state} = 'claiming' AND ${table.changeId} IS NOT NULL AND jsonb_typeof(${table.claim}) = 'object')
|
|
251
|
+
OR (${table.state} <> 'claiming' AND ${table.changeId} IS NULL AND ${table.claim} IS NULL)`)
|
|
252
|
+
]);
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region ../sql-pg/src/internal/database/migrations.ts
|
|
256
|
+
const MIGRATION_LOCK_KEY = "cms:database-migrations:v1";
|
|
257
|
+
const migrateCmsDatabase = Effect.fn("CmsDatabase.migrate")(function* (schema) {
|
|
258
|
+
const postgres = yield* PgClient.PgClient;
|
|
259
|
+
const database = yield* PgDrizzle.makeWithDefaults();
|
|
260
|
+
yield* postgres.withTransaction(Effect.gen(function* () {
|
|
261
|
+
yield* postgres.unsafe("select pg_advisory_xact_lock(hashtextextended($1, 0))", [MIGRATION_LOCK_KEY]);
|
|
262
|
+
yield* migrate(embeddedMigrations, database._.session, {
|
|
263
|
+
migrationsFolder: "embedded",
|
|
264
|
+
migrationsSchema: schema,
|
|
265
|
+
migrationsTable: "__drizzle_migrations"
|
|
266
|
+
});
|
|
267
|
+
yield* database.insert(cmsState).values({}).onConflictDoNothing({ target: cmsState.singleton });
|
|
268
|
+
yield* database.insert(initializationState).values({}).onConflictDoNothing({ target: initializationState.singleton });
|
|
269
|
+
}));
|
|
270
|
+
});
|
|
271
|
+
function cmsDatabaseMigrationLayer(schema) {
|
|
272
|
+
return Layer.effectDiscard(migrateCmsDatabase(schema));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region ../sql-pg/src/internal/postgres/scoped-client.ts
|
|
277
|
+
const PgJson = Statement.custom("PgJson");
|
|
278
|
+
/**
|
|
279
|
+
* Builds a PostgreSQL client whose every physical pool connection starts in
|
|
280
|
+
* the configured schema. The upstream driver does not yet expose PostgreSQL
|
|
281
|
+
* startup parameters, so the initialization belongs at our pool seam.
|
|
282
|
+
*/
|
|
283
|
+
const makeSchemaClient = Effect.fn("Postgres.makeSchemaClient")(function* (options, schema) {
|
|
284
|
+
const pool = yield* PgPool.make(options);
|
|
285
|
+
const initialized = /* @__PURE__ */ new WeakSet();
|
|
286
|
+
const searchPath = `set search_path to "${schema}"`;
|
|
287
|
+
const initialize = (connection) => initialized.has(connection) ? Effect.succeed(connection) : connection.query(searchPath).pipe(Effect.tap(() => Effect.sync(() => initialized.add(connection))), Effect.as(connection));
|
|
288
|
+
const acquirer = Effect.map(Effect.flatMap(pool.get, initialize), makeConnection);
|
|
289
|
+
const transactionAcquirer = Effect.map(Effect.flatMap(pool.reserve, initialize), makeConnection);
|
|
290
|
+
const listenAcquirer = Effect.flatMap(pool.reserve, initialize);
|
|
291
|
+
const borrower = (use) => pool.use((connection) => Effect.flatMap(initialize(connection), (ready) => use(makeConnection(ready))));
|
|
292
|
+
const compiler = PgClient.makeCompiler(options.transformQueryNames, options.transformJson);
|
|
293
|
+
const transformRows = options.transformResultNames ? Statement.defaultTransforms(options.transformResultNames, options.transformJson).array : void 0;
|
|
294
|
+
const listen = (channel) => Effect.flatMap(listenAcquirer, (connection) => connection.listen(channel));
|
|
295
|
+
const json = (value) => Statement.fragment([PgJson(value, void 0, void 0)]);
|
|
296
|
+
return Object.assign(yield* Client.make({
|
|
297
|
+
acquirer,
|
|
298
|
+
borrower,
|
|
299
|
+
compiler,
|
|
300
|
+
prepareTransactionControls: true,
|
|
301
|
+
spanAttributes: [
|
|
302
|
+
...options.spanAttributes ? Object.entries(options.spanAttributes) : [],
|
|
303
|
+
["db.system.name", "postgresql"],
|
|
304
|
+
["cms.database.schema", schema]
|
|
305
|
+
],
|
|
306
|
+
transactionAcquirer,
|
|
307
|
+
transformRows
|
|
308
|
+
}), {
|
|
309
|
+
[PgClient.TypeId]: PgClient.TypeId,
|
|
310
|
+
config: options,
|
|
311
|
+
json,
|
|
312
|
+
listen,
|
|
313
|
+
notify: (channel, payload) => Effect.asVoid(Effect.scoped(Effect.flatMap(acquirer, (connection) => connection.executeRaw("select pg_notify($1, $2)", [channel, payload]))))
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
var ConnectionImpl = class {
|
|
317
|
+
connection;
|
|
318
|
+
constructor(connection) {
|
|
319
|
+
this.connection = connection;
|
|
320
|
+
}
|
|
321
|
+
run(query, params, prepare = true) {
|
|
322
|
+
return Effect.map(this.connection.query(query, params, prepare), (result) => result.rows);
|
|
323
|
+
}
|
|
324
|
+
execute(sql, params, transformRows) {
|
|
325
|
+
const operation = this.run(sql, params);
|
|
326
|
+
return transformRows ? Effect.map(operation, transformRows) : operation;
|
|
327
|
+
}
|
|
328
|
+
executeRaw(sql, params) {
|
|
329
|
+
return this.connection.query(sql, params);
|
|
330
|
+
}
|
|
331
|
+
executeWithoutTransform(sql, params) {
|
|
332
|
+
return this.run(sql, params);
|
|
333
|
+
}
|
|
334
|
+
executeValues(sql, params) {
|
|
335
|
+
return this.connection.queryValues(sql, params);
|
|
336
|
+
}
|
|
337
|
+
executeValuesUnprepared(sql, params) {
|
|
338
|
+
return this.connection.queryValues(sql, params, false);
|
|
339
|
+
}
|
|
340
|
+
executeUnprepared(sql, params, transformRows) {
|
|
341
|
+
const operation = this.run(sql, params, false);
|
|
342
|
+
return transformRows ? Effect.map(operation, transformRows) : operation;
|
|
343
|
+
}
|
|
344
|
+
executeStream(sql, params, transformRows) {
|
|
345
|
+
const stream = this.connection.stream(sql, params);
|
|
346
|
+
if (!transformRows) return stream;
|
|
347
|
+
return Stream.mapArray(stream, (rows) => {
|
|
348
|
+
const transformed = transformRows(rows);
|
|
349
|
+
const first = transformed[0];
|
|
350
|
+
return first === void 0 ? rows : [first, ...transformed.slice(1)];
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
function makeConnection(connection) {
|
|
355
|
+
return new ConnectionImpl(connection);
|
|
356
|
+
}
|
|
357
|
+
function schemaClientLayer(options, schema) {
|
|
358
|
+
return PgClient.layerFrom(makeSchemaClient(options, schema));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region ../auth/src/internal/user.ts
|
|
363
|
+
const cmsUserCreationChangeField = "cmsCreationChangeId";
|
|
364
|
+
const cmsUserSessionsRevokedChangeField = "cmsSessionsRevokedChangeId";
|
|
365
|
+
const BetterAuthUser = Schema.Struct({
|
|
366
|
+
banned: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),
|
|
367
|
+
createdAt: Schema.Date,
|
|
368
|
+
email: Schema.String,
|
|
369
|
+
emailVerified: Schema.Boolean,
|
|
370
|
+
id: Schema.String,
|
|
371
|
+
name: Schema.String,
|
|
372
|
+
role: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
373
|
+
updatedAt: Schema.Date
|
|
374
|
+
});
|
|
375
|
+
const BetterAuthUserRecoveryEvidence = Schema.Struct({
|
|
376
|
+
[cmsUserCreationChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId))),
|
|
377
|
+
[cmsUserSessionsRevokedChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId)))
|
|
378
|
+
});
|
|
379
|
+
function decodeBetterAuthUser(value) {
|
|
380
|
+
return Schema.decodeEffect(BetterAuthUser)(value).pipe(Effect.flatMap((user) => Schema.decodeUnknownEffect(User)({
|
|
381
|
+
banned: user.banned === true,
|
|
382
|
+
createdAt: user.createdAt.toISOString(),
|
|
383
|
+
email: user.email,
|
|
384
|
+
emailVerified: user.emailVerified,
|
|
385
|
+
id: user.id,
|
|
386
|
+
name: user.name,
|
|
387
|
+
role: user.role,
|
|
388
|
+
updatedAt: user.updatedAt.toISOString()
|
|
389
|
+
})));
|
|
390
|
+
}
|
|
391
|
+
function decodeBetterAuthActor(user) {
|
|
392
|
+
return Schema.decodeEffect(StudioActor)(betterAuthActorInput(user));
|
|
393
|
+
}
|
|
394
|
+
function decodeBetterAuthActorOption(user) {
|
|
395
|
+
return Schema.decodeOption(StudioActor)(betterAuthActorInput(user));
|
|
396
|
+
}
|
|
397
|
+
function decodeBetterAuthUserCreationChangeId(user) {
|
|
398
|
+
return decodeChangeId(user, cmsUserCreationChangeField);
|
|
399
|
+
}
|
|
400
|
+
function decodeBetterAuthUserSessionsRevokedChangeId(user) {
|
|
401
|
+
return decodeChangeId(user, cmsUserSessionsRevokedChangeField);
|
|
402
|
+
}
|
|
403
|
+
function decodeChangeId(user, field) {
|
|
404
|
+
return Schema.decodeEffect(BetterAuthUserRecoveryEvidence)(user).pipe(Effect.map((evidence) => evidence[field] ?? null));
|
|
405
|
+
}
|
|
406
|
+
function betterAuthProviderRoles(value) {
|
|
407
|
+
return value ? [...new Set(value.split(",").map((role) => role.trim()).filter(Boolean))] : [];
|
|
408
|
+
}
|
|
409
|
+
function betterAuthActorInput(user) {
|
|
410
|
+
return {
|
|
411
|
+
email: user.email,
|
|
412
|
+
id: user.id,
|
|
413
|
+
name: user.name,
|
|
414
|
+
roles: betterAuthProviderRoles(user.role)
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
//#endregion
|
|
419
|
+
//#region ../auth/src/internal/better-auth.ts
|
|
420
|
+
const cmsBetterAuthAccess = createAccessControl(defaultStatements);
|
|
421
|
+
const cmsBetterAuthRoles = {
|
|
422
|
+
administrator: cmsBetterAuthAccess.newRole({
|
|
423
|
+
session: ["list", "revoke"],
|
|
424
|
+
user: [
|
|
425
|
+
"create",
|
|
426
|
+
"list",
|
|
427
|
+
"get",
|
|
428
|
+
"set-role",
|
|
429
|
+
"delete",
|
|
430
|
+
"update"
|
|
431
|
+
]
|
|
432
|
+
}),
|
|
433
|
+
editor: cmsBetterAuthAccess.newRole({
|
|
434
|
+
session: [],
|
|
435
|
+
user: []
|
|
436
|
+
}),
|
|
437
|
+
viewer: cmsBetterAuthAccess.newRole({
|
|
438
|
+
session: [],
|
|
439
|
+
user: []
|
|
440
|
+
})
|
|
441
|
+
};
|
|
442
|
+
const timestampFields = {
|
|
443
|
+
createdAt: "created_at",
|
|
444
|
+
updatedAt: "updated_at"
|
|
445
|
+
};
|
|
446
|
+
function createCmsBetterAuthOptions(options, activity) {
|
|
447
|
+
return {
|
|
448
|
+
advanced: { database: {
|
|
449
|
+
generateId: "uuid",
|
|
450
|
+
joins: true
|
|
451
|
+
} },
|
|
452
|
+
appName: "CMS Studio",
|
|
453
|
+
basePath: options.basePath ?? "/api/cms/auth",
|
|
454
|
+
baseURL: options.baseURL,
|
|
455
|
+
database: options.database,
|
|
456
|
+
emailAndPassword: {
|
|
457
|
+
disableSignUp: true,
|
|
458
|
+
enabled: true,
|
|
459
|
+
...activity?.emailAndPassword
|
|
460
|
+
},
|
|
461
|
+
hooks: activity?.hooks,
|
|
462
|
+
user: {
|
|
463
|
+
additionalFields: {
|
|
464
|
+
[cmsUserCreationChangeField]: hiddenChangeField("cms_creation_change_id"),
|
|
465
|
+
[cmsUserSessionsRevokedChangeField]: hiddenChangeField("cms_sessions_revoked_change_id")
|
|
466
|
+
},
|
|
467
|
+
modelName: "auth_users",
|
|
468
|
+
fields: {
|
|
469
|
+
...timestampFields,
|
|
470
|
+
emailVerified: "email_verified"
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
session: {
|
|
474
|
+
cookieCache: {
|
|
475
|
+
enabled: false,
|
|
476
|
+
strategy: "jwt"
|
|
477
|
+
},
|
|
478
|
+
modelName: "auth_sessions",
|
|
479
|
+
fields: {
|
|
480
|
+
...timestampFields,
|
|
481
|
+
expiresAt: "expires_at",
|
|
482
|
+
ipAddress: "ip_address",
|
|
483
|
+
userAgent: "user_agent",
|
|
484
|
+
userId: "user_id"
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
account: {
|
|
488
|
+
modelName: "auth_accounts",
|
|
489
|
+
fields: {
|
|
490
|
+
accessToken: "access_token",
|
|
491
|
+
accessTokenExpiresAt: "access_token_expires_at",
|
|
492
|
+
accountId: "account_id",
|
|
493
|
+
...timestampFields,
|
|
494
|
+
idToken: "id_token",
|
|
495
|
+
providerId: "provider_id",
|
|
496
|
+
refreshToken: "refresh_token",
|
|
497
|
+
refreshTokenExpiresAt: "refresh_token_expires_at",
|
|
498
|
+
userId: "user_id"
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
verification: {
|
|
502
|
+
modelName: "auth_verifications",
|
|
503
|
+
fields: {
|
|
504
|
+
...timestampFields,
|
|
505
|
+
expiresAt: "expires_at"
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
rateLimit: {
|
|
509
|
+
enabled: true,
|
|
510
|
+
storage: "database",
|
|
511
|
+
modelName: "auth_rate_limits",
|
|
512
|
+
fields: { lastRequest: "last_request" }
|
|
513
|
+
},
|
|
514
|
+
plugins: [admin({
|
|
515
|
+
ac: cmsBetterAuthAccess,
|
|
516
|
+
adminRoles: ["administrator"],
|
|
517
|
+
defaultRole: "editor",
|
|
518
|
+
roles: cmsBetterAuthRoles,
|
|
519
|
+
schema: {
|
|
520
|
+
session: { fields: { impersonatedBy: "impersonated_by" } },
|
|
521
|
+
user: { fields: {
|
|
522
|
+
banExpires: "ban_expires",
|
|
523
|
+
banReason: "ban_reason",
|
|
524
|
+
banned: "banned",
|
|
525
|
+
role: "role"
|
|
526
|
+
} }
|
|
527
|
+
}
|
|
528
|
+
})],
|
|
529
|
+
secret: options.secret
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function createCmsBetterAuth(options, activity) {
|
|
533
|
+
return betterAuth(createCmsBetterAuthOptions(options, activity));
|
|
534
|
+
}
|
|
535
|
+
function hiddenChangeField(fieldName) {
|
|
536
|
+
return {
|
|
537
|
+
fieldName,
|
|
538
|
+
input: false,
|
|
539
|
+
required: false,
|
|
540
|
+
returned: false,
|
|
541
|
+
type: "string"
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
//#endregion
|
|
40
546
|
//#region ../server/src/internal/activity/activity-storage.ts
|
|
41
547
|
var ActivityStore = class extends Context.Service()("@internal/server/ActivityStore") {};
|
|
42
548
|
|
|
@@ -683,63 +1189,6 @@ function appliedResolution(change, intent, userId) {
|
|
|
683
1189
|
};
|
|
684
1190
|
}
|
|
685
1191
|
|
|
686
|
-
//#endregion
|
|
687
|
-
//#region ../auth/src/internal/user.ts
|
|
688
|
-
const cmsUserCreationChangeField = "cmsCreationChangeId";
|
|
689
|
-
const cmsUserSessionsRevokedChangeField = "cmsSessionsRevokedChangeId";
|
|
690
|
-
const BetterAuthUser = Schema.Struct({
|
|
691
|
-
banned: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),
|
|
692
|
-
createdAt: Schema.Date,
|
|
693
|
-
email: Schema.String,
|
|
694
|
-
emailVerified: Schema.Boolean,
|
|
695
|
-
id: Schema.String,
|
|
696
|
-
name: Schema.String,
|
|
697
|
-
role: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
698
|
-
updatedAt: Schema.Date
|
|
699
|
-
});
|
|
700
|
-
const BetterAuthUserRecoveryEvidence = Schema.Struct({
|
|
701
|
-
[cmsUserCreationChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId))),
|
|
702
|
-
[cmsUserSessionsRevokedChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId)))
|
|
703
|
-
});
|
|
704
|
-
function decodeBetterAuthUser(value) {
|
|
705
|
-
return Schema.decodeEffect(BetterAuthUser)(value).pipe(Effect.flatMap((user) => Schema.decodeUnknownEffect(User)({
|
|
706
|
-
banned: user.banned === true,
|
|
707
|
-
createdAt: user.createdAt.toISOString(),
|
|
708
|
-
email: user.email,
|
|
709
|
-
emailVerified: user.emailVerified,
|
|
710
|
-
id: user.id,
|
|
711
|
-
name: user.name,
|
|
712
|
-
role: user.role,
|
|
713
|
-
updatedAt: user.updatedAt.toISOString()
|
|
714
|
-
})));
|
|
715
|
-
}
|
|
716
|
-
function decodeBetterAuthActor(user) {
|
|
717
|
-
return Schema.decodeEffect(StudioActor)(betterAuthActorInput(user));
|
|
718
|
-
}
|
|
719
|
-
function decodeBetterAuthActorOption(user) {
|
|
720
|
-
return Schema.decodeOption(StudioActor)(betterAuthActorInput(user));
|
|
721
|
-
}
|
|
722
|
-
function decodeBetterAuthUserCreationChangeId(user) {
|
|
723
|
-
return decodeChangeId(user, cmsUserCreationChangeField);
|
|
724
|
-
}
|
|
725
|
-
function decodeBetterAuthUserSessionsRevokedChangeId(user) {
|
|
726
|
-
return decodeChangeId(user, cmsUserSessionsRevokedChangeField);
|
|
727
|
-
}
|
|
728
|
-
function decodeChangeId(user, field) {
|
|
729
|
-
return Schema.decodeEffect(BetterAuthUserRecoveryEvidence)(user).pipe(Effect.map((evidence) => evidence[field] ?? null));
|
|
730
|
-
}
|
|
731
|
-
function betterAuthProviderRoles(value) {
|
|
732
|
-
return value ? [...new Set(value.split(",").map((role) => role.trim()).filter(Boolean))] : [];
|
|
733
|
-
}
|
|
734
|
-
function betterAuthActorInput(user) {
|
|
735
|
-
return {
|
|
736
|
-
email: user.email,
|
|
737
|
-
id: user.id,
|
|
738
|
-
name: user.name,
|
|
739
|
-
roles: betterAuthProviderRoles(user.role)
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
|
|
743
1192
|
//#endregion
|
|
744
1193
|
//#region ../auth/src/internal/activity-hooks.ts
|
|
745
1194
|
function betterAuthActivityWriter(storage, crypto) {
|
|
@@ -776,156 +1225,29 @@ function betterAuthActivityOptions(writeActivity, crypto, runPromise) {
|
|
|
776
1225
|
if (context.path === "/sign-out") return write("authentication.signed-out", actor);
|
|
777
1226
|
if (context.path === "/change-password") return write("authentication.password.changed", actor);
|
|
778
1227
|
return Promise.resolve();
|
|
779
|
-
}),
|
|
780
|
-
before
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
function activityDraft(action, actor, requestId) {
|
|
785
|
-
return ActivityEntryDraft.make({
|
|
786
|
-
action,
|
|
787
|
-
context: {
|
|
788
|
-
actor,
|
|
789
|
-
requestId: RequestId.make(requestId)
|
|
790
|
-
},
|
|
791
|
-
details: {},
|
|
792
|
-
target: {
|
|
793
|
-
kind: "user",
|
|
794
|
-
userId: actor.id
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
function decodeActor(user) {
|
|
799
|
-
const option = decodeBetterAuthActorOption(user);
|
|
800
|
-
return Option.getOrUndefined(option);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
//#endregion
|
|
804
|
-
//#region ../auth/src/internal/better-auth.ts
|
|
805
|
-
const cmsBetterAuthAccess = createAccessControl(defaultStatements);
|
|
806
|
-
const cmsBetterAuthRoles = {
|
|
807
|
-
administrator: cmsBetterAuthAccess.newRole({
|
|
808
|
-
session: ["list", "revoke"],
|
|
809
|
-
user: [
|
|
810
|
-
"create",
|
|
811
|
-
"list",
|
|
812
|
-
"get",
|
|
813
|
-
"set-role",
|
|
814
|
-
"delete",
|
|
815
|
-
"update"
|
|
816
|
-
]
|
|
817
|
-
}),
|
|
818
|
-
editor: cmsBetterAuthAccess.newRole({
|
|
819
|
-
session: [],
|
|
820
|
-
user: []
|
|
821
|
-
}),
|
|
822
|
-
viewer: cmsBetterAuthAccess.newRole({
|
|
823
|
-
session: [],
|
|
824
|
-
user: []
|
|
825
|
-
})
|
|
826
|
-
};
|
|
827
|
-
const timestampFields = {
|
|
828
|
-
createdAt: "created_at",
|
|
829
|
-
updatedAt: "updated_at"
|
|
830
|
-
};
|
|
831
|
-
function createCmsBetterAuthOptions(options, activity) {
|
|
832
|
-
return {
|
|
833
|
-
advanced: { database: {
|
|
834
|
-
generateId: "uuid",
|
|
835
|
-
joins: true
|
|
836
|
-
} },
|
|
837
|
-
appName: "CMS Studio",
|
|
838
|
-
basePath: options.basePath ?? "/api/cms/auth",
|
|
839
|
-
baseURL: options.baseURL,
|
|
840
|
-
database: options.database,
|
|
841
|
-
emailAndPassword: {
|
|
842
|
-
disableSignUp: true,
|
|
843
|
-
enabled: true,
|
|
844
|
-
...activity?.emailAndPassword
|
|
845
|
-
},
|
|
846
|
-
hooks: activity?.hooks,
|
|
847
|
-
user: {
|
|
848
|
-
additionalFields: {
|
|
849
|
-
[cmsUserCreationChangeField]: hiddenChangeField("cms_creation_change_id"),
|
|
850
|
-
[cmsUserSessionsRevokedChangeField]: hiddenChangeField("cms_sessions_revoked_change_id")
|
|
851
|
-
},
|
|
852
|
-
modelName: "auth_users",
|
|
853
|
-
fields: {
|
|
854
|
-
...timestampFields,
|
|
855
|
-
emailVerified: "email_verified"
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
|
-
session: {
|
|
859
|
-
cookieCache: {
|
|
860
|
-
enabled: false,
|
|
861
|
-
strategy: "jwt"
|
|
862
|
-
},
|
|
863
|
-
modelName: "auth_sessions",
|
|
864
|
-
fields: {
|
|
865
|
-
...timestampFields,
|
|
866
|
-
expiresAt: "expires_at",
|
|
867
|
-
ipAddress: "ip_address",
|
|
868
|
-
userAgent: "user_agent",
|
|
869
|
-
userId: "user_id"
|
|
870
|
-
}
|
|
871
|
-
},
|
|
872
|
-
account: {
|
|
873
|
-
modelName: "auth_accounts",
|
|
874
|
-
fields: {
|
|
875
|
-
accessToken: "access_token",
|
|
876
|
-
accessTokenExpiresAt: "access_token_expires_at",
|
|
877
|
-
accountId: "account_id",
|
|
878
|
-
...timestampFields,
|
|
879
|
-
idToken: "id_token",
|
|
880
|
-
providerId: "provider_id",
|
|
881
|
-
refreshToken: "refresh_token",
|
|
882
|
-
refreshTokenExpiresAt: "refresh_token_expires_at",
|
|
883
|
-
userId: "user_id"
|
|
884
|
-
}
|
|
885
|
-
},
|
|
886
|
-
verification: {
|
|
887
|
-
modelName: "auth_verifications",
|
|
888
|
-
fields: {
|
|
889
|
-
...timestampFields,
|
|
890
|
-
expiresAt: "expires_at"
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
rateLimit: {
|
|
894
|
-
enabled: true,
|
|
895
|
-
storage: "database",
|
|
896
|
-
modelName: "auth_rate_limits",
|
|
897
|
-
fields: { lastRequest: "last_request" }
|
|
898
|
-
},
|
|
899
|
-
plugins: [admin({
|
|
900
|
-
ac: cmsBetterAuthAccess,
|
|
901
|
-
adminRoles: ["administrator"],
|
|
902
|
-
defaultRole: "editor",
|
|
903
|
-
roles: cmsBetterAuthRoles,
|
|
904
|
-
schema: {
|
|
905
|
-
session: { fields: { impersonatedBy: "impersonated_by" } },
|
|
906
|
-
user: { fields: {
|
|
907
|
-
banExpires: "ban_expires",
|
|
908
|
-
banReason: "ban_reason",
|
|
909
|
-
banned: "banned",
|
|
910
|
-
role: "role"
|
|
911
|
-
} }
|
|
912
|
-
}
|
|
913
|
-
})],
|
|
914
|
-
secret: options.secret
|
|
915
|
-
};
|
|
916
|
-
}
|
|
917
|
-
function createCmsBetterAuth(options, activity) {
|
|
918
|
-
return betterAuth(createCmsBetterAuthOptions(options, activity));
|
|
919
|
-
}
|
|
920
|
-
function hiddenChangeField(fieldName) {
|
|
921
|
-
return {
|
|
922
|
-
fieldName,
|
|
923
|
-
input: false,
|
|
924
|
-
required: false,
|
|
925
|
-
returned: false,
|
|
926
|
-
type: "string"
|
|
1228
|
+
}),
|
|
1229
|
+
before
|
|
1230
|
+
}
|
|
927
1231
|
};
|
|
928
1232
|
}
|
|
1233
|
+
function activityDraft(action, actor, requestId) {
|
|
1234
|
+
return ActivityEntryDraft.make({
|
|
1235
|
+
action,
|
|
1236
|
+
context: {
|
|
1237
|
+
actor,
|
|
1238
|
+
requestId: RequestId.make(requestId)
|
|
1239
|
+
},
|
|
1240
|
+
details: {},
|
|
1241
|
+
target: {
|
|
1242
|
+
kind: "user",
|
|
1243
|
+
userId: actor.id
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
function decodeActor(user) {
|
|
1248
|
+
const option = decodeBetterAuthActorOption(user);
|
|
1249
|
+
return Option.getOrUndefined(option);
|
|
1250
|
+
}
|
|
929
1251
|
|
|
930
1252
|
//#endregion
|
|
931
1253
|
//#region ../auth/src/internal/handler.ts
|
|
@@ -5398,13 +5720,6 @@ function createCmsInstallationLayer(options) {
|
|
|
5398
5720
|
});
|
|
5399
5721
|
}
|
|
5400
5722
|
|
|
5401
|
-
//#endregion
|
|
5402
|
-
//#region ../sql-pg/src/internal/database/table-helpers.ts
|
|
5403
|
-
const transactionTimestamp = sql`transaction_timestamp()`;
|
|
5404
|
-
function isOneOf(column, values) {
|
|
5405
|
-
return sql`${column} in (${sql.join(values.map((value) => sql`${value}`), sql`, `)})`;
|
|
5406
|
-
}
|
|
5407
|
-
|
|
5408
5723
|
//#endregion
|
|
5409
5724
|
//#region ../sql-pg/src/internal/activity/tables.ts
|
|
5410
5725
|
const ACTIVITY_TARGET_KINDS = [
|
|
@@ -5896,227 +6211,6 @@ function changeJournalUnavailable(operation, cause) {
|
|
|
5896
6211
|
});
|
|
5897
6212
|
}
|
|
5898
6213
|
|
|
5899
|
-
//#endregion
|
|
5900
|
-
//#region ../sql-pg/src/internal/database/embedded-migrations.generated.ts
|
|
5901
|
-
const embeddedMigrations = [
|
|
5902
|
-
{
|
|
5903
|
-
sql: [
|
|
5904
|
-
"CREATE TABLE \"activity_entries\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"action\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text NOT NULL,\n \"target_id\" text,\n \"details\" jsonb DEFAULT '{}' NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'user')),\n CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" <> 'media-library' AND \"target_id\" IS NOT NULL)),\n CONSTRAINT \"activity_entries_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"activity_entries_details_check\" CHECK (jsonb_typeof(\"details\") = 'object')\n);\n",
|
|
5905
|
-
"\nCREATE TABLE \"auth_accounts\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"issuer\" text NOT NULL,\n \"account_id\" text NOT NULL,\n \"provider_id\" text NOT NULL,\n \"user_id\" uuid NOT NULL,\n \"access_token\" text,\n \"refresh_token\" text,\n \"id_token\" text,\n \"access_token_expires_at\" timestamp with time zone,\n \"refresh_token_expires_at\" timestamp with time zone,\n \"scope\" text,\n \"password\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
|
|
5906
|
-
"\nCREATE TABLE \"auth_rate_limits\" (\n \"key\" text PRIMARY KEY,\n \"count\" bigint NOT NULL,\n \"last_request\" bigint NOT NULL\n);\n",
|
|
5907
|
-
"\nCREATE TABLE \"auth_sessions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"expires_at\" timestamp with time zone NOT NULL,\n \"token\" text NOT NULL UNIQUE,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"ip_address\" text,\n \"user_agent\" text,\n \"user_id\" uuid NOT NULL,\n \"impersonated_by\" text\n);\n",
|
|
5908
|
-
"\nCREATE TABLE \"auth_users\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"name\" text NOT NULL,\n \"email\" text NOT NULL UNIQUE,\n \"email_verified\" boolean DEFAULT false NOT NULL,\n \"image\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"role\" text DEFAULT 'editor' NOT NULL,\n \"banned\" boolean DEFAULT false NOT NULL,\n \"ban_reason\" text,\n \"ban_expires\" timestamp with time zone,\n \"cms_creation_change_id\" uuid UNIQUE,\n \"cms_sessions_revoked_change_id\" uuid UNIQUE,\n CONSTRAINT \"auth_users_role_check\" CHECK (\"role\" in ('administrator', 'editor', 'viewer'))\n);\n",
|
|
5909
|
-
"\nCREATE TABLE \"auth_verifications\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"identifier\" text NOT NULL,\n \"value\" text NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
|
|
5910
|
-
"\nCREATE TABLE \"change_receipts\" (\n \"change_id\" uuid PRIMARY KEY,\n \"fingerprint\" text NOT NULL,\n \"outcome\" text NOT NULL,\n \"activity_id\" uuid UNIQUE,\n \"completed_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"change_receipts_outcome_check\" CHECK ((\"outcome\" = 'applied' AND \"activity_id\" IS NOT NULL)\n OR (\"outcome\" = 'cancelled' AND \"activity_id\" IS NULL))\n);\n",
|
|
5911
|
-
"\nCREATE TABLE \"cms_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"generation\" bigint DEFAULT 0 NOT NULL,\n CONSTRAINT \"cms_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"cms_state_generation_check\" CHECK (\"generation\" >= 0)\n);\n",
|
|
5912
|
-
"\nCREATE TABLE \"document_heads\" (\n \"document_id\" uuid PRIMARY KEY,\n \"authored_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid\n);\n",
|
|
5913
|
-
"\nCREATE TABLE \"document_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"object_key\" text NOT NULL,\n \"path\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"node_path\" integer[] NOT NULL,\n CONSTRAINT \"document_media_references_identity_unique\" UNIQUE(\"document_id\",\"source_path\",\"node_path\",\"object_key\"),\n CONSTRAINT \"document_media_references_object_key_check\" CHECK (char_length(\"object_key\") between 1 and 1024\n AND btrim(\"object_key\") = \"object_key\"\n AND \"object_key\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"object_key\") = 0),\n CONSTRAINT \"document_media_references_node_path_check\" CHECK (array_position(\"node_path\", NULL) IS NULL AND 0 <= ALL(\"node_path\"))\n);\n",
|
|
5914
|
-
"\nCREATE TABLE \"document_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"action\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"markdown\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"activity_details\" jsonb DEFAULT '{}' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"document_revisions_document_id_unique\" UNIQUE(\"document_id\",\"id\"),\n CONSTRAINT \"document_revisions_action_check\" CHECK (\"action\" in ('document.create', 'document.move', 'document.remove', 'document.restore', 'document.undelete', 'document.update'))\n);\n",
|
|
5915
|
-
"\nCREATE TABLE \"documents\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"source_path\" text NOT NULL,\n \"deleted_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL\n);\n",
|
|
5916
|
-
"\nCREATE TABLE \"initialization_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"state\" text DEFAULT 'uninitialized' NOT NULL,\n \"change_id\" uuid,\n \"claim\" jsonb,\n CONSTRAINT \"initialization_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"initialization_state_state_check\" CHECK (\"state\" in ('uninitialized', 'claiming', 'ready')),\n CONSTRAINT \"initialization_state_claim_check\" CHECK ((\"state\" = 'claiming' AND \"change_id\" IS NOT NULL AND jsonb_typeof(\"claim\") = 'object')\n OR (\"state\" <> 'claiming' AND \"change_id\" IS NULL AND \"claim\" IS NULL))\n);\n",
|
|
5917
|
-
"\nCREATE TABLE \"media_assets\" (\n \"id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text DEFAULT '' NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"status\" text DEFAULT 'uploading' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_assets_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_assets_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_assets_status_check\" CHECK (\"status\" in ('uploading', 'ready', 'deleting')),\n CONSTRAINT \"media_assets_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_assets_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_assets_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$')\n);\n",
|
|
5918
|
-
"\nCREATE TABLE \"media_replacements\" (\n \"media_id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL,\n \"staging_object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"staged\" boolean DEFAULT false NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_replacements_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_replacements_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_replacements_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_replacements_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_replacements_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_staging_object_key_check\" CHECK (\"staging_object_key\" ~ '^media/replacements/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_distinct_object_keys_check\" CHECK (\"staging_object_key\" <> \"object_key\")\n);\n",
|
|
5919
|
-
"\nCREATE TABLE \"pending_changes\" (\n \"id\" uuid PRIMARY KEY,\n \"action\" text NOT NULL,\n \"subject\" text NOT NULL,\n \"scope\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text,\n \"target_id\" text,\n \"intent\" jsonb NOT NULL,\n \"fingerprint\" text NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"pending_changes_scope_check\" CHECK (\"scope\" in ('initialization', 'media', 'users')),\n CONSTRAINT \"pending_changes_subject_check\" CHECK (char_length(\"subject\") between 1 and 1024 AND btrim(\"subject\") = \"subject\"),\n CONSTRAINT \"pending_changes_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"pending_changes_intent_check\" CHECK (jsonb_typeof(\"intent\") = 'object'),\n CONSTRAINT \"pending_changes_target_check\" CHECK ((\"target_kind\" IS NULL AND \"target_id\" IS NULL)\n OR (\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" in ('document', 'media', 'user')\n AND \"target_id\" IS NOT NULL))\n);\n",
|
|
5920
|
-
"\nCREATE TABLE \"working_document_publish_attempts\" (\n \"id\" uuid PRIMARY KEY,\n \"activity\" jsonb NOT NULL,\n \"document_id\" uuid NOT NULL,\n \"expected_generation\" uuid NOT NULL,\n \"expected_version\" uuid NOT NULL,\n \"high_watermark\" bigint NOT NULL,\n \"markdown_hash\" text NOT NULL,\n \"state\" bytea NOT NULL,\n \"state_vector\" bytea NOT NULL,\n \"checkpoint_version\" uuid,\n \"phase\" text DEFAULT 'pending' NOT NULL,\n \"failure\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_publish_attempts_phase_check\" CHECK (\"phase\" in ('pending', 'checkpointed', 'published', 'failed')),\n CONSTRAINT \"working_document_publish_attempts_high_watermark_check\" CHECK (\"high_watermark\" between 0 and 9007199254740991),\n CONSTRAINT \"working_document_publish_attempts_markdown_hash_check\" CHECK (char_length(\"markdown_hash\") between 1 and 128),\n CONSTRAINT \"working_document_publish_attempts_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_document_publish_attempts_state_vector_check\" CHECK (octet_length(\"state_vector\") > 0),\n CONSTRAINT \"working_document_publish_attempts_payload_check\" CHECK ((\n \"phase\" = 'pending'\n AND \"checkpoint_version\" IS NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" in ('checkpointed', 'published')\n AND \"checkpoint_version\" IS NOT NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" = 'failed'\n AND \"checkpoint_version\" IS NULL\n AND char_length(\"failure\") between 1 and 128\n ))\n);\n",
|
|
5921
|
-
"\nCREATE TABLE \"working_document_updates\" (\n \"document_id\" uuid,\n \"generation_id\" uuid NOT NULL,\n \"sequence\" bigint,\n \"update\" bytea NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_updates_pkey\" PRIMARY KEY(\"document_id\",\"sequence\"),\n CONSTRAINT \"working_document_updates_sequence_check\" CHECK (\"sequence\" between 1 and 9007199254740991),\n CONSTRAINT \"working_document_updates_update_check\" CHECK (octet_length(\"update\") > 0)\n);\n",
|
|
5922
|
-
"\nCREATE TABLE \"working_documents\" (\n \"document_id\" uuid PRIMARY KEY,\n \"format_version\" integer NOT NULL,\n \"generation_id\" uuid NOT NULL,\n \"state\" bytea NOT NULL,\n \"saved_state_vector\" bytea NOT NULL,\n \"saved_version\" uuid NOT NULL,\n \"next_update_sequence\" bigint DEFAULT 1 NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_documents_generation_unique\" UNIQUE(\"document_id\",\"generation_id\"),\n CONSTRAINT \"working_documents_format_version_check\" CHECK (\"format_version\" = 1),\n CONSTRAINT \"working_documents_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_documents_saved_state_vector_check\" CHECK (octet_length(\"saved_state_vector\") > 0),\n CONSTRAINT \"working_documents_next_update_sequence_check\" CHECK (\"next_update_sequence\" between 1 and 9007199254740991)\n);\n",
|
|
5923
|
-
"\nCREATE INDEX \"activity_entries_history\" ON \"activity_entries\" (\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5924
|
-
"\nCREATE INDEX \"activity_entries_actor\" ON \"activity_entries\" (\"actor_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5925
|
-
"\nCREATE INDEX \"activity_entries_target\" ON \"activity_entries\" (\"target_kind\",\"target_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5926
|
-
"\nCREATE INDEX \"activity_entries_request\" ON \"activity_entries\" (\"request_id\");",
|
|
5927
|
-
"\nCREATE INDEX \"auth_accounts_user_id\" ON \"auth_accounts\" (\"user_id\");",
|
|
5928
|
-
"\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"issuer\",\"account_id\");",
|
|
5929
|
-
"\nCREATE INDEX \"auth_sessions_user_id\" ON \"auth_sessions\" (\"user_id\");",
|
|
5930
|
-
"\nCREATE INDEX \"auth_verifications_identifier\" ON \"auth_verifications\" (\"identifier\");",
|
|
5931
|
-
"\nCREATE INDEX \"change_receipts_activity\" ON \"change_receipts\" (\"activity_id\");",
|
|
5932
|
-
"\nCREATE INDEX \"document_media_references_object_key\" ON \"document_media_references\" (\"object_key\");",
|
|
5933
|
-
"\nCREATE INDEX \"document_revisions_history\" ON \"document_revisions\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5934
|
-
"\nCREATE UNIQUE INDEX \"documents_active_path\" ON \"documents\" (\"source_path\") WHERE \"deleted_at\" is null;",
|
|
5935
|
-
"\nCREATE INDEX \"media_assets_catalog\" ON \"media_assets\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
|
|
5936
|
-
"\nCREATE INDEX \"media_assets_folder\" ON \"media_assets\" (\"folder\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
|
|
5937
|
-
"\nCREATE INDEX \"media_assets_recovery\" ON \"media_assets\" (\"updated_at\",\"id\") WHERE \"status\" <> 'ready';",
|
|
5938
|
-
"\nCREATE INDEX \"media_replacements_recovery\" ON \"media_replacements\" (\"updated_at\",\"media_id\");",
|
|
5939
|
-
"\nCREATE UNIQUE INDEX \"pending_changes_subject\" ON \"pending_changes\" (\"subject\");",
|
|
5940
|
-
"\nCREATE INDEX \"pending_changes_recovery\" ON \"pending_changes\" (\"scope\",\"updated_at\",\"id\");",
|
|
5941
|
-
"\nCREATE UNIQUE INDEX \"working_document_publish_attempts_active\" ON \"working_document_publish_attempts\" (\"document_id\") WHERE \"phase\" in ('pending', 'checkpointed');",
|
|
5942
|
-
"\nCREATE INDEX \"working_document_publish_attempts_recovery\" ON \"working_document_publish_attempts\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5943
|
-
"\nALTER TABLE \"auth_accounts\" ADD CONSTRAINT \"auth_accounts_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
|
|
5944
|
-
"\nALTER TABLE \"auth_sessions\" ADD CONSTRAINT \"auth_sessions_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
|
|
5945
|
-
"\nALTER TABLE \"change_receipts\" ADD CONSTRAINT \"change_receipts_activity_id_activity_entries_id_fkey\" FOREIGN KEY (\"activity_id\") REFERENCES \"activity_entries\"(\"id\") ON DELETE RESTRICT;",
|
|
5946
|
-
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
|
|
5947
|
-
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_authored_revision_fkey\" FOREIGN KEY (\"document_id\",\"authored_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
5948
|
-
"\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_published_revision_fkey\" FOREIGN KEY (\"document_id\",\"published_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
5949
|
-
"\nALTER TABLE \"document_media_references\" ADD CONSTRAINT \"document_media_references_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
|
|
5950
|
-
"\nALTER TABLE \"document_revisions\" ADD CONSTRAINT \"document_revisions_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
|
|
5951
|
-
"\nALTER TABLE \"media_replacements\" ADD CONSTRAINT \"media_replacements_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
|
|
5952
|
-
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"expected_generation\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
|
|
5953
|
-
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_expected_version_fkey\" FOREIGN KEY (\"document_id\",\"expected_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
5954
|
-
"\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_checkpoint_version_fkey\" FOREIGN KEY (\"document_id\",\"checkpoint_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
|
|
5955
|
-
"\nALTER TABLE \"working_document_updates\" ADD CONSTRAINT \"working_document_updates_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"generation_id\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
|
|
5956
|
-
"\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
|
|
5957
|
-
"\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_saved_version_fkey\" FOREIGN KEY (\"document_id\",\"saved_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;"
|
|
5958
|
-
],
|
|
5959
|
-
bps: true,
|
|
5960
|
-
folderMillis: 1788466567e3,
|
|
5961
|
-
hash: "943a4996ef8c4324bd58280a80103e5a1632b088880164904b3857686e26f33e",
|
|
5962
|
-
name: "20260903201607_cms_baseline"
|
|
5963
|
-
},
|
|
5964
|
-
{
|
|
5965
|
-
sql: [
|
|
5966
|
-
"ALTER TABLE \"auth_rate_limits\" ADD COLUMN \"id\" uuid DEFAULT gen_random_uuid();",
|
|
5967
|
-
"\nALTER TABLE \"auth_rate_limits\" DROP CONSTRAINT \"auth_rate_limits_pkey\";",
|
|
5968
|
-
"\nALTER TABLE \"auth_rate_limits\" ADD PRIMARY KEY (\"id\");",
|
|
5969
|
-
"\nALTER TABLE \"auth_rate_limits\" ADD CONSTRAINT \"auth_rate_limits_key_key\" UNIQUE(\"key\");"
|
|
5970
|
-
],
|
|
5971
|
-
bps: true,
|
|
5972
|
-
folderMillis: 1788587191e3,
|
|
5973
|
-
hash: "78b837c6b72a3de22d68e8db90bd211e61a0b97ff29bf8d16a0bba245eefa7ed",
|
|
5974
|
-
name: "20260905054631_burly_northstar"
|
|
5975
|
-
},
|
|
5976
|
-
{
|
|
5977
|
-
sql: ["ALTER TABLE \"auth_accounts\" DROP COLUMN \"issuer\";", "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"provider_id\",\"account_id\");"],
|
|
5978
|
-
bps: true,
|
|
5979
|
-
folderMillis: 178875937e4,
|
|
5980
|
-
hash: "e442485fa6c2d611e3dae508a12d245481bc5ec8f2dd4f5d853910df34484787",
|
|
5981
|
-
name: "20260907053610_fancy_lady_deathstrike"
|
|
5982
|
-
},
|
|
5983
|
-
{
|
|
5984
|
-
sql: ["ALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));", "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"],
|
|
5985
|
-
bps: true,
|
|
5986
|
-
folderMillis: 1788866265e3,
|
|
5987
|
-
hash: "24c56a37796caf8d76c0a97128a382b31e71808aa5b0ca7e5bac96795f9e16c7",
|
|
5988
|
-
name: "20260908111745_classy_johnny_storm"
|
|
5989
|
-
},
|
|
5990
|
-
{
|
|
5991
|
-
sql: [
|
|
5992
|
-
"CREATE TABLE \"seo_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"scope\" text NOT NULL,\n \"media_id\" uuid NOT NULL,\n CONSTRAINT \"seo_media_references_scope_media_unique\" UNIQUE(\"scope\",\"media_id\"),\n CONSTRAINT \"seo_media_references_scope_check\" CHECK (\"scope\" in ('working', 'published'))\n);\n",
|
|
5993
|
-
"\nCREATE TABLE \"seo_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"settings\" jsonb NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"seo_revisions_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"seo_revisions_settings_check\" CHECK (jsonb_typeof(\"settings\") = 'object')\n);\n",
|
|
5994
|
-
"\nCREATE TABLE \"seo_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"working_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid NOT NULL,\n CONSTRAINT \"seo_state_singleton_check\" CHECK (\"singleton\")\n);\n",
|
|
5995
|
-
"\nCREATE INDEX \"seo_media_references_media\" ON \"seo_media_references\" (\"media_id\");",
|
|
5996
|
-
"\nCREATE INDEX \"seo_revisions_history\" ON \"seo_revisions\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
|
|
5997
|
-
"\nALTER TABLE \"seo_media_references\" ADD CONSTRAINT \"seo_media_references_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
|
|
5998
|
-
"\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_working_revision_fkey\" FOREIGN KEY (\"working_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
|
|
5999
|
-
"\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_published_revision_fkey\" FOREIGN KEY (\"published_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
|
|
6000
|
-
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));",
|
|
6001
|
-
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_kind_check\", ADD CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'seo', 'user'));",
|
|
6002
|
-
"\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_check\", ADD CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" in ('media-library', 'seo') AND \"target_id\" IS NULL)\n OR (\"target_kind\" not in ('media-library', 'seo') AND \"target_id\" IS NOT NULL));",
|
|
6003
|
-
"\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"
|
|
6004
|
-
],
|
|
6005
|
-
bps: true,
|
|
6006
|
-
folderMillis: 1789233351e3,
|
|
6007
|
-
hash: "8e6a6abf5385ab3ecf8eb083c1923ac9c74d72aa71bd1d444b7402d3e7e77000",
|
|
6008
|
-
name: "20260912171551_charming_valkyrie"
|
|
6009
|
-
}
|
|
6010
|
-
];
|
|
6011
|
-
|
|
6012
|
-
//#endregion
|
|
6013
|
-
//#region ../sql-pg/src/internal/documents/tables.ts
|
|
6014
|
-
const cmsState = pgTable("cms_state", {
|
|
6015
|
-
singleton: boolean().default(true).primaryKey(),
|
|
6016
|
-
generation: bigint({ mode: "bigint" }).default(sql`0`).notNull()
|
|
6017
|
-
}, (table) => [check("cms_state_singleton_check", sql`${table.singleton}`), check("cms_state_generation_check", sql`${table.generation} >= 0`)]);
|
|
6018
|
-
const documentsTable = pgTable("documents", {
|
|
6019
|
-
id: uuid().defaultRandom().primaryKey(),
|
|
6020
|
-
sourcePath: text("source_path").notNull(),
|
|
6021
|
-
deletedAt: timestamp("deleted_at", {
|
|
6022
|
-
mode: "string",
|
|
6023
|
-
withTimezone: true
|
|
6024
|
-
}),
|
|
6025
|
-
createdAt: timestamp("created_at", {
|
|
6026
|
-
mode: "string",
|
|
6027
|
-
withTimezone: true
|
|
6028
|
-
}).default(transactionTimestamp).notNull(),
|
|
6029
|
-
updatedAt: timestamp("updated_at", {
|
|
6030
|
-
mode: "string",
|
|
6031
|
-
withTimezone: true
|
|
6032
|
-
}).default(transactionTimestamp).notNull()
|
|
6033
|
-
}, (table) => [uniqueIndex("documents_active_path").on(table.sourcePath).where(sql`${table.deletedAt} is null`)]);
|
|
6034
|
-
const documentRevisions = pgTable("document_revisions", {
|
|
6035
|
-
id: uuid().defaultRandom().primaryKey(),
|
|
6036
|
-
documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "restrict" }),
|
|
6037
|
-
action: text({ enum: DOCUMENT_REVISION_ACTIONS }).notNull(),
|
|
6038
|
-
sourcePath: text("source_path").notNull(),
|
|
6039
|
-
markdown: text().notNull(),
|
|
6040
|
-
actorId: text("actor_id").notNull(),
|
|
6041
|
-
actorEmail: text("actor_email").notNull(),
|
|
6042
|
-
actorName: text("actor_name").notNull(),
|
|
6043
|
-
actorRoles: jsonb("actor_roles").$type().notNull(),
|
|
6044
|
-
requestId: uuid("request_id").notNull(),
|
|
6045
|
-
reason: text(),
|
|
6046
|
-
activityDetails: jsonb("activity_details").$type().default({}).notNull(),
|
|
6047
|
-
createdAt: timestamp("created_at", {
|
|
6048
|
-
mode: "string",
|
|
6049
|
-
withTimezone: true
|
|
6050
|
-
}).default(transactionTimestamp).notNull()
|
|
6051
|
-
}, (table) => [
|
|
6052
|
-
check("document_revisions_action_check", isOneOf(table.action, DOCUMENT_REVISION_ACTIONS)),
|
|
6053
|
-
unique("document_revisions_document_id_unique").on(table.documentId, table.id),
|
|
6054
|
-
index("document_revisions_history").on(table.documentId, table.createdAt.desc(), table.id.desc())
|
|
6055
|
-
]);
|
|
6056
|
-
const documentHeads = pgTable("document_heads", {
|
|
6057
|
-
documentId: uuid("document_id").primaryKey().references(() => documentsTable.id, { onDelete: "restrict" }),
|
|
6058
|
-
authoredRevisionId: uuid("authored_revision_id").notNull(),
|
|
6059
|
-
publishedRevisionId: uuid("published_revision_id")
|
|
6060
|
-
}, (table) => [foreignKey({
|
|
6061
|
-
columns: [table.documentId, table.authoredRevisionId],
|
|
6062
|
-
foreignColumns: [documentRevisions.documentId, documentRevisions.id],
|
|
6063
|
-
name: "document_heads_authored_revision_fkey"
|
|
6064
|
-
}).onDelete("restrict"), foreignKey({
|
|
6065
|
-
columns: [table.documentId, table.publishedRevisionId],
|
|
6066
|
-
foreignColumns: [documentRevisions.documentId, documentRevisions.id],
|
|
6067
|
-
name: "document_heads_published_revision_fkey"
|
|
6068
|
-
}).onDelete("restrict")]);
|
|
6069
|
-
const documentMediaReferences = pgTable("document_media_references", {
|
|
6070
|
-
id: uuid().defaultRandom().primaryKey(),
|
|
6071
|
-
documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "cascade" }),
|
|
6072
|
-
objectKey: text("object_key").notNull(),
|
|
6073
|
-
path: text().notNull(),
|
|
6074
|
-
sourcePath: text("source_path").notNull(),
|
|
6075
|
-
nodePath: integer("node_path").array().notNull()
|
|
6076
|
-
}, (table) => [
|
|
6077
|
-
unique("document_media_references_identity_unique").on(table.documentId, table.sourcePath, table.nodePath, table.objectKey),
|
|
6078
|
-
check("document_media_references_object_key_check", sql`char_length(${table.objectKey}) between 1 and 1024
|
|
6079
|
-
AND btrim(${table.objectKey}) = ${table.objectKey}
|
|
6080
|
-
AND ${table.objectKey} !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'
|
|
6081
|
-
AND position(chr(92) in ${table.objectKey}) = 0`),
|
|
6082
|
-
check("document_media_references_node_path_check", sql`array_position(${table.nodePath}, NULL) IS NULL AND 0 <= ALL(${table.nodePath})`),
|
|
6083
|
-
index("document_media_references_object_key").on(table.objectKey)
|
|
6084
|
-
]);
|
|
6085
|
-
|
|
6086
|
-
//#endregion
|
|
6087
|
-
//#region ../sql-pg/src/internal/initialization/tables.ts
|
|
6088
|
-
const INITIALIZATION_STATES = [
|
|
6089
|
-
"uninitialized",
|
|
6090
|
-
"claiming",
|
|
6091
|
-
"ready"
|
|
6092
|
-
];
|
|
6093
|
-
const initializationState = pgTable("initialization_state", {
|
|
6094
|
-
singleton: boolean().default(true).primaryKey(),
|
|
6095
|
-
state: text({ enum: INITIALIZATION_STATES }).default("uninitialized").notNull(),
|
|
6096
|
-
changeId: uuid("change_id"),
|
|
6097
|
-
claim: jsonb().$type()
|
|
6098
|
-
}, (table) => [
|
|
6099
|
-
check("initialization_state_singleton_check", sql`${table.singleton}`),
|
|
6100
|
-
check("initialization_state_state_check", isOneOf(table.state, INITIALIZATION_STATES)),
|
|
6101
|
-
check("initialization_state_claim_check", sql`(${table.state} = 'claiming' AND ${table.changeId} IS NOT NULL AND jsonb_typeof(${table.claim}) = 'object')
|
|
6102
|
-
OR (${table.state} <> 'claiming' AND ${table.changeId} IS NULL AND ${table.claim} IS NULL)`)
|
|
6103
|
-
]);
|
|
6104
|
-
|
|
6105
|
-
//#endregion
|
|
6106
|
-
//#region ../sql-pg/src/internal/database/migrations.ts
|
|
6107
|
-
const MIGRATION_LOCK_KEY = "cms:database-migrations:v1";
|
|
6108
|
-
const migrateCmsDatabase = Effect.fn("CmsDatabase.migrate")(function* () {
|
|
6109
|
-
const postgres = yield* PgClient.PgClient;
|
|
6110
|
-
const database = yield* PgDrizzle.makeWithDefaults();
|
|
6111
|
-
yield* postgres.withTransaction(Effect.gen(function* () {
|
|
6112
|
-
yield* postgres.unsafe("select pg_advisory_xact_lock(hashtextextended($1, 0))", [MIGRATION_LOCK_KEY]);
|
|
6113
|
-
yield* migrate(embeddedMigrations, database._.session, "__drizzle_migrations");
|
|
6114
|
-
yield* database.insert(cmsState).values({}).onConflictDoNothing({ target: cmsState.singleton });
|
|
6115
|
-
yield* database.insert(initializationState).values({}).onConflictDoNothing({ target: initializationState.singleton });
|
|
6116
|
-
}));
|
|
6117
|
-
});
|
|
6118
|
-
const cmsDatabaseMigrationLayer = Layer.effectDiscard(migrateCmsDatabase());
|
|
6119
|
-
|
|
6120
6214
|
//#endregion
|
|
6121
6215
|
//#region ../sql-pg/src/internal/documents/commands.ts
|
|
6122
6216
|
const isEffectDrizzleQueryError = Schema.is(EffectDrizzleQueryError);
|
|
@@ -8078,21 +8172,32 @@ function notifyWorkingDocumentChange(database, kind, documentId, generationId) {
|
|
|
8078
8172
|
* Mutations that span seams remain transactions inside this adapter.
|
|
8079
8173
|
*/
|
|
8080
8174
|
function postgresLayer(options) {
|
|
8081
|
-
const
|
|
8082
|
-
|
|
8175
|
+
const { schema, ...poolOptions } = options;
|
|
8176
|
+
const clientOptions = {
|
|
8177
|
+
...poolOptions,
|
|
8083
8178
|
applicationName: options.applicationName ?? "@internal/sql-pg"
|
|
8084
|
-
}
|
|
8085
|
-
const
|
|
8086
|
-
const
|
|
8087
|
-
|
|
8179
|
+
};
|
|
8180
|
+
const database = schemaClientLayer(clientOptions, schema);
|
|
8181
|
+
const migrations = cmsDatabaseMigrationLayer(schema).pipe(Layer.provide(database));
|
|
8182
|
+
const locks = postgresAdvisoryLockLayer(poolOptions);
|
|
8183
|
+
return Layer.mergeAll(postgresActivityStoreLayer, changeJournalLayer, documentStoreLayer, mediaStoreLayer, seoStoreLayer, initializationStoreLayer.pipe(Layer.provide(locks)), postgresUserCommandFenceLayer.pipe(Layer.provide(locks)), postgresWorkingDocumentChangesLayer(poolOptions), workingDocumentStoreLayer).pipe(Layer.provide(migrations), Layer.provide(database));
|
|
8088
8184
|
}
|
|
8089
8185
|
|
|
8090
8186
|
//#endregion
|
|
8091
8187
|
//#region src/runtime/installation.ts
|
|
8188
|
+
var DatabaseSchemaProvisionFailed = class extends Schema.TaggedError()("NuxtCmsInstallation.DatabaseSchemaProvisionFailed", {
|
|
8189
|
+
cause: Schema.Defect(),
|
|
8190
|
+
schema: Schema.String
|
|
8191
|
+
}) {};
|
|
8092
8192
|
const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options) {
|
|
8193
|
+
yield* provisionDatabaseSchema(options.database);
|
|
8093
8194
|
const crypto = NodeCrypto.layer;
|
|
8094
|
-
const
|
|
8095
|
-
const
|
|
8195
|
+
const databaseUrl = scopedDatabaseUrl(options.database);
|
|
8196
|
+
const postgres = postgresLayer({
|
|
8197
|
+
schema: options.database.schema,
|
|
8198
|
+
url: Redacted.make(options.database.url)
|
|
8199
|
+
});
|
|
8200
|
+
const identity = Layer.unwrap(Effect.acquireRelease(Effect.sync(() => new Pool({ connectionString: databaseUrl })), (pool) => Effect.promise(() => pool.end()).pipe(Effect.asVoid)).pipe(Effect.map((pool) => betterAuthLayer({
|
|
8096
8201
|
baseURL: options.baseUrl,
|
|
8097
8202
|
database: pool,
|
|
8098
8203
|
secret: `cms-authentication:${options.secret}`
|
|
@@ -8119,6 +8224,16 @@ const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options)
|
|
|
8119
8224
|
studioSecret: Redacted.make(`cms-collaboration:${options.secret}`)
|
|
8120
8225
|
});
|
|
8121
8226
|
});
|
|
8227
|
+
const provisionDatabaseSchema = Effect.fn("NuxtCmsInstallation.provisionDatabaseSchema")(function* (database) {
|
|
8228
|
+
const pool = new Pool({ connectionString: database.url });
|
|
8229
|
+
yield* Effect.tryPromise({
|
|
8230
|
+
try: () => pool.query(`create schema if not exists "${database.schema}"`),
|
|
8231
|
+
catch: (cause) => new DatabaseSchemaProvisionFailed({
|
|
8232
|
+
cause,
|
|
8233
|
+
schema: database.schema
|
|
8234
|
+
})
|
|
8235
|
+
}).pipe(Effect.ensuring(Effect.promise(() => pool.end())));
|
|
8236
|
+
});
|
|
8122
8237
|
function toS3MediaObjectStoreOptions(options) {
|
|
8123
8238
|
const { credentials: authoredCredentials, publicBaseUrl: _publicBaseUrl, ...storeOptions } = options;
|
|
8124
8239
|
if (!authoredCredentials) return storeOptions;
|
|
@@ -8135,7 +8250,13 @@ function toS3MediaObjectStoreOptions(options) {
|
|
|
8135
8250
|
credentials
|
|
8136
8251
|
};
|
|
8137
8252
|
}
|
|
8253
|
+
function scopedDatabaseUrl(database) {
|
|
8254
|
+
if (!/^[a-z_][a-z0-9_]{0,62}$/u.test(database.schema)) throw new Error("Invalid CMS PostgreSQL schema.");
|
|
8255
|
+
const url = new URL(database.url);
|
|
8256
|
+
url.searchParams.set("options", `-csearch_path=${database.schema}`);
|
|
8257
|
+
return url.href;
|
|
8258
|
+
}
|
|
8138
8259
|
|
|
8139
8260
|
//#endregion
|
|
8140
|
-
export {
|
|
8141
|
-
//# sourceMappingURL=installation-
|
|
8261
|
+
export { embeddedMigrations as a, createCmsBetterAuth as i, scopedDatabaseUrl as n, toS3MediaObjectStoreOptions as r, installCms as t };
|
|
8262
|
+
//# sourceMappingURL=installation-DsGst1BH.js.map
|