@actuate-media/cms-core 0.51.0 → 0.51.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/dist/__tests__/actions/document-crud.test.js +25 -0
- package/dist/__tests__/actions/document-crud.test.js.map +1 -1
- package/dist/__tests__/config/runtime.test.d.ts +2 -0
- package/dist/__tests__/config/runtime.test.d.ts.map +1 -0
- package/dist/__tests__/config/runtime.test.js +65 -0
- package/dist/__tests__/config/runtime.test.js.map +1 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +27 -2
- package/dist/actions.js.map +1 -1
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +35 -1
- package/dist/config/runtime.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/0001_init/migration.sql +560 -3
- package/prisma/migrations/0002_folders/migration.sql +0 -39
- package/prisma/migrations/0003_search_and_webhooks/migration.sql +0 -50
- package/prisma/migrations/0004_script_tags/migration.sql +0 -21
- package/prisma/migrations/0005_password_reset_tokens/migration.sql +0 -20
- package/prisma/migrations/0006_page_builder/migration.sql +0 -38
- package/prisma/migrations/0007_dashboard_metrics/migration.sql +0 -74
- package/prisma/migrations/0008_media_center/migration.sql +0 -47
- package/prisma/migrations/0009_seo/migration.sql +0 -143
- package/prisma/migrations/0010_forms/migration.sql +0 -130
- package/prisma/migrations/0011_user_roles_owner_viewer/migration.sql +0 -6
- package/prisma/migrations/0012_invites_and_user_lifecycle/migration.sql +0 -40
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "actuate_folders" (
|
|
3
|
-
"id" TEXT NOT NULL,
|
|
4
|
-
"name" TEXT NOT NULL,
|
|
5
|
-
"scope" TEXT NOT NULL,
|
|
6
|
-
"parentId" TEXT,
|
|
7
|
-
"position" INTEGER NOT NULL DEFAULT 0,
|
|
8
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
9
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
10
|
-
|
|
11
|
-
CONSTRAINT "actuate_folders_pkey" PRIMARY KEY ("id")
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
-- CreateIndex
|
|
15
|
-
CREATE INDEX "actuate_folders_scope_idx" ON "actuate_folders"("scope");
|
|
16
|
-
|
|
17
|
-
-- CreateIndex
|
|
18
|
-
CREATE INDEX "actuate_folders_parentId_idx" ON "actuate_folders"("parentId");
|
|
19
|
-
|
|
20
|
-
-- AddForeignKey (self-relation for nesting)
|
|
21
|
-
ALTER TABLE "actuate_folders" ADD CONSTRAINT "actuate_folders_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "actuate_folders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
22
|
-
|
|
23
|
-
-- AlterTable: add folderId to documents
|
|
24
|
-
ALTER TABLE "actuate_documents" ADD COLUMN "folderId" TEXT;
|
|
25
|
-
|
|
26
|
-
-- CreateIndex
|
|
27
|
-
CREATE INDEX "actuate_documents_folderId_idx" ON "actuate_documents"("folderId");
|
|
28
|
-
|
|
29
|
-
-- AddForeignKey
|
|
30
|
-
ALTER TABLE "actuate_documents" ADD CONSTRAINT "actuate_documents_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "actuate_folders"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
31
|
-
|
|
32
|
-
-- AlterTable: add folderId to media
|
|
33
|
-
ALTER TABLE "actuate_media" ADD COLUMN "folderId" TEXT;
|
|
34
|
-
|
|
35
|
-
-- CreateIndex
|
|
36
|
-
CREATE INDEX "actuate_media_folderId_idx" ON "actuate_media"("folderId");
|
|
37
|
-
|
|
38
|
-
-- AddForeignKey
|
|
39
|
-
ALTER TABLE "actuate_media" ADD CONSTRAINT "actuate_media_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "actuate_folders"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
-- Full-text search: GIN index on documents for fast ts_vector queries
|
|
2
|
-
CREATE INDEX IF NOT EXISTS "idx_actuate_documents_fts"
|
|
3
|
-
ON "actuate_documents"
|
|
4
|
-
USING GIN (to_tsvector('english', COALESCE("title", '') || ' ' || COALESCE("plainText", '')));
|
|
5
|
-
|
|
6
|
-
-- Webhook endpoints table
|
|
7
|
-
CREATE TABLE IF NOT EXISTS "actuate_webhook_endpoints" (
|
|
8
|
-
"id" TEXT NOT NULL,
|
|
9
|
-
"url" TEXT NOT NULL,
|
|
10
|
-
"events" JSONB NOT NULL,
|
|
11
|
-
"secret" TEXT NOT NULL,
|
|
12
|
-
"active" BOOLEAN NOT NULL DEFAULT true,
|
|
13
|
-
"name" TEXT,
|
|
14
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
15
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
16
|
-
|
|
17
|
-
CONSTRAINT "actuate_webhook_endpoints_pkey" PRIMARY KEY ("id")
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
-- Webhook delivery log table
|
|
21
|
-
CREATE TABLE IF NOT EXISTS "actuate_webhook_deliveries" (
|
|
22
|
-
"id" TEXT NOT NULL,
|
|
23
|
-
"endpointId" TEXT NOT NULL,
|
|
24
|
-
"event" TEXT NOT NULL,
|
|
25
|
-
"payload" JSONB NOT NULL,
|
|
26
|
-
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
27
|
-
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
28
|
-
"maxAttempts" INTEGER NOT NULL DEFAULT 3,
|
|
29
|
-
"lastAttemptAt" TIMESTAMP(3),
|
|
30
|
-
"nextRetryAt" TIMESTAMP(3),
|
|
31
|
-
"responseStatus" INTEGER,
|
|
32
|
-
"responseBody" TEXT,
|
|
33
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
34
|
-
|
|
35
|
-
CONSTRAINT "actuate_webhook_deliveries_pkey" PRIMARY KEY ("id")
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
CREATE INDEX IF NOT EXISTS "actuate_webhook_deliveries_endpointId_idx"
|
|
39
|
-
ON "actuate_webhook_deliveries"("endpointId");
|
|
40
|
-
|
|
41
|
-
CREATE INDEX IF NOT EXISTS "actuate_webhook_deliveries_status_idx"
|
|
42
|
-
ON "actuate_webhook_deliveries"("status");
|
|
43
|
-
|
|
44
|
-
CREATE INDEX IF NOT EXISTS "actuate_webhook_deliveries_nextRetryAt_idx"
|
|
45
|
-
ON "actuate_webhook_deliveries"("nextRetryAt");
|
|
46
|
-
|
|
47
|
-
ALTER TABLE "actuate_webhook_deliveries"
|
|
48
|
-
ADD CONSTRAINT "actuate_webhook_deliveries_endpointId_fkey"
|
|
49
|
-
FOREIGN KEY ("endpointId") REFERENCES "actuate_webhook_endpoints"("id")
|
|
50
|
-
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "actuate_script_tags" (
|
|
3
|
-
"id" TEXT NOT NULL,
|
|
4
|
-
"name" TEXT NOT NULL,
|
|
5
|
-
"code" TEXT NOT NULL,
|
|
6
|
-
"placement" TEXT NOT NULL,
|
|
7
|
-
"scope" TEXT NOT NULL,
|
|
8
|
-
"targetPaths" TEXT[],
|
|
9
|
-
"priority" INTEGER NOT NULL DEFAULT 100,
|
|
10
|
-
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
11
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
13
|
-
|
|
14
|
-
CONSTRAINT "actuate_script_tags_pkey" PRIMARY KEY ("id")
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- CreateIndex
|
|
18
|
-
CREATE INDEX "actuate_script_tags_enabled_idx" ON "actuate_script_tags"("enabled");
|
|
19
|
-
|
|
20
|
-
-- CreateIndex
|
|
21
|
-
CREATE INDEX "actuate_script_tags_placement_idx" ON "actuate_script_tags"("placement");
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "actuate_password_reset_tokens" (
|
|
3
|
-
"id" TEXT NOT NULL,
|
|
4
|
-
"userId" TEXT NOT NULL,
|
|
5
|
-
"tokenHash" TEXT NOT NULL,
|
|
6
|
-
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
7
|
-
"usedAt" TIMESTAMP(3),
|
|
8
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
9
|
-
|
|
10
|
-
CONSTRAINT "actuate_password_reset_tokens_pkey" PRIMARY KEY ("id")
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
-- CreateIndex
|
|
14
|
-
CREATE INDEX "actuate_password_reset_tokens_tokenHash_idx" ON "actuate_password_reset_tokens"("tokenHash");
|
|
15
|
-
|
|
16
|
-
-- CreateIndex
|
|
17
|
-
CREATE INDEX "actuate_password_reset_tokens_userId_idx" ON "actuate_password_reset_tokens"("userId");
|
|
18
|
-
|
|
19
|
-
-- AddForeignKey
|
|
20
|
-
ALTER TABLE "actuate_password_reset_tokens" ADD CONSTRAINT "actuate_password_reset_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "actuate_users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "actuate_page_templates" (
|
|
3
|
-
"id" TEXT NOT NULL,
|
|
4
|
-
"name" TEXT NOT NULL,
|
|
5
|
-
"description" TEXT,
|
|
6
|
-
"category" TEXT NOT NULL DEFAULT 'content',
|
|
7
|
-
"tree" JSONB NOT NULL,
|
|
8
|
-
"thumbnail" TEXT,
|
|
9
|
-
"builtIn" BOOLEAN NOT NULL DEFAULT false,
|
|
10
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
11
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
12
|
-
|
|
13
|
-
CONSTRAINT "actuate_page_templates_pkey" PRIMARY KEY ("id")
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- CreateTable
|
|
17
|
-
CREATE TABLE "actuate_saved_sections" (
|
|
18
|
-
"id" TEXT NOT NULL,
|
|
19
|
-
"name" TEXT NOT NULL,
|
|
20
|
-
"description" TEXT,
|
|
21
|
-
"category" TEXT NOT NULL DEFAULT 'content',
|
|
22
|
-
"tree" JSONB NOT NULL,
|
|
23
|
-
"thumbnail" TEXT,
|
|
24
|
-
"usageCount" INTEGER NOT NULL DEFAULT 0,
|
|
25
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
27
|
-
|
|
28
|
-
CONSTRAINT "actuate_saved_sections_pkey" PRIMARY KEY ("id")
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
-- CreateIndex
|
|
32
|
-
CREATE INDEX "actuate_page_templates_category_idx" ON "actuate_page_templates"("category");
|
|
33
|
-
|
|
34
|
-
-- CreateIndex
|
|
35
|
-
CREATE INDEX "actuate_page_templates_builtIn_idx" ON "actuate_page_templates"("builtIn");
|
|
36
|
-
|
|
37
|
-
-- CreateIndex
|
|
38
|
-
CREATE INDEX "actuate_saved_sections_category_idx" ON "actuate_saved_sections"("category");
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
-- Dashboard metrics & content health
|
|
2
|
-
--
|
|
3
|
-
-- Adds two tables that back the redesigned admin Dashboard:
|
|
4
|
-
-- * actuate_api_request_metrics — per-minute pre-aggregated request
|
|
5
|
-
-- counters with a fixed log-scale latency histogram, sized to keep
|
|
6
|
-
-- a week of traffic in O(minutes × routes × status-buckets) rows.
|
|
7
|
-
-- * actuate_content_issues — persisted content-quality issues
|
|
8
|
-
-- produced by the nightly content-health scanner. Upserted by
|
|
9
|
-
-- (documentId, type) so the scanner is idempotent.
|
|
10
|
-
--
|
|
11
|
-
-- Both tables are safe to add to a populated database: they have no
|
|
12
|
-
-- backfill dependency and no constraints that touch existing rows.
|
|
13
|
-
|
|
14
|
-
-- ---------------------------------------------------------------------------
|
|
15
|
-
-- ContentIssueType enum
|
|
16
|
-
-- ---------------------------------------------------------------------------
|
|
17
|
-
CREATE TYPE "ContentIssueType" AS ENUM (
|
|
18
|
-
'MISSING_META_DESCRIPTION',
|
|
19
|
-
'MISSING_ALT_TEXT',
|
|
20
|
-
'BROKEN_INTERNAL_LINK',
|
|
21
|
-
'OUTDATED_CONTENT'
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
-- ---------------------------------------------------------------------------
|
|
25
|
-
-- actuate_api_request_metrics
|
|
26
|
-
-- ---------------------------------------------------------------------------
|
|
27
|
-
CREATE TABLE "actuate_api_request_metrics" (
|
|
28
|
-
"id" TEXT NOT NULL,
|
|
29
|
-
"bucketStart" TIMESTAMP(3) NOT NULL,
|
|
30
|
-
"route" TEXT NOT NULL,
|
|
31
|
-
"statusBucket" TEXT NOT NULL,
|
|
32
|
-
"count" INTEGER NOT NULL DEFAULT 0,
|
|
33
|
-
"sumLatencyMs" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
34
|
-
"maxLatencyMs" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
35
|
-
"latencyHistogram" JSONB NOT NULL,
|
|
36
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
37
|
-
|
|
38
|
-
CONSTRAINT "actuate_api_request_metrics_pkey" PRIMARY KEY ("id")
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
CREATE UNIQUE INDEX "actuate_api_request_metrics_bucketStart_route_statusBucket_key"
|
|
42
|
-
ON "actuate_api_request_metrics" ("bucketStart", "route", "statusBucket");
|
|
43
|
-
|
|
44
|
-
CREATE INDEX "actuate_api_request_metrics_bucketStart_idx"
|
|
45
|
-
ON "actuate_api_request_metrics" ("bucketStart");
|
|
46
|
-
|
|
47
|
-
-- ---------------------------------------------------------------------------
|
|
48
|
-
-- actuate_content_issues
|
|
49
|
-
-- ---------------------------------------------------------------------------
|
|
50
|
-
CREATE TABLE "actuate_content_issues" (
|
|
51
|
-
"id" TEXT NOT NULL,
|
|
52
|
-
"documentId" TEXT NOT NULL,
|
|
53
|
-
"type" "ContentIssueType" NOT NULL,
|
|
54
|
-
"count" INTEGER NOT NULL DEFAULT 1,
|
|
55
|
-
"details" JSONB,
|
|
56
|
-
"firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
57
|
-
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
58
|
-
|
|
59
|
-
CONSTRAINT "actuate_content_issues_pkey" PRIMARY KEY ("id"),
|
|
60
|
-
CONSTRAINT "actuate_content_issues_documentId_fkey"
|
|
61
|
-
FOREIGN KEY ("documentId")
|
|
62
|
-
REFERENCES "actuate_documents"("id")
|
|
63
|
-
ON DELETE CASCADE
|
|
64
|
-
ON UPDATE CASCADE
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
CREATE UNIQUE INDEX "actuate_content_issues_documentId_type_key"
|
|
68
|
-
ON "actuate_content_issues" ("documentId", "type");
|
|
69
|
-
|
|
70
|
-
CREATE INDEX "actuate_content_issues_type_idx"
|
|
71
|
-
ON "actuate_content_issues" ("type");
|
|
72
|
-
|
|
73
|
-
CREATE INDEX "actuate_content_issues_documentId_idx"
|
|
74
|
-
ON "actuate_content_issues" ("documentId");
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
-- Media Center
|
|
2
|
-
--
|
|
3
|
-
-- Extends actuate_media with the metadata the Media Center needs: SEO fields
|
|
4
|
-
-- (caption / description / focusKeyword), provenance (originalFileName), a
|
|
5
|
-
-- normalised storage split (publicUrl / storageProvider), media processing
|
|
6
|
-
-- artefacts (thumbnailUrl / responsiveVariants / durationSeconds), a tags
|
|
7
|
-
-- bag, soft-delete (deletedAt), and a processing status.
|
|
8
|
-
--
|
|
9
|
-
-- SEO score and issues are deliberately NOT persisted — they are derived on
|
|
10
|
-
-- read by `calculateMediaSeoScore()` so they never drift from the metadata.
|
|
11
|
-
--
|
|
12
|
-
-- Safe to apply to a populated database:
|
|
13
|
-
-- * Every new column is nullable or has a default — no backfill required.
|
|
14
|
-
-- * `status` defaults to READY so existing rows are immediately valid.
|
|
15
|
-
-- * No existing column is dropped or retyped.
|
|
16
|
-
|
|
17
|
-
-- ---------------------------------------------------------------------------
|
|
18
|
-
-- MediaStatus enum
|
|
19
|
-
-- ---------------------------------------------------------------------------
|
|
20
|
-
CREATE TYPE "MediaStatus" AS ENUM (
|
|
21
|
-
'PROCESSING',
|
|
22
|
-
'READY',
|
|
23
|
-
'FAILED'
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
-- ---------------------------------------------------------------------------
|
|
27
|
-
-- actuate_media new columns
|
|
28
|
-
-- ---------------------------------------------------------------------------
|
|
29
|
-
ALTER TABLE "actuate_media"
|
|
30
|
-
ADD COLUMN "originalFileName" TEXT,
|
|
31
|
-
ADD COLUMN "caption" TEXT,
|
|
32
|
-
ADD COLUMN "description" TEXT,
|
|
33
|
-
ADD COLUMN "focusKeyword" TEXT,
|
|
34
|
-
ADD COLUMN "tags" JSONB,
|
|
35
|
-
ADD COLUMN "publicUrl" TEXT,
|
|
36
|
-
ADD COLUMN "storageProvider" TEXT,
|
|
37
|
-
ADD COLUMN "durationSeconds" DOUBLE PRECISION,
|
|
38
|
-
ADD COLUMN "thumbnailUrl" TEXT,
|
|
39
|
-
ADD COLUMN "responsiveVariants" JSONB,
|
|
40
|
-
ADD COLUMN "status" "MediaStatus" NOT NULL DEFAULT 'READY',
|
|
41
|
-
ADD COLUMN "deletedAt" TIMESTAMP(3);
|
|
42
|
-
|
|
43
|
-
-- ---------------------------------------------------------------------------
|
|
44
|
-
-- Indexes backing the new query filters (soft-delete + type filtering)
|
|
45
|
-
-- ---------------------------------------------------------------------------
|
|
46
|
-
CREATE INDEX "actuate_media_deletedAt_idx" ON "actuate_media" ("deletedAt");
|
|
47
|
-
CREATE INDEX "actuate_media_mimeType_idx" ON "actuate_media" ("mimeType");
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
-- SEO Operations Center
|
|
2
|
-
--
|
|
3
|
-
-- Adds the persistence layer for the SEO module:
|
|
4
|
-
-- * Redirect: runtime + management columns (enabled, priority, preserveQuery,
|
|
5
|
-
-- source_kind, hits, lastHitAt, createdById).
|
|
6
|
-
-- * SeoAuditRun: one row per audit execution (score + issue-count snapshot).
|
|
7
|
-
-- * SeoIssue: detected SEO problems, status carried across runs via issueKey.
|
|
8
|
-
-- * Redirect404Hit: aggregated 404 traffic observed by the middleware.
|
|
9
|
-
-- * RedirectSuggestion: confidence-scored 404 recovery / chain suggestions.
|
|
10
|
-
--
|
|
11
|
-
-- Safe to apply to a populated database:
|
|
12
|
-
-- * Every new Redirect column is nullable or has a default — no backfill.
|
|
13
|
-
-- * New tables/enums are additive; no existing column is dropped or retyped.
|
|
14
|
-
|
|
15
|
-
-- ---------------------------------------------------------------------------
|
|
16
|
-
-- Enums
|
|
17
|
-
-- ---------------------------------------------------------------------------
|
|
18
|
-
CREATE TYPE "SeoAuditStatus" AS ENUM ('RUNNING', 'COMPLETED', 'FAILED');
|
|
19
|
-
CREATE TYPE "SeoIssueSeverity" AS ENUM ('critical', 'warning', 'info');
|
|
20
|
-
CREATE TYPE "SeoIssueStatus" AS ENUM ('open', 'ignored', 'resolved', 'recurring');
|
|
21
|
-
CREATE TYPE "SeoIssueCategory" AS ENUM (
|
|
22
|
-
'content', 'technical', 'redirects', 'media',
|
|
23
|
-
'performance', 'schema', 'social', 'indexing'
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
-- ---------------------------------------------------------------------------
|
|
27
|
-
-- actuate_redirects new columns
|
|
28
|
-
-- ---------------------------------------------------------------------------
|
|
29
|
-
ALTER TABLE "actuate_redirects"
|
|
30
|
-
ADD COLUMN "enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
31
|
-
ADD COLUMN "priority" INTEGER NOT NULL DEFAULT 0,
|
|
32
|
-
ADD COLUMN "preserveQuery" BOOLEAN NOT NULL DEFAULT false,
|
|
33
|
-
ADD COLUMN "source_kind" TEXT NOT NULL DEFAULT 'manual',
|
|
34
|
-
ADD COLUMN "hits" INTEGER NOT NULL DEFAULT 0,
|
|
35
|
-
ADD COLUMN "lastHitAt" TIMESTAMP(3),
|
|
36
|
-
ADD COLUMN "createdById" TEXT;
|
|
37
|
-
|
|
38
|
-
CREATE INDEX "actuate_redirects_enabled_idx" ON "actuate_redirects" ("enabled");
|
|
39
|
-
CREATE INDEX "actuate_redirects_lastHitAt_idx" ON "actuate_redirects" ("lastHitAt");
|
|
40
|
-
|
|
41
|
-
-- ---------------------------------------------------------------------------
|
|
42
|
-
-- actuate_seo_audit_runs
|
|
43
|
-
-- ---------------------------------------------------------------------------
|
|
44
|
-
CREATE TABLE "actuate_seo_audit_runs" (
|
|
45
|
-
"id" TEXT NOT NULL,
|
|
46
|
-
"status" "SeoAuditStatus" NOT NULL DEFAULT 'RUNNING',
|
|
47
|
-
"scope" TEXT NOT NULL DEFAULT 'full',
|
|
48
|
-
"startedById" TEXT,
|
|
49
|
-
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
50
|
-
"finishedAt" TIMESTAMP(3),
|
|
51
|
-
"siteScoreBefore" INTEGER,
|
|
52
|
-
"siteScoreAfter" INTEGER,
|
|
53
|
-
"pagesScanned" INTEGER NOT NULL DEFAULT 0,
|
|
54
|
-
"issuesFound" INTEGER NOT NULL DEFAULT 0,
|
|
55
|
-
"criticalCount" INTEGER NOT NULL DEFAULT 0,
|
|
56
|
-
"warningCount" INTEGER NOT NULL DEFAULT 0,
|
|
57
|
-
"infoCount" INTEGER NOT NULL DEFAULT 0,
|
|
58
|
-
"errorMessage" TEXT,
|
|
59
|
-
"metadata" JSONB,
|
|
60
|
-
CONSTRAINT "actuate_seo_audit_runs_pkey" PRIMARY KEY ("id")
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
CREATE INDEX "actuate_seo_audit_runs_status_idx" ON "actuate_seo_audit_runs" ("status");
|
|
64
|
-
CREATE INDEX "actuate_seo_audit_runs_startedAt_idx" ON "actuate_seo_audit_runs" ("startedAt");
|
|
65
|
-
|
|
66
|
-
-- ---------------------------------------------------------------------------
|
|
67
|
-
-- actuate_seo_issues
|
|
68
|
-
-- ---------------------------------------------------------------------------
|
|
69
|
-
CREATE TABLE "actuate_seo_issues" (
|
|
70
|
-
"id" TEXT NOT NULL,
|
|
71
|
-
"auditRunId" TEXT,
|
|
72
|
-
"issueKey" TEXT NOT NULL,
|
|
73
|
-
"entityType" TEXT,
|
|
74
|
-
"entityId" TEXT,
|
|
75
|
-
"entityTitle" TEXT,
|
|
76
|
-
"url" TEXT,
|
|
77
|
-
"severity" "SeoIssueSeverity" NOT NULL,
|
|
78
|
-
"category" "SeoIssueCategory" NOT NULL,
|
|
79
|
-
"type" TEXT NOT NULL,
|
|
80
|
-
"title" TEXT NOT NULL,
|
|
81
|
-
"description" TEXT,
|
|
82
|
-
"impact" TEXT,
|
|
83
|
-
"recommendation" TEXT,
|
|
84
|
-
"status" "SeoIssueStatus" NOT NULL DEFAULT 'open',
|
|
85
|
-
"fixable" BOOLEAN NOT NULL DEFAULT false,
|
|
86
|
-
"fixActionType" TEXT,
|
|
87
|
-
"relatedEntityIds" JSONB,
|
|
88
|
-
"source" TEXT NOT NULL DEFAULT 'audit',
|
|
89
|
-
"firstDetectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
90
|
-
"lastDetectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
91
|
-
"resolvedAt" TIMESTAMP(3),
|
|
92
|
-
"resolvedById" TEXT,
|
|
93
|
-
"metadata" JSONB,
|
|
94
|
-
CONSTRAINT "actuate_seo_issues_pkey" PRIMARY KEY ("id")
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
CREATE INDEX "actuate_seo_issues_auditRunId_idx" ON "actuate_seo_issues" ("auditRunId");
|
|
98
|
-
CREATE INDEX "actuate_seo_issues_status_idx" ON "actuate_seo_issues" ("status");
|
|
99
|
-
CREATE INDEX "actuate_seo_issues_severity_idx" ON "actuate_seo_issues" ("severity");
|
|
100
|
-
CREATE INDEX "actuate_seo_issues_category_idx" ON "actuate_seo_issues" ("category");
|
|
101
|
-
CREATE INDEX "actuate_seo_issues_issueKey_idx" ON "actuate_seo_issues" ("issueKey");
|
|
102
|
-
|
|
103
|
-
ALTER TABLE "actuate_seo_issues"
|
|
104
|
-
ADD CONSTRAINT "actuate_seo_issues_auditRunId_fkey"
|
|
105
|
-
FOREIGN KEY ("auditRunId") REFERENCES "actuate_seo_audit_runs"("id")
|
|
106
|
-
ON DELETE SET NULL ON UPDATE CASCADE;
|
|
107
|
-
|
|
108
|
-
-- ---------------------------------------------------------------------------
|
|
109
|
-
-- actuate_redirect_404_hits
|
|
110
|
-
-- ---------------------------------------------------------------------------
|
|
111
|
-
CREATE TABLE "actuate_redirect_404_hits" (
|
|
112
|
-
"id" TEXT NOT NULL,
|
|
113
|
-
"path" TEXT NOT NULL,
|
|
114
|
-
"hits" INTEGER NOT NULL DEFAULT 1,
|
|
115
|
-
"referrer" TEXT,
|
|
116
|
-
"resolvedAt" TIMESTAMP(3),
|
|
117
|
-
"firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
118
|
-
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
119
|
-
CONSTRAINT "actuate_redirect_404_hits_pkey" PRIMARY KEY ("id")
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
CREATE UNIQUE INDEX "actuate_redirect_404_hits_path_key" ON "actuate_redirect_404_hits" ("path");
|
|
123
|
-
CREATE INDEX "actuate_redirect_404_hits_lastSeenAt_idx" ON "actuate_redirect_404_hits" ("lastSeenAt");
|
|
124
|
-
|
|
125
|
-
-- ---------------------------------------------------------------------------
|
|
126
|
-
-- actuate_redirect_suggestions
|
|
127
|
-
-- ---------------------------------------------------------------------------
|
|
128
|
-
CREATE TABLE "actuate_redirect_suggestions" (
|
|
129
|
-
"id" TEXT NOT NULL,
|
|
130
|
-
"fromPath" TEXT NOT NULL,
|
|
131
|
-
"toPath" TEXT NOT NULL,
|
|
132
|
-
"confidence" INTEGER NOT NULL DEFAULT 0,
|
|
133
|
-
"reason" TEXT,
|
|
134
|
-
"status" TEXT NOT NULL DEFAULT 'open',
|
|
135
|
-
"source" TEXT NOT NULL DEFAULT 'ai-404-recovery',
|
|
136
|
-
"metadata" JSONB,
|
|
137
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
138
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
139
|
-
CONSTRAINT "actuate_redirect_suggestions_pkey" PRIMARY KEY ("id")
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
CREATE INDEX "actuate_redirect_suggestions_status_idx" ON "actuate_redirect_suggestions" ("status");
|
|
143
|
-
CREATE INDEX "actuate_redirect_suggestions_fromPath_idx" ON "actuate_redirect_suggestions" ("fromPath");
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
-- Forms system
|
|
2
|
-
--
|
|
3
|
-
-- Expands the Forms feature from a single flat submissions table into a real
|
|
4
|
-
-- submission workflow with schema versioning, per-submission file attachments,
|
|
5
|
-
-- and per-form webhooks.
|
|
6
|
-
--
|
|
7
|
-
-- * actuate_form_submissions: new workflow columns (entryNumber, sender*,
|
|
8
|
-
-- unread/starred/archived, spamStatus, attribution metadata, schema version
|
|
9
|
-
-- link, normalizedData, read/archived timestamps, updatedAt).
|
|
10
|
-
-- * actuate_form_schema_versions: versioned field-schema snapshots so old
|
|
11
|
-
-- submissions always render against the schema they were captured with.
|
|
12
|
-
-- * actuate_form_submission_files: file-upload metadata (storage keys, not
|
|
13
|
-
-- blobs) with cascade delete from its submission.
|
|
14
|
-
-- * actuate_form_webhooks: per-form signed outbound webhooks.
|
|
15
|
-
--
|
|
16
|
-
-- Safe to apply to a populated database:
|
|
17
|
-
-- * Every new column on actuate_form_submissions is nullable or has a default.
|
|
18
|
-
-- * updatedAt is backfilled from createdAt for existing rows before the NOT
|
|
19
|
-
-- NULL default takes over for new rows.
|
|
20
|
-
-- * No existing column is dropped or retyped. formId stays a loose string
|
|
21
|
-
-- (no new FK) so historical rows with orphaned formIds are not rejected.
|
|
22
|
-
|
|
23
|
-
-- ---------------------------------------------------------------------------
|
|
24
|
-
-- actuate_form_submissions new columns
|
|
25
|
-
-- ---------------------------------------------------------------------------
|
|
26
|
-
ALTER TABLE "actuate_form_submissions"
|
|
27
|
-
ADD COLUMN "entryNumber" INTEGER,
|
|
28
|
-
ADD COLUMN "schemaVersionId" TEXT,
|
|
29
|
-
ADD COLUMN "normalizedData" JSONB,
|
|
30
|
-
ADD COLUMN "senderName" TEXT,
|
|
31
|
-
ADD COLUMN "senderEmail" TEXT,
|
|
32
|
-
ADD COLUMN "senderPhone" TEXT,
|
|
33
|
-
ADD COLUMN "preview" TEXT,
|
|
34
|
-
ADD COLUMN "unread" BOOLEAN NOT NULL DEFAULT true,
|
|
35
|
-
ADD COLUMN "starred" BOOLEAN NOT NULL DEFAULT false,
|
|
36
|
-
ADD COLUMN "archived" BOOLEAN NOT NULL DEFAULT false,
|
|
37
|
-
ADD COLUMN "spamStatus" TEXT NOT NULL DEFAULT 'clean',
|
|
38
|
-
ADD COLUMN "ipAddressHash" TEXT,
|
|
39
|
-
ADD COLUMN "userAgent" TEXT,
|
|
40
|
-
ADD COLUMN "referrer" TEXT,
|
|
41
|
-
ADD COLUMN "pageUrl" TEXT,
|
|
42
|
-
ADD COLUMN "utmSource" TEXT,
|
|
43
|
-
ADD COLUMN "utmMedium" TEXT,
|
|
44
|
-
ADD COLUMN "utmCampaign" TEXT,
|
|
45
|
-
ADD COLUMN "readAt" TIMESTAMP(3),
|
|
46
|
-
ADD COLUMN "archivedAt" TIMESTAMP(3),
|
|
47
|
-
ADD COLUMN "updatedAt" TIMESTAMP(3);
|
|
48
|
-
|
|
49
|
-
-- Backfill updatedAt for existing rows, then enforce NOT NULL with a default
|
|
50
|
-
-- so new inserts (and Prisma's @updatedAt) always have a value.
|
|
51
|
-
UPDATE "actuate_form_submissions" SET "updatedAt" = "createdAt" WHERE "updatedAt" IS NULL;
|
|
52
|
-
ALTER TABLE "actuate_form_submissions"
|
|
53
|
-
ALTER COLUMN "updatedAt" SET NOT NULL,
|
|
54
|
-
ALTER COLUMN "updatedAt" SET DEFAULT CURRENT_TIMESTAMP;
|
|
55
|
-
|
|
56
|
-
-- Existing rows predate the read/unread workflow; treat them as already read so
|
|
57
|
-
-- they don't all light up as unread in the new inbox.
|
|
58
|
-
UPDATE "actuate_form_submissions" SET "unread" = false WHERE "status" <> 'new';
|
|
59
|
-
|
|
60
|
-
CREATE INDEX "actuate_form_submissions_unread_idx" ON "actuate_form_submissions" ("unread");
|
|
61
|
-
CREATE INDEX "actuate_form_submissions_starred_idx" ON "actuate_form_submissions" ("starred");
|
|
62
|
-
CREATE INDEX "actuate_form_submissions_archived_idx" ON "actuate_form_submissions" ("archived");
|
|
63
|
-
CREATE INDEX "actuate_form_submissions_spamStatus_idx" ON "actuate_form_submissions" ("spamStatus");
|
|
64
|
-
CREATE INDEX "actuate_form_submissions_submittedAt_idx" ON "actuate_form_submissions" ("submittedAt");
|
|
65
|
-
CREATE INDEX "actuate_form_submissions_senderEmail_idx" ON "actuate_form_submissions" ("senderEmail");
|
|
66
|
-
|
|
67
|
-
-- ---------------------------------------------------------------------------
|
|
68
|
-
-- actuate_form_schema_versions
|
|
69
|
-
-- ---------------------------------------------------------------------------
|
|
70
|
-
CREATE TABLE "actuate_form_schema_versions" (
|
|
71
|
-
"id" TEXT NOT NULL,
|
|
72
|
-
"formId" TEXT NOT NULL,
|
|
73
|
-
"version" INTEGER NOT NULL,
|
|
74
|
-
"fields" JSONB NOT NULL,
|
|
75
|
-
"notes" TEXT,
|
|
76
|
-
"createdById" TEXT,
|
|
77
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
78
|
-
CONSTRAINT "actuate_form_schema_versions_pkey" PRIMARY KEY ("id")
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
CREATE UNIQUE INDEX "actuate_form_schema_versions_formId_version_key"
|
|
82
|
-
ON "actuate_form_schema_versions" ("formId", "version");
|
|
83
|
-
CREATE INDEX "actuate_form_schema_versions_formId_idx"
|
|
84
|
-
ON "actuate_form_schema_versions" ("formId");
|
|
85
|
-
|
|
86
|
-
-- ---------------------------------------------------------------------------
|
|
87
|
-
-- actuate_form_submission_files
|
|
88
|
-
-- ---------------------------------------------------------------------------
|
|
89
|
-
CREATE TABLE "actuate_form_submission_files" (
|
|
90
|
-
"id" TEXT NOT NULL,
|
|
91
|
-
"submissionId" TEXT NOT NULL,
|
|
92
|
-
"fieldKey" TEXT NOT NULL,
|
|
93
|
-
"mediaAssetId" TEXT,
|
|
94
|
-
"fileName" TEXT NOT NULL,
|
|
95
|
-
"mimeType" TEXT NOT NULL,
|
|
96
|
-
"sizeBytes" INTEGER NOT NULL,
|
|
97
|
-
"storageKey" TEXT NOT NULL,
|
|
98
|
-
"publicUrl" TEXT,
|
|
99
|
-
"secureDownloadUrl" TEXT,
|
|
100
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
101
|
-
CONSTRAINT "actuate_form_submission_files_pkey" PRIMARY KEY ("id")
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
CREATE INDEX "actuate_form_submission_files_submissionId_idx"
|
|
105
|
-
ON "actuate_form_submission_files" ("submissionId");
|
|
106
|
-
|
|
107
|
-
ALTER TABLE "actuate_form_submission_files"
|
|
108
|
-
ADD CONSTRAINT "actuate_form_submission_files_submissionId_fkey"
|
|
109
|
-
FOREIGN KEY ("submissionId") REFERENCES "actuate_form_submissions"("id")
|
|
110
|
-
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
111
|
-
|
|
112
|
-
-- ---------------------------------------------------------------------------
|
|
113
|
-
-- actuate_form_webhooks
|
|
114
|
-
-- ---------------------------------------------------------------------------
|
|
115
|
-
CREATE TABLE "actuate_form_webhooks" (
|
|
116
|
-
"id" TEXT NOT NULL,
|
|
117
|
-
"formId" TEXT NOT NULL,
|
|
118
|
-
"url" TEXT NOT NULL,
|
|
119
|
-
"secret" TEXT NOT NULL,
|
|
120
|
-
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
121
|
-
"events" JSONB NOT NULL,
|
|
122
|
-
"retryCount" INTEGER NOT NULL DEFAULT 0,
|
|
123
|
-
"lastDeliveryAt" TIMESTAMP(3),
|
|
124
|
-
"lastDeliveryStatus" TEXT,
|
|
125
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
126
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
127
|
-
CONSTRAINT "actuate_form_webhooks_pkey" PRIMARY KEY ("id")
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
CREATE INDEX "actuate_form_webhooks_formId_idx" ON "actuate_form_webhooks" ("formId");
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
-- AlterEnum
|
|
2
|
-
-- Add OWNER and VIEWER to the UserRole enum. These are appended (Postgres
|
|
3
|
-
-- ALTER TYPE ... ADD VALUE appends), and must be committed in their own
|
|
4
|
-
-- migration before any later statement references the new values.
|
|
5
|
-
ALTER TYPE "UserRole" ADD VALUE IF NOT EXISTS 'OWNER';
|
|
6
|
-
ALTER TYPE "UserRole" ADD VALUE IF NOT EXISTS 'VIEWER';
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
-- CreateEnum
|
|
2
|
-
CREATE TYPE "InviteStatus" AS ENUM ('PENDING', 'ACCEPTED', 'EXPIRED', 'CANCELLED');
|
|
3
|
-
|
|
4
|
-
-- AlterTable: access-control lifecycle columns (all additive, nullable/defaulted)
|
|
5
|
-
ALTER TABLE "actuate_users" ADD COLUMN "suspendedAt" TIMESTAMP(3);
|
|
6
|
-
ALTER TABLE "actuate_users" ADD COLUMN "lockedAt" TIMESTAMP(3);
|
|
7
|
-
ALTER TABLE "actuate_users" ADD COLUMN "forcePasswordReset" BOOLEAN NOT NULL DEFAULT false;
|
|
8
|
-
ALTER TABLE "actuate_users" ADD COLUMN "mfaRequired" BOOLEAN NOT NULL DEFAULT false;
|
|
9
|
-
ALTER TABLE "actuate_users" ADD COLUMN "failedLoginCount" INTEGER NOT NULL DEFAULT 0;
|
|
10
|
-
ALTER TABLE "actuate_users" ADD COLUMN "lastActiveAt" TIMESTAMP(3);
|
|
11
|
-
ALTER TABLE "actuate_users" ADD COLUMN "invitedById" TEXT;
|
|
12
|
-
ALTER TABLE "actuate_users" ADD COLUMN "acceptedInviteAt" TIMESTAMP(3);
|
|
13
|
-
|
|
14
|
-
-- CreateTable
|
|
15
|
-
CREATE TABLE "actuate_invites" (
|
|
16
|
-
"id" TEXT NOT NULL,
|
|
17
|
-
"email" TEXT NOT NULL,
|
|
18
|
-
"role" "UserRole" NOT NULL,
|
|
19
|
-
"status" "InviteStatus" NOT NULL DEFAULT 'PENDING',
|
|
20
|
-
"tokenHash" TEXT NOT NULL,
|
|
21
|
-
"message" TEXT,
|
|
22
|
-
"invitedByUserId" TEXT,
|
|
23
|
-
"acceptedUserId" TEXT,
|
|
24
|
-
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
25
|
-
"acceptedAt" TIMESTAMP(3),
|
|
26
|
-
"cancelledAt" TIMESTAMP(3),
|
|
27
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
28
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
29
|
-
|
|
30
|
-
CONSTRAINT "actuate_invites_pkey" PRIMARY KEY ("id")
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
-- CreateIndex
|
|
34
|
-
CREATE INDEX "actuate_invites_email_idx" ON "actuate_invites"("email");
|
|
35
|
-
|
|
36
|
-
-- CreateIndex
|
|
37
|
-
CREATE INDEX "actuate_invites_tokenHash_idx" ON "actuate_invites"("tokenHash");
|
|
38
|
-
|
|
39
|
-
-- CreateIndex
|
|
40
|
-
CREATE INDEX "actuate_invites_status_idx" ON "actuate_invites"("status");
|