@taodigital/database 0.0.0-stage → 1.2.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.
Files changed (173) hide show
  1. package/README.md +21 -2
  2. package/dist/index.d.ts +58 -0
  3. package/dist/index.js +209 -0
  4. package/package.json +29 -4
  5. package/prisma/migrations/0000_init/migration.sql +220 -0
  6. package/prisma/migrations/0001_tenant_isolation/migration.sql +43 -0
  7. package/prisma/migrations/0002_app_runtime_role/migration.sql +14 -0
  8. package/prisma/migrations/0003_skill_taxonomy/migration.sql +30 -0
  9. package/prisma/migrations/0004_extended_models/migration.sql +215 -0
  10. package/prisma/migrations/0005_enhanced_test_artifacts/migration.sql +24 -0
  11. package/prisma/migrations/0006_tenant_settings/migration.sql +28 -0
  12. package/prisma/migrations/0007_project_slug/migration.sql +11 -0
  13. package/prisma/migrations/0008_project_crawl_config/migration.sql +3 -0
  14. package/prisma/migrations/0009_tenant_slug/migration.sql +11 -0
  15. package/prisma/migrations/0010_user_password/migration.sql +3 -0
  16. package/prisma/migrations/0011_oauth_connections/migration.sql +78 -0
  17. package/prisma/migrations/0012_agent_webhooks/migration.sql +46 -0
  18. package/prisma/migrations/0013_project_artifacts/migration.sql +27 -0
  19. package/prisma/migrations/0014_knowledge_chunks/migration.sql +37 -0
  20. package/prisma/migrations/20260626022056_platform_job_migration/migration.sql +44 -0
  21. package/prisma/migrations/20260626053339_kag_schema_update/migration.sql +27 -0
  22. package/prisma/migrations/20260626053340_restore_bm25_index/migration.sql +13 -0
  23. package/prisma/migrations/20260626063704_token_optimisation/migration.sql +86 -0
  24. package/prisma/migrations/20260626080000_job_name/migration.sql +2 -0
  25. package/prisma/migrations/20260626090000_rls_missing_tables/migration.sql +39 -0
  26. package/prisma/migrations/20260626100000_token_budget/migration.sql +21 -0
  27. package/prisma/migrations/20260626110000_screen_groups/migration.sql +42 -0
  28. package/prisma/migrations/20260626120000_artifact_intelligence/migration.sql +5 -0
  29. package/prisma/migrations/20260626130000_notifications/migration.sql +34 -0
  30. package/prisma/migrations/20260627100000_element_viewport/migration.sql +2 -0
  31. package/prisma/migrations/20260627100000_screenshot_cloud_url/migration.sql +2 -0
  32. package/prisma/migrations/20260627110000_screenshot_index/migration.sql +2 -0
  33. package/prisma/migrations/20260627140000_artifact_storage_key/migration.sql +3 -0
  34. package/prisma/migrations/20260627150000_screen_lifecycle/migration.sql +5 -0
  35. package/prisma/migrations/20260627160000_native_app_support/migration.sql +41 -0
  36. package/prisma/migrations/20260627200000_rls_missing_tables/migration.sql +57 -0
  37. package/prisma/migrations/20260627210000_llmcalllog_tasktype/migration.sql +1 -0
  38. package/prisma/migrations/20260628100000_element_enrichment/migration.sql +7 -0
  39. package/prisma/migrations/20260628110000_element_hash/migration.sql +6 -0
  40. package/prisma/migrations/20260628120000_screen_diff/migration.sql +20 -0
  41. package/prisma/migrations/20260628130000_probe_observations/migration.sql +19 -0
  42. package/prisma/migrations/20260629100000_visual_baseline_masking/migration.sql +1 -0
  43. package/prisma/migrations/20260629110000_testcase_viewports/migration.sql +1 -0
  44. package/prisma/migrations/20260630100000_visual_baseline_element_snapshot/migration.sql +1 -0
  45. package/prisma/migrations/20260630110000_git_branched_baselines/migration.sql +11 -0
  46. package/prisma/migrations/20260630120000_testcase_viewport_constraint/migration.sql +1 -0
  47. package/prisma/migrations/20260630130000_test_case_runs/migration.sql +22 -0
  48. package/prisma/migrations/20260630140000_perf_env_comments/migration.sql +68 -0
  49. package/prisma/migrations/20260630150000_testcase_gen_at/migration.sql +2 -0
  50. package/prisma/migrations/20260630160000_rls_catchup_late_tables/migration.sql +41 -0
  51. package/prisma/migrations/20260701100000_skill_file_diff_approval/migration.sql +9 -0
  52. package/prisma/migrations/20260701200000_workspace_connector/migration.sql +20 -0
  53. package/prisma/migrations/20260701220000_screen_a11y_security/migration.sql +2 -0
  54. package/prisma/migrations/20260702100000_ci_threshold_root_cause/migration.sql +2 -0
  55. package/prisma/migrations/20260702120000_medium_priority_gaps/migration.sql +28 -0
  56. package/prisma/migrations/20260702140000_testcase_v2_technique/migration.sql +7 -0
  57. package/prisma/migrations/20260702150000_add_app_field/migration.sql +40 -0
  58. package/prisma/migrations/20260702160000_add_requirement_model/migration.sql +62 -0
  59. package/prisma/migrations/20260702180000_add_invitation_model/migration.sql +53 -0
  60. package/prisma/migrations/20260702190000_suite_hierarchy_artifact_trace/migration.sql +28 -0
  61. package/prisma/migrations/20260702200000_project_member_access/migration.sql +31 -0
  62. package/prisma/migrations/20260703000000_add_system_config/migration.sql +11 -0
  63. package/prisma/migrations/20260703000000_custom_roles/migration.sql +29 -0
  64. package/prisma/migrations/20260703100000_platform_admin/migration.sql +11 -0
  65. package/prisma/migrations/20260703110000_add_extension_models/migration.sql +106 -0
  66. package/prisma/migrations/20260703120000_project_restricted_column/migration.sql +1 -0
  67. package/prisma/migrations/20260703200000_system_config_category_index/migration.sql +1 -0
  68. package/prisma/migrations/20260703210000_workspace_layer/migration.sql +24 -0
  69. package/prisma/migrations/20260703230000_workspace_agent_tokens/migration.sql +2 -0
  70. package/prisma/migrations/20260704000000_requirement_rls_policy/migration.sql +35 -0
  71. package/prisma/migrations/20260704100000_fix_oauth_auditlog_cascade/migration.sql +9 -0
  72. package/prisma/migrations/20260704110000_skillfile_approval_status/migration.sql +2 -0
  73. package/prisma/migrations/20260704120000_scenario_suspect_workspace/migration.sql +35 -0
  74. package/prisma/migrations/20260704130000_testcase_traceto_suspect_indexes/migration.sql +5 -0
  75. package/prisma/migrations/20260704140000_workspace_rls/migration.sql +19 -0
  76. package/prisma/migrations/20260704150000_project_cascade_deletes/migration.sql +125 -0
  77. package/prisma/migrations/20260705100000_platform_job_worker_id/migration.sql +12 -0
  78. package/prisma/migrations/20260705110000_screen_discovery_method/migration.sql +7 -0
  79. package/prisma/migrations/20260705120000_webhook_delivery/migration.sql +32 -0
  80. package/prisma/migrations/20260705130000_tenant_feature_flags/migration.sql +23 -0
  81. package/prisma/migrations/20260705140000_auth_sessions/migration.sql +30 -0
  82. package/prisma/migrations/20260705150000_fix_rls_wrong_session_var/migration.sql +51 -0
  83. package/prisma/migrations/20260705160000_testcase_flaky_quarantine/migration.sql +14 -0
  84. package/prisma/migrations/20260705170000_testcaserun_browser/migration.sql +6 -0
  85. package/prisma/migrations/20260705180000_allow_custom_roles/migration.sql +22 -0
  86. package/prisma/migrations/20260706050000_screen_markdown_extraction/migration.sql +8 -0
  87. package/prisma/migrations/20260706090000_add_lighthouse_to_performance_snapshot/migration.sql +4 -0
  88. package/prisma/migrations/20260706100000_add_lighthouse_bp_and_job_index/migration.sql +5 -0
  89. package/prisma/migrations/20260706110000_add_visual_diff_ai_summary/migration.sql +2 -0
  90. package/prisma/migrations/20260707120000_script_bundles/migration.sql +25 -0
  91. package/prisma/migrations/20260707130000_requirement_source_section/migration.sql +4 -0
  92. package/prisma/migrations/20260707140000_structured_skill_metadata/migration.sql +8 -0
  93. package/prisma/migrations/20260707150000_crawler_platform_primitives/migration.sql +112 -0
  94. package/prisma/migrations/20260707160000_screen_group_versioning/migration.sql +9 -0
  95. package/prisma/migrations/20260707170000_add_mfa_fields/migration.sql +24 -0
  96. package/prisma/migrations/20260707180000_add_missing_tables/migration.sql +158 -0
  97. package/prisma/migrations/20260707190000_add_missing_columns/migration.sql +15 -0
  98. package/prisma/migrations/20260707200000_add_plan_sessions/migration.sql +1 -0
  99. package/prisma/migrations/20260708100000_missing_columns_comprehensive/migration.sql +15 -0
  100. package/prisma/migrations/20260708200000_testcase_dataset_column/migration.sql +16 -0
  101. package/prisma/migrations/20260709100000_add_filename_to_native_app_build/migration.sql +1 -0
  102. package/prisma/migrations/20260709200000_cloud_url_visual_artifacts/migration.sql +6 -0
  103. package/prisma/migrations/20260714200000_add_cached_scenarios_to_artifact/migration.sql +4 -0
  104. package/prisma/migrations/20260715200000_screen_markdown_content/migration.sql +2 -0
  105. package/prisma/migrations/20260716100000_github_repo_coverage_tables/migration.sql +114 -0
  106. package/prisma/migrations/20260716200000_github_pr_script_validation/migration.sql +48 -0
  107. package/prisma/migrations/20260716210000_s3_content_keys/migration.sql +20 -0
  108. package/prisma/migrations/20260717220000_ide_push_token/migration.sql +21 -0
  109. package/prisma/migrations/20260717230000_ide_push_script_ids/migration.sql +2 -0
  110. package/prisma/migrations/20260730040000_add_step_evidence_and_validation/migration.sql +93 -0
  111. package/prisma/migrations/20260803000000_add_tenantId_to_test_data_row/migration.sql +40 -0
  112. package/prisma/migrations/20260804000000_add_project_restricted/migration.sql +6 -0
  113. package/prisma/migrations/20260804000000_add_user_avatar_url/migration.sql +4 -0
  114. package/prisma/migrations/20260805000000_add_auditlog_ipaddress/migration.sql +2 -0
  115. package/prisma/migrations/20260807000000_add_test_data_classification/migration.sql +18 -0
  116. package/prisma/migrations/20260807000001_add_test_case_notes/migration.sql +5 -0
  117. package/prisma/migrations/20260807000002_add_visual_baseline_browser_structured_steps/migration.sql +11 -0
  118. package/prisma/migrations/20260807100000_add_tenant_plan_config/migration.sql +14 -0
  119. package/prisma/migrations/20260808000000_agent_token_missing_columns/migration.sql +22 -0
  120. package/prisma/migrations/20260808000001_visual_diff_image_and_threshold/migration.sql +8 -0
  121. package/prisma/migrations/20260808000002_ssoconfig_email_domains/migration.sql +7 -0
  122. package/prisma/migrations/20260808000003_project_status_description_updatedat/migration.sql +7 -0
  123. package/prisma/migrations/20260814000000_workspace_require_mfa/migration.sql +2 -0
  124. package/prisma/migrations/20260814000001_add_screenshot_dpr/migration.sql +2 -0
  125. package/prisma/migrations/20260818000000_add_content_hash_to_test_case/migration.sql +6 -0
  126. package/prisma/migrations/20260818000001_add_grounding_hash_to_test_case/migration.sql +3 -0
  127. package/prisma/migrations/20260819000000_coverage_mapping_cross_encoder_fields/migration.sql +3 -0
  128. package/prisma/migrations/20260820000000_add_locators_json_to_test_case/migration.sql +6 -0
  129. package/prisma/migrations/20260820000001_add_test_case_version/migration.sql +27 -0
  130. package/prisma/migrations/20260826000000_add_capture_step_screenshots/migration.sql +1 -0
  131. package/prisma/migrations/20260903000000_add_platform_job_dlq/migration.sql +10 -0
  132. package/prisma/migrations/20260903000002_add_versioning_tables/migration.sql +38 -0
  133. package/prisma/migrations/20260903000003_add_learning_models/migration.sql +71 -0
  134. package/prisma/migrations/20260903000004_add_workspace_agent_prompts/migration.sql +33 -0
  135. package/prisma/migrations/20260903000005_add_config_history/migration.sql +70 -0
  136. package/prisma/migrations/20260903000006_add_skill_file_config/migration.sql +24 -0
  137. package/prisma/migrations/20260904000000_add_agent_prompt_platform_table/migration.sql +23 -0
  138. package/prisma/migrations/20260904180424_rbac_role_configs_admin_roles/migration.sql +606 -0
  139. package/prisma/migrations/20260907000000_fix_testcase_timestamps/migration.sql +13 -0
  140. package/prisma/migrations/20260907000001_add_artifact_imported_suite_id/migration.sql +1 -0
  141. package/prisma/migrations/20260907000002_add_user_login_tracking/migration.sql +9 -0
  142. package/prisma/migrations/20260907000003_add_artifact_import_tracking/migration.sql +9 -0
  143. package/prisma/migrations/20260907000004_add_artifact_version_chain/migration.sql +18 -0
  144. package/prisma/migrations/20260908000000_add_project_vsa_enabled/migration.sql +2 -0
  145. package/prisma/migrations/20260908000001_rbac_migration_catchup/migration.sql +314 -0
  146. package/prisma/migrations/20260908000002_fix_role_configs_empty_permissions/migration.sql +22 -0
  147. package/prisma/migrations/20260908000003_sync_builtin_role_permissions/migration.sql +38 -0
  148. package/prisma/migrations/20260909000000_add_filepath_to_testscript/migration.sql +5 -0
  149. package/prisma/migrations/20260909000001_add_alignment_result_table/migration.sql +31 -0
  150. package/prisma/migrations/20260910000000_add_admin_mfa/migration.sql +35 -0
  151. package/prisma/migrations/20260910000000_add_dom_snapshot_cloud_url/migration.sql +2 -0
  152. package/prisma/migrations/20260910000001_add_requires_auth_to_screen/migration.sql +1 -0
  153. package/prisma/migrations/20260910000002_add_screen_requires_auth/migration.sql +2 -0
  154. package/prisma/migrations/20260910000003_add_admin_auth_sessions/migration.sql +17 -0
  155. package/prisma/migrations/20260916000001_add_admin_last_login/migration.sql +1 -0
  156. package/prisma/migrations/20260916000002_add_admin_failed_login/migration.sql +2 -0
  157. package/prisma/migrations/20260916000003_seed_system_tenant/migration.sql +6 -0
  158. package/prisma/migrations/20260918000000_fix_permissions_comprehensive/migration.sql +63 -0
  159. package/prisma/migrations/20260924000000_add_screen_role_access/migration.sql +2 -0
  160. package/prisma/migrations/20260928000000_add_navigation_graph/migration.sql +41 -0
  161. package/prisma/migrations/20260929000000_artifact_content_hash_suite_unique/migration.sql +25 -0
  162. package/prisma/migrations/20260929000000_navigation_graph_unique_constraint/migration.sql +5 -0
  163. package/prisma/migrations/20260929000001_add_membership_status/migration.sql +7 -0
  164. package/prisma/migrations/20260929000002_add_sso_config_scim_token_hash/migration.sql +8 -0
  165. package/prisma/migrations/20261005000001_jobs_workers_hardening/migration.sql +63 -0
  166. package/prisma/migrations/20261009000001_add_suite_category/migration.sql +2 -0
  167. package/prisma/migrations/20261009000002_add_testcase_approved_fields/migration.sql +3 -0
  168. package/prisma/migrations/20261012_auto_version_history/migration.sql +111 -0
  169. package/prisma/migrations/20261015000001_traceability_alignment_gaps/migration.sql +11 -0
  170. package/prisma/migrations/20261028000001_context_intelligence_p1_p7/migration.sql +76 -0
  171. package/prisma/migrations/migration_lock.toml +3 -0
  172. package/prisma/schema.prisma +2901 -0
  173. package/prisma/seed.ts +1262 -0
@@ -0,0 +1,2 @@
1
+ -- Add human-readable name to PlatformJob for tracking (format: EventName_Date_timestamp)
2
+ ALTER TABLE "PlatformJob" ADD COLUMN "name" TEXT;
@@ -0,0 +1,39 @@
1
+ -- ============================================================================
2
+ -- RLS FOR MISSING TABLES — extends 0001_tenant_isolation
3
+ --
4
+ -- This migration applies Row-Level Security to tables that were added after
5
+ -- the initial tenant isolation migration (0001_tenant_isolation). All tables
6
+ -- listed here follow the same pattern: a "tenantId" column scoped to the
7
+ -- owning tenant, isolated via the app.current_tenant session variable.
8
+ --
9
+ -- Tables covered here (NOT in 0001_tenant_isolation):
10
+ -- PlatformJob, UserSession, LLMCallLog, TokenBudget, OAuthConnection,
11
+ -- ElementFingerprint, TestRun, TestResult, ProjectArtifact, VisualBaseline,
12
+ -- VisualDiff, HumanReviewItem, AgentToken, Webhook, KnowledgeChunk,
13
+ -- TenantSetting
14
+ -- ============================================================================
15
+
16
+ DO $$
17
+ DECLARE
18
+ t text;
19
+ tenant_tables text[] := ARRAY[
20
+ 'PlatformJob','UserSession','LLMCallLog','TokenBudget','OAuthConnection',
21
+ 'ElementFingerprint','TestRun','TestResult','ProjectArtifact','VisualBaseline',
22
+ 'VisualDiff','HumanReviewItem','AgentToken','Webhook','KnowledgeChunk',
23
+ 'TenantSetting'
24
+ ];
25
+ BEGIN
26
+ FOREACH t IN ARRAY tenant_tables LOOP
27
+ EXECUTE format('ALTER TABLE "%s" ENABLE ROW LEVEL SECURITY;', t);
28
+ EXECUTE format('ALTER TABLE "%s" FORCE ROW LEVEL SECURITY;', t);
29
+ BEGIN
30
+ EXECUTE format($f$
31
+ CREATE POLICY tenant_isolation ON "%s"
32
+ USING ("tenantId" = current_setting('app.current_tenant', true))
33
+ WITH CHECK ("tenantId" = current_setting('app.current_tenant', true));
34
+ $f$, t);
35
+ EXCEPTION WHEN duplicate_object THEN
36
+ NULL; -- policy already exists, skip
37
+ END;
38
+ END LOOP;
39
+ END $$;
@@ -0,0 +1,21 @@
1
+ -- TokenBudget: per-tenant monthly token and USD spending limits with running counters.
2
+ CREATE TABLE IF NOT EXISTS "TokenBudget" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "monthlyTokenCap" INTEGER,
6
+ "monthlyUsdCap" DOUBLE PRECISION,
7
+ "alertAtPercent" INTEGER NOT NULL DEFAULT 80,
8
+ "currentMonthTokens" INTEGER NOT NULL DEFAULT 0,
9
+ "currentMonthUsd" DOUBLE PRECISION NOT NULL DEFAULT 0,
10
+ "lastResetAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ CONSTRAINT "TokenBudget_pkey" PRIMARY KEY ("id")
13
+ );
14
+
15
+ CREATE UNIQUE INDEX IF NOT EXISTS "TokenBudget_tenantId_key" ON "TokenBudget"("tenantId");
16
+
17
+ DO $$ BEGIN
18
+ ALTER TABLE "TokenBudget" ADD CONSTRAINT "TokenBudget_tenantId_fkey"
19
+ FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
20
+ EXCEPTION WHEN duplicate_object THEN NULL;
21
+ END $$;
@@ -0,0 +1,42 @@
1
+ -- ScreenGroup: AI-generated semantic grouping of screens during post-crawl
2
+
3
+ CREATE TABLE IF NOT EXISTS "ScreenGroup" (
4
+ "id" TEXT NOT NULL,
5
+ "tenantId" TEXT NOT NULL,
6
+ "projectId" TEXT NOT NULL,
7
+ "name" TEXT NOT NULL,
8
+ "slug" TEXT NOT NULL,
9
+ "description" TEXT,
10
+ "color" TEXT NOT NULL DEFAULT '#6FD0E8',
11
+ "icon" TEXT NOT NULL DEFAULT '◈',
12
+ "order" INTEGER NOT NULL DEFAULT 0,
13
+ CONSTRAINT "ScreenGroup_pkey" PRIMARY KEY ("id")
14
+ );
15
+
16
+ CREATE INDEX IF NOT EXISTS "ScreenGroup_tenantId_projectId_idx" ON "ScreenGroup"("tenantId", "projectId");
17
+
18
+ -- FK: ScreenGroup → Project
19
+ DO $$ BEGIN
20
+ ALTER TABLE "ScreenGroup" ADD CONSTRAINT "ScreenGroup_projectId_fkey"
21
+ FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
22
+ EXCEPTION WHEN duplicate_object THEN NULL;
23
+ END $$;
24
+
25
+ -- Add groupId to Screen
26
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "groupId" TEXT;
27
+
28
+ -- FK: Screen → ScreenGroup
29
+ DO $$ BEGIN
30
+ ALTER TABLE "Screen" ADD CONSTRAINT "Screen_groupId_fkey"
31
+ FOREIGN KEY ("groupId") REFERENCES "ScreenGroup"("id") ON DELETE SET NULL ON UPDATE CASCADE;
32
+ EXCEPTION WHEN duplicate_object THEN NULL;
33
+ END $$;
34
+
35
+ -- RLS for ScreenGroup
36
+ ALTER TABLE "ScreenGroup" ENABLE ROW LEVEL SECURITY;
37
+
38
+ DO $$ BEGIN
39
+ CREATE POLICY "tenant_isolation" ON "ScreenGroup"
40
+ USING ("tenantId" = current_setting('app.tenant_id', true));
41
+ EXCEPTION WHEN duplicate_object THEN NULL;
42
+ END $$;
@@ -0,0 +1,5 @@
1
+ -- Add AI-generated intelligence fields to ProjectArtifact
2
+ ALTER TABLE "ProjectArtifact" ADD COLUMN IF NOT EXISTS "summary" TEXT;
3
+ ALTER TABLE "ProjectArtifact" ADD COLUMN IF NOT EXISTS "keywords" TEXT[] NOT NULL DEFAULT '{}';
4
+ ALTER TABLE "ProjectArtifact" ADD COLUMN IF NOT EXISTS "docType" TEXT;
5
+ ALTER TABLE "ProjectArtifact" ADD COLUMN IF NOT EXISTS "chunkCount" INTEGER NOT NULL DEFAULT 1;
@@ -0,0 +1,34 @@
1
+ -- Add Notification and NotificationPreference tables
2
+
3
+ CREATE TABLE IF NOT EXISTS "Notification" (
4
+ "id" TEXT NOT NULL,
5
+ "tenantId" TEXT NOT NULL,
6
+ "userId" TEXT NOT NULL,
7
+ "type" TEXT NOT NULL,
8
+ "title" TEXT NOT NULL,
9
+ "body" TEXT NOT NULL,
10
+ "metadata" JSONB,
11
+ "read" BOOLEAN NOT NULL DEFAULT false,
12
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+ CONSTRAINT "Notification_pkey" PRIMARY KEY ("id"),
14
+ CONSTRAINT "Notification_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE CASCADE,
15
+ CONSTRAINT "Notification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE
16
+ );
17
+
18
+ CREATE INDEX IF NOT EXISTS "Notification_tenantId_userId_read_idx" ON "Notification"("tenantId", "userId", "read");
19
+ CREATE INDEX IF NOT EXISTS "Notification_tenantId_createdAt_idx" ON "Notification"("tenantId", "createdAt");
20
+
21
+ CREATE TABLE IF NOT EXISTS "NotificationPreference" (
22
+ "id" TEXT NOT NULL,
23
+ "tenantId" TEXT NOT NULL,
24
+ "userId" TEXT NOT NULL,
25
+ "eventType" TEXT NOT NULL,
26
+ "inApp" BOOLEAN NOT NULL DEFAULT true,
27
+ "email" BOOLEAN NOT NULL DEFAULT true,
28
+ CONSTRAINT "NotificationPreference_pkey" PRIMARY KEY ("id"),
29
+ CONSTRAINT "NotificationPreference_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE CASCADE,
30
+ CONSTRAINT "NotificationPreference_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE,
31
+ CONSTRAINT "NotificationPreference_userId_tenantId_eventType_key" UNIQUE ("userId", "tenantId", "eventType")
32
+ );
33
+
34
+ CREATE INDEX IF NOT EXISTS "NotificationPreference_tenantId_userId_idx" ON "NotificationPreference"("tenantId", "userId");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "Element" ADD COLUMN IF NOT EXISTS "viewport" TEXT NOT NULL DEFAULT 'DESKTOP';
2
+ CREATE INDEX IF NOT EXISTS "Element_tenantId_screenId_viewport_idx" ON "Element"("tenantId", "screenId", "viewport");
@@ -0,0 +1,2 @@
1
+ -- Add cloud storage URL to Screenshot for S3/R2 hosted images
2
+ ALTER TABLE "Screenshot" ADD COLUMN "cloudUrl" TEXT;
@@ -0,0 +1,2 @@
1
+ -- Index for fast latest-screenshot lookup per screen
2
+ CREATE INDEX IF NOT EXISTS "Screenshot_screenId_version_idx" ON "Screenshot"("screenId", "version" DESC);
@@ -0,0 +1,3 @@
1
+ -- Add storageKey to ProjectArtifact for original file storage in S3/R2.
2
+ -- Nullable: null means original not stored in cloud (markdown-only artifact).
3
+ ALTER TABLE "ProjectArtifact" ADD COLUMN IF NOT EXISTS "storageKey" TEXT;
@@ -0,0 +1,5 @@
1
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "status" TEXT NOT NULL DEFAULT 'ACTIVE';
2
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "lastCrawlJobId" TEXT;
3
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "removedAt" TIMESTAMP(3);
4
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "removalReason" TEXT;
5
+ CREATE INDEX IF NOT EXISTS "Screen_tenantId_projectId_status_idx" ON "Screen"("tenantId", "projectId", "status");
@@ -0,0 +1,41 @@
1
+ -- Native app build upload support
2
+
3
+ -- Project.appType: web | android | ios | windows | macos | electron
4
+ ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "appType" TEXT;
5
+
6
+ -- PlatformJob device/Appium metadata columns
7
+ ALTER TABLE "PlatformJob" ADD COLUMN IF NOT EXISTS "deviceModel" TEXT;
8
+ ALTER TABLE "PlatformJob" ADD COLUMN IF NOT EXISTS "osVersion" TEXT;
9
+ ALTER TABLE "PlatformJob" ADD COLUMN IF NOT EXISTS "deviceFarm" TEXT;
10
+ ALTER TABLE "PlatformJob" ADD COLUMN IF NOT EXISTS "appiumSessionId" TEXT;
11
+
12
+ -- NativeAppBuild: stores upload metadata (S3 path, platform, file format, etc.)
13
+ CREATE TABLE IF NOT EXISTS "NativeAppBuild" (
14
+ "id" TEXT NOT NULL,
15
+ "tenantId" TEXT NOT NULL,
16
+ "projectId" TEXT NOT NULL,
17
+ "platform" TEXT NOT NULL,
18
+ "fileFormat" TEXT NOT NULL,
19
+ "s3Path" TEXT NOT NULL,
20
+ "packageName" TEXT,
21
+ "version" TEXT,
22
+ "uploadedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
23
+ CONSTRAINT "NativeAppBuild_pkey" PRIMARY KEY ("id"),
24
+ CONSTRAINT "NativeAppBuild_projectId_fkey"
25
+ FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE
26
+ );
27
+
28
+ CREATE INDEX IF NOT EXISTS "NativeAppBuild_tenantId_projectId_idx" ON "NativeAppBuild"("tenantId", "projectId");
29
+
30
+ -- RLS: row-level security on NativeAppBuild (same pattern as other tables)
31
+ ALTER TABLE "NativeAppBuild" ENABLE ROW LEVEL SECURITY;
32
+ ALTER TABLE "NativeAppBuild" FORCE ROW LEVEL SECURITY;
33
+
34
+ DO $$
35
+ BEGIN
36
+ CREATE POLICY tenant_isolation ON "NativeAppBuild"
37
+ USING ("tenantId" = current_setting('app.current_tenant', true))
38
+ WITH CHECK ("tenantId" = current_setting('app.current_tenant', true));
39
+ EXCEPTION WHEN duplicate_object THEN
40
+ NULL;
41
+ END $$;
@@ -0,0 +1,57 @@
1
+ -- ============================================================================
2
+ -- RLS FOR MISSING TABLES — extends 20260626090000_rls_missing_tables
3
+ --
4
+ -- Applies Row-Level Security to tables that were added after the previous
5
+ -- RLS catch-up migration. All tables follow the same pattern used throughout
6
+ -- this project: a "tenantId" column scoped via the app.current_tenant
7
+ -- session variable.
8
+ --
9
+ -- Tables covered here:
10
+ -- ScreenDiff, ProbeObservation, TestCaseRun, Notification,
11
+ -- NotificationPreference
12
+ --
13
+ -- NOTE (fixed post-hoc): ScreenDiff, ProbeObservation, and TestCaseRun are
14
+ -- actually created by LATER migrations (20260628120000_screen_diff,
15
+ -- 20260628130000_probe_observations, 20260630130000_test_case_runs). On any
16
+ -- database that evolved incrementally in dev those tables already existed
17
+ -- by the time this ran, so it never failed there — but on a genuinely fresh
18
+ -- `prisma migrate deploy` this migration fails outright with
19
+ -- "relation does not exist" before those tables are ever created, which
20
+ -- breaks bootstrapping a brand-new environment/region from scratch.
21
+ -- Guarding each statement with a to_regclass() existence check makes this
22
+ -- migration a no-op for tables that don't exist yet without changing its
23
+ -- effect anywhere it already succeeded. RLS for the three later tables is
24
+ -- finished off for real in 20260630160000_rls_catchup_late_tables, once
25
+ -- they're guaranteed to exist.
26
+ --
27
+ -- If this migration's checksum was already recorded by `prisma migrate
28
+ -- deploy` against a database, applying this edited file will fail with a
29
+ -- "migration modified" error. Resolve with:
30
+ -- npx prisma migrate resolve --applied 20260627200000_rls_missing_tables
31
+ -- ============================================================================
32
+
33
+ DO $$
34
+ DECLARE
35
+ t text;
36
+ tenant_tables text[] := ARRAY[
37
+ 'ScreenDiff','ProbeObservation','TestCaseRun','Notification',
38
+ 'NotificationPreference'
39
+ ];
40
+ BEGIN
41
+ FOREACH t IN ARRAY tenant_tables LOOP
42
+ IF to_regclass(format('"%s"', t)) IS NULL THEN
43
+ CONTINUE; -- table doesn't exist yet on a fresh deploy; caught up later
44
+ END IF;
45
+ EXECUTE format('ALTER TABLE "%s" ENABLE ROW LEVEL SECURITY;', t);
46
+ EXECUTE format('ALTER TABLE "%s" FORCE ROW LEVEL SECURITY;', t);
47
+ BEGIN
48
+ EXECUTE format($f$
49
+ CREATE POLICY tenant_isolation ON "%s"
50
+ USING ("tenantId" = current_setting('app.current_tenant', true))
51
+ WITH CHECK ("tenantId" = current_setting('app.current_tenant', true));
52
+ $f$, t);
53
+ EXCEPTION WHEN duplicate_object THEN
54
+ NULL; -- policy already exists, skip
55
+ END;
56
+ END LOOP;
57
+ END $$;
@@ -0,0 +1 @@
1
+ ALTER TABLE "LLMCallLog" ADD COLUMN IF NOT EXISTS "taskType" TEXT;
@@ -0,0 +1,7 @@
1
+ -- Phase 1: Element model enrichment — bounding rect, aria state, parent landmark
2
+ ALTER TABLE "Element" ADD COLUMN IF NOT EXISTS "boundingRect" JSONB;
3
+ ALTER TABLE "Element" ADD COLUMN IF NOT EXISTS "ariaState" JSONB;
4
+ ALTER TABLE "Element" ADD COLUMN IF NOT EXISTS "parentLandmark" TEXT;
5
+
6
+ CREATE INDEX IF NOT EXISTS "Element_tenantId_screenId_parentLandmark_idx"
7
+ ON "Element"("tenantId", "screenId", "parentLandmark");
@@ -0,0 +1,6 @@
1
+ -- Phase 2: Element hash for stale-test detection
2
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "elementHash" TEXT;
3
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "elementHashChangedAt" TIMESTAMP(3);
4
+
5
+ CREATE INDEX IF NOT EXISTS "Screen_tenantId_projectId_elementHashChangedAt_idx"
6
+ ON "Screen"("tenantId", "projectId", "elementHashChangedAt");
@@ -0,0 +1,20 @@
1
+ -- Phase 3: Perceptual screenshot diff
2
+ CREATE TABLE IF NOT EXISTS "ScreenDiff" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "projectId" TEXT NOT NULL,
6
+ "screenId" TEXT NOT NULL,
7
+ "fromVersion" INTEGER NOT NULL,
8
+ "toVersion" INTEGER NOT NULL,
9
+ "pHashDistance" DOUBLE PRECISION NOT NULL,
10
+ "changeLevel" TEXT NOT NULL,
11
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ CONSTRAINT "ScreenDiff_pkey" PRIMARY KEY ("id"),
13
+ CONSTRAINT "ScreenDiff_screenId_fkey"
14
+ FOREIGN KEY ("screenId") REFERENCES "Screen"("id") ON DELETE CASCADE ON UPDATE CASCADE,
15
+ CONSTRAINT "ScreenDiff_screenId_fromVersion_toVersion_key"
16
+ UNIQUE ("screenId", "fromVersion", "toVersion")
17
+ );
18
+
19
+ CREATE INDEX IF NOT EXISTS "ScreenDiff_tenantId_projectId_idx" ON "ScreenDiff"("tenantId", "projectId");
20
+ CREATE INDEX IF NOT EXISTS "ScreenDiff_tenantId_screenId_idx" ON "ScreenDiff"("tenantId", "screenId");
@@ -0,0 +1,19 @@
1
+ -- Phase 5: Structured probe observations
2
+ CREATE TABLE IF NOT EXISTS "ProbeObservation" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "projectId" TEXT NOT NULL,
6
+ "screenId" TEXT NOT NULL,
7
+ "elementMeaning" TEXT NOT NULL,
8
+ "observationType" TEXT NOT NULL,
9
+ "observedText" TEXT NOT NULL,
10
+ "triggeredBy" TEXT NOT NULL,
11
+ "observedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ CONSTRAINT "ProbeObservation_pkey" PRIMARY KEY ("id"),
13
+ CONSTRAINT "ProbeObservation_screenId_fkey"
14
+ FOREIGN KEY ("screenId") REFERENCES "Screen"("id") ON DELETE CASCADE ON UPDATE CASCADE
15
+ );
16
+
17
+ CREATE INDEX IF NOT EXISTS "ProbeObservation_tenantId_projectId_idx" ON "ProbeObservation"("tenantId", "projectId");
18
+ CREATE INDEX IF NOT EXISTS "ProbeObservation_tenantId_screenId_idx" ON "ProbeObservation"("tenantId", "screenId");
19
+ CREATE INDEX IF NOT EXISTS "ProbeObservation_tenantId_screenId_observationType_idx" ON "ProbeObservation"("tenantId", "screenId", "observationType");
@@ -0,0 +1 @@
1
+ ALTER TABLE "VisualBaseline" ADD COLUMN IF NOT EXISTS "ignoredRegions" JSONB NOT NULL DEFAULT '[]';
@@ -0,0 +1 @@
1
+ ALTER TABLE "TestCase" ADD COLUMN IF NOT EXISTS "viewports" JSONB NOT NULL DEFAULT '[]';
@@ -0,0 +1 @@
1
+ ALTER TABLE "VisualBaseline" ADD COLUMN "elementSnapshot" JSONB;
@@ -0,0 +1,11 @@
1
+ -- Add git branch/commit tracking to visual baselines
2
+ ALTER TABLE "VisualBaseline" ADD COLUMN "gitBranch" TEXT NOT NULL DEFAULT 'main';
3
+ ALTER TABLE "VisualBaseline" ADD COLUMN "gitCommit" TEXT;
4
+ ALTER TABLE "VisualBaseline" ADD COLUMN "domSnapshotPath" TEXT;
5
+
6
+ -- Add DOM snapshot path to Screen
7
+ ALTER TABLE "Screen" ADD COLUMN "domSnapshotPath" TEXT;
8
+
9
+ -- Drop old unique constraint and replace with branch-aware one
10
+ DROP INDEX IF EXISTS "VisualBaseline_screenId_viewport_key";
11
+ CREATE UNIQUE INDEX "VisualBaseline_screenId_viewport_gitBranch_key" ON "VisualBaseline"("screenId", "viewport", "gitBranch");
@@ -0,0 +1 @@
1
+ ALTER TABLE "TestCase" ADD COLUMN "viewportConstraint" TEXT NOT NULL DEFAULT 'ALL';
@@ -0,0 +1,22 @@
1
+ -- CreateTable: per-test-case execution run (distinct from suite-level TestRun)
2
+ CREATE TABLE "TestCaseRun" (
3
+ "id" TEXT NOT NULL,
4
+ "testCaseId" TEXT NOT NULL,
5
+ "tenantId" TEXT NOT NULL,
6
+ "status" TEXT NOT NULL DEFAULT 'PENDING',
7
+ "executionPlan" JSONB,
8
+ "stepResults" JSONB,
9
+ "totalDuration" INTEGER,
10
+ "errorStep" INTEGER,
11
+ "errorMessage" TEXT,
12
+ "screenshotPath" TEXT,
13
+ "viewport" TEXT NOT NULL DEFAULT 'DESKTOP',
14
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
+ "completedAt" TIMESTAMP(3),
16
+ CONSTRAINT "TestCaseRun_pkey" PRIMARY KEY ("id")
17
+ );
18
+
19
+ ALTER TABLE "TestCaseRun" ADD CONSTRAINT "TestCaseRun_testCaseId_fkey"
20
+ FOREIGN KEY ("testCaseId") REFERENCES "TestCase"("id") ON DELETE CASCADE ON UPDATE CASCADE;
21
+
22
+ CREATE INDEX "TestCaseRun_tenantId_testCaseId_idx" ON "TestCaseRun"("tenantId", "testCaseId");
@@ -0,0 +1,68 @@
1
+ -- CreateTable PerformanceSnapshot
2
+ CREATE TABLE "PerformanceSnapshot" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "screenId" TEXT NOT NULL,
6
+ "crawlJobId" TEXT NOT NULL,
7
+ "lcp" DOUBLE PRECISION,
8
+ "fcp" DOUBLE PRECISION,
9
+ "cls" DOUBLE PRECISION,
10
+ "ttfb" DOUBLE PRECISION,
11
+ "viewport" TEXT NOT NULL DEFAULT 'DESKTOP',
12
+ "capturedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+
14
+ CONSTRAINT "PerformanceSnapshot_pkey" PRIMARY KEY ("id")
15
+ );
16
+
17
+ -- CreateTable ProjectEnvironment
18
+ CREATE TABLE "ProjectEnvironment" (
19
+ "id" TEXT NOT NULL,
20
+ "tenantId" TEXT NOT NULL,
21
+ "projectId" TEXT NOT NULL,
22
+ "name" TEXT NOT NULL,
23
+ "baseUrl" TEXT NOT NULL,
24
+ "credentials_enc" TEXT,
25
+ "isDefault" BOOLEAN NOT NULL DEFAULT false,
26
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
27
+ "updatedAt" TIMESTAMP(3) NOT NULL,
28
+
29
+ CONSTRAINT "ProjectEnvironment_pkey" PRIMARY KEY ("id")
30
+ );
31
+
32
+ -- CreateTable Comment
33
+ CREATE TABLE "Comment" (
34
+ "id" TEXT NOT NULL,
35
+ "tenantId" TEXT NOT NULL,
36
+ "parentType" TEXT NOT NULL,
37
+ "parentId" TEXT NOT NULL,
38
+ "userId" TEXT NOT NULL,
39
+ "body" TEXT NOT NULL,
40
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
41
+ "updatedAt" TIMESTAMP(3) NOT NULL,
42
+
43
+ CONSTRAINT "Comment_pkey" PRIMARY KEY ("id")
44
+ );
45
+
46
+ -- CreateIndex
47
+ CREATE INDEX "PerformanceSnapshot_tenantId_screenId_idx" ON "PerformanceSnapshot"("tenantId", "screenId");
48
+ CREATE INDEX "PerformanceSnapshot_tenantId_crawlJobId_idx" ON "PerformanceSnapshot"("tenantId", "crawlJobId");
49
+
50
+ -- CreateIndex
51
+ CREATE INDEX "ProjectEnvironment_tenantId_projectId_idx" ON "ProjectEnvironment"("tenantId", "projectId");
52
+
53
+ -- CreateIndex
54
+ CREATE INDEX "Comment_tenantId_parentType_parentId_idx" ON "Comment"("tenantId", "parentType", "parentId");
55
+
56
+ -- Enable RLS
57
+ ALTER TABLE "PerformanceSnapshot" ENABLE ROW LEVEL SECURITY;
58
+ ALTER TABLE "ProjectEnvironment" ENABLE ROW LEVEL SECURITY;
59
+ ALTER TABLE "Comment" ENABLE ROW LEVEL SECURITY;
60
+
61
+ CREATE POLICY "tenant_isolation_perf" ON "PerformanceSnapshot"
62
+ USING (current_setting('app.tenant_id', true) = "tenantId");
63
+
64
+ CREATE POLICY "tenant_isolation_env" ON "ProjectEnvironment"
65
+ USING (current_setting('app.tenant_id', true) = "tenantId");
66
+
67
+ CREATE POLICY "tenant_isolation_comment" ON "Comment"
68
+ USING (current_setting('app.tenant_id', true) = "tenantId");
@@ -0,0 +1,2 @@
1
+ -- Add genAt (AI generation timestamp) to TestCase
2
+ ALTER TABLE "TestCase" ADD COLUMN IF NOT EXISTS "genAt" TIMESTAMP(3);
@@ -0,0 +1,41 @@
1
+ -- ============================================================================
2
+ -- RLS CATCH-UP FOR LATE TABLES — finishes what 20260627200000_rls_missing_tables
3
+ -- couldn't, for ScreenDiff, ProbeObservation, and TestCaseRun.
4
+ --
5
+ -- Those three tables are created by migrations that run AFTER
6
+ -- 20260627200000_rls_missing_tables (20260628120000_screen_diff,
7
+ -- 20260628130000_probe_observations, 20260630130000_test_case_runs), so the
8
+ -- earlier migration's attempt to enable RLS on them is now a guarded no-op
9
+ -- on a fresh database (see the note added there). This migration runs after
10
+ -- all three tables definitely exist and applies the same tenant-isolation
11
+ -- pattern used throughout the project.
12
+ --
13
+ -- Idempotent: safe to run even where 20260627200000 already succeeded in
14
+ -- applying RLS to these tables (e.g. a database that evolved incrementally
15
+ -- in dev, where the tables pre-existed) — ENABLE/FORCE ROW LEVEL SECURITY
16
+ -- are no-ops when already set, and policy creation is guarded against
17
+ -- duplicate_object.
18
+ -- ============================================================================
19
+
20
+ DO $$
21
+ DECLARE
22
+ t text;
23
+ tenant_tables text[] := ARRAY['ScreenDiff','ProbeObservation','TestCaseRun'];
24
+ BEGIN
25
+ FOREACH t IN ARRAY tenant_tables LOOP
26
+ IF to_regclass(format('"%s"', t)) IS NULL THEN
27
+ CONTINUE; -- defensive; should always exist by this point
28
+ END IF;
29
+ EXECUTE format('ALTER TABLE "%s" ENABLE ROW LEVEL SECURITY;', t);
30
+ EXECUTE format('ALTER TABLE "%s" FORCE ROW LEVEL SECURITY;', t);
31
+ BEGIN
32
+ EXECUTE format($f$
33
+ CREATE POLICY tenant_isolation ON "%s"
34
+ USING ("tenantId" = current_setting('app.current_tenant', true))
35
+ WITH CHECK ("tenantId" = current_setting('app.current_tenant', true));
36
+ $f$, t);
37
+ EXCEPTION WHEN duplicate_object THEN
38
+ NULL; -- policy already exists, skip
39
+ END;
40
+ END LOOP;
41
+ END $$;
@@ -0,0 +1,9 @@
1
+ -- Add diff tracking and approval status fields to SkillFile
2
+ ALTER TABLE "SkillFile" ADD COLUMN "priorContent" TEXT;
3
+ ALTER TABLE "SkillFile" ADD COLUMN "priorVersion" INTEGER;
4
+ ALTER TABLE "SkillFile" ADD COLUMN "priorGeneratedAt" TIMESTAMP(3);
5
+ ALTER TABLE "SkillFile" ADD COLUMN "changesSummary" TEXT;
6
+ ALTER TABLE "SkillFile" ADD COLUMN "approvalStatus" TEXT NOT NULL DEFAULT 'PENDING';
7
+
8
+ -- Backfill: existing approved files
9
+ UPDATE "SkillFile" SET "approvalStatus" = 'APPROVED' WHERE "approvedBy" IS NOT NULL;
@@ -0,0 +1,20 @@
1
+ -- CreateTable
2
+ CREATE TABLE "WorkspaceConnector" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "kind" TEXT NOT NULL,
6
+ "secretRef" TEXT NOT NULL DEFAULT 'local-aes256',
7
+ "config" JSONB,
8
+ "testOk" BOOLEAN NOT NULL DEFAULT false,
9
+ "testedAt" TIMESTAMP(3),
10
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ "updatedAt" TIMESTAMP(3) NOT NULL,
12
+
13
+ CONSTRAINT "WorkspaceConnector_pkey" PRIMARY KEY ("id")
14
+ );
15
+
16
+ -- CreateIndex
17
+ CREATE UNIQUE INDEX "WorkspaceConnector_tenantId_kind_key" ON "WorkspaceConnector"("tenantId", "kind");
18
+
19
+ -- CreateIndex
20
+ CREATE INDEX "WorkspaceConnector_tenantId_idx" ON "WorkspaceConnector"("tenantId");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "a11yViolations" JSONB;
2
+ ALTER TABLE "Screen" ADD COLUMN IF NOT EXISTS "securityHeaders" JSONB;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "ciFailureThreshold" INTEGER;
2
+ ALTER TABLE "TestResult" ADD COLUMN IF NOT EXISTS "rootCauseSummary" TEXT;
@@ -0,0 +1,28 @@
1
+ -- TestSuite: owner assignment
2
+ ALTER TABLE "TestSuite" ADD COLUMN IF NOT EXISTS "ownerUserId" TEXT;
3
+
4
+ -- TestResult: network timings + data-driven row
5
+ ALTER TABLE "TestResult" ADD COLUMN IF NOT EXISTS "networkTimings" JSONB;
6
+ ALTER TABLE "TestResult" ADD COLUMN IF NOT EXISTS "dataRow" JSONB;
7
+
8
+ -- Project: SLA threshold
9
+ ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "slaThreshold" INTEGER;
10
+
11
+ -- PerformanceSnapshot: Lighthouse scores
12
+ ALTER TABLE "PerformanceSnapshot" ADD COLUMN IF NOT EXISTS "lighthousePerf" INTEGER;
13
+ ALTER TABLE "PerformanceSnapshot" ADD COLUMN IF NOT EXISTS "lighthouseA11y" INTEGER;
14
+ ALTER TABLE "PerformanceSnapshot" ADD COLUMN IF NOT EXISTS "lighthouseSEO" INTEGER;
15
+ ALTER TABLE "PerformanceSnapshot" ADD COLUMN IF NOT EXISTS "lighthouseBP" INTEGER;
16
+ ALTER TABLE "PerformanceSnapshot" ADD COLUMN IF NOT EXISTS "lighthouseReport" JSONB;
17
+
18
+ -- SharedRunToken: shareable signed links
19
+ CREATE TABLE IF NOT EXISTS "SharedRunToken" (
20
+ "id" TEXT NOT NULL PRIMARY KEY,
21
+ "tenantId" TEXT NOT NULL,
22
+ "runId" TEXT NOT NULL,
23
+ "token" TEXT NOT NULL UNIQUE,
24
+ "expiresAt" TIMESTAMPTZ NOT NULL,
25
+ "createdAt" TIMESTAMPTZ NOT NULL DEFAULT now()
26
+ );
27
+ CREATE INDEX IF NOT EXISTS "SharedRunToken_tenantId_idx" ON "SharedRunToken"("tenantId");
28
+ CREATE INDEX IF NOT EXISTS "SharedRunToken_token_idx" ON "SharedRunToken"("token");
@@ -0,0 +1,7 @@
1
+ -- TestCase: v2 technique-of-record field
2
+ ALTER TABLE "TestCase" ADD COLUMN IF NOT EXISTS "techniqueOfRecord" TEXT;
3
+ ALTER TABLE "TestCase" ADD COLUMN IF NOT EXISTS "traceTo" TEXT;
4
+ ALTER TABLE "TestCase" ADD COLUMN IF NOT EXISTS "testDataInline" JSONB;
5
+
6
+ -- TestSuite: coverage reporting
7
+ ALTER TABLE "TestSuite" ADD COLUMN IF NOT EXISTS "coverageReport" JSONB;
@@ -0,0 +1,40 @@
1
+ -- CreateTable
2
+ CREATE TABLE "AppField" (
3
+ "id" TEXT NOT NULL,
4
+ "tenantId" TEXT NOT NULL,
5
+ "projectId" TEXT NOT NULL,
6
+ "fieldKey" TEXT NOT NULL,
7
+ "label" TEXT NOT NULL,
8
+ "elementRole" TEXT NOT NULL,
9
+ "dataBearing" BOOLEAN NOT NULL DEFAULT true,
10
+ "dataType" TEXT NOT NULL,
11
+ "required" BOOLEAN NOT NULL DEFAULT false,
12
+ "minLength" INTEGER,
13
+ "maxLength" INTEGER,
14
+ "minValue" DOUBLE PRECISION,
15
+ "maxValue" DOUBLE PRECISION,
16
+ "precision" INTEGER,
17
+ "regex" TEXT,
18
+ "enumValues" JSONB,
19
+ "piiClass" TEXT NOT NULL DEFAULT 'none',
20
+ "exampleValue" TEXT,
21
+ "relationGroup" TEXT,
22
+ "notes" TEXT,
23
+ "status" TEXT NOT NULL DEFAULT 'unconfirmed',
24
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
25
+ "updatedAt" TIMESTAMP(3) NOT NULL,
26
+
27
+ CONSTRAINT "AppField_pkey" PRIMARY KEY ("id")
28
+ );
29
+
30
+ -- CreateIndex
31
+ CREATE UNIQUE INDEX "AppField_tenantId_projectId_fieldKey_key" ON "AppField"("tenantId", "projectId", "fieldKey");
32
+
33
+ -- CreateIndex
34
+ CREATE INDEX "AppField_tenantId_projectId_idx" ON "AppField"("tenantId", "projectId");
35
+
36
+ -- AddForeignKey
37
+ ALTER TABLE "AppField" ADD CONSTRAINT "AppField_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
38
+
39
+ -- RowLevelSecurity (matches tenant isolation pattern used by all other tables)
40
+ ALTER TABLE "AppField" ENABLE ROW LEVEL SECURITY;