@penclipai/db 2026.704.0 → 2026.714.0

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 (122) hide show
  1. package/dist/backup-lib.test.js +1 -1
  2. package/dist/backup-lib.test.js.map +1 -1
  3. package/dist/check-migration-safety.d.ts +27 -0
  4. package/dist/check-migration-safety.d.ts.map +1 -0
  5. package/dist/check-migration-safety.js +811 -0
  6. package/dist/check-migration-safety.js.map +1 -0
  7. package/dist/check-migration-safety.test.d.ts +2 -0
  8. package/dist/check-migration-safety.test.d.ts.map +1 -0
  9. package/dist/check-migration-safety.test.js +391 -0
  10. package/dist/check-migration-safety.test.js.map +1 -0
  11. package/dist/client.test.js +743 -0
  12. package/dist/client.test.js.map +1 -1
  13. package/dist/issue-comment-derived-attribution-migration.test.d.ts +2 -0
  14. package/dist/issue-comment-derived-attribution-migration.test.d.ts.map +1 -0
  15. package/dist/issue-comment-derived-attribution-migration.test.js +287 -0
  16. package/dist/issue-comment-derived-attribution-migration.test.js.map +1 -0
  17. package/dist/migration-safety-baseline.d.ts +135 -0
  18. package/dist/migration-safety-baseline.d.ts.map +1 -0
  19. package/dist/migration-safety-baseline.js +150 -0
  20. package/dist/migration-safety-baseline.js.map +1 -0
  21. package/dist/migrations/0128_user_specific_secrets.sql +178 -0
  22. package/dist/migrations/0129_agent_api_key_responsible_user.sql +41 -0
  23. package/dist/migrations/0131_repair_run_responsible_user_context_refs.sql +67 -0
  24. package/dist/migrations/0132_issue_comment_derived_attribution_fast.sql +82 -0
  25. package/dist/migrations/0133_resource_membership_stars.sql +7 -0
  26. package/dist/migrations/0134_run_responsible_user_invariant.sql +211 -0
  27. package/dist/migrations/0135_repair_run_responsible_user_updated_at_sweep.sql +84 -0
  28. package/dist/migrations/0136_acpx_default_engine_migration.sql +97 -0
  29. package/dist/migrations/0137_skill_studio_server_foundation.sql +76 -0
  30. package/dist/migrations/0138_skill_studio_run_retention.sql +5 -0
  31. package/dist/migrations/0139_skill_studio_run_templates.sql +44 -0
  32. package/dist/migrations/0140_built_in_managed_resources.sql +43 -0
  33. package/dist/migrations/0141_heartbeat_runs_company_created_at_index.sql +2 -0
  34. package/dist/migrations/0142_company_search_sort_indexes.sql +3 -0
  35. package/dist/migrations/0143_cases_foundation.sql +248 -0
  36. package/dist/migrations/0144_case_document_annotations.sql +31 -0
  37. package/dist/migrations/0145_inbox_dismissal_snooze_kind.sql +15 -0
  38. package/dist/migrations/0146_routine_activity_gate.sql +3 -0
  39. package/dist/migrations/0147_cost_event_status.sql +1 -0
  40. package/dist/migrations/meta/_journal.json +132 -6
  41. package/dist/schema/agent_api_keys.d.ts +23 -0
  42. package/dist/schema/agent_api_keys.d.ts.map +1 -1
  43. package/dist/schema/agent_api_keys.js +1 -0
  44. package/dist/schema/agent_api_keys.js.map +1 -1
  45. package/dist/schema/agent_memberships.d.ts +17 -0
  46. package/dist/schema/agent_memberships.d.ts.map +1 -1
  47. package/dist/schema/agent_memberships.js +2 -0
  48. package/dist/schema/agent_memberships.js.map +1 -1
  49. package/dist/schema/built_in_managed_resources.d.ts +197 -0
  50. package/dist/schema/built_in_managed_resources.d.ts.map +1 -0
  51. package/dist/schema/built_in_managed_resources.js +22 -0
  52. package/dist/schema/built_in_managed_resources.js.map +1 -0
  53. package/dist/schema/cases.d.ts +982 -0
  54. package/dist/schema/cases.d.ts.map +1 -0
  55. package/dist/schema/cases.js +122 -0
  56. package/dist/schema/cases.js.map +1 -0
  57. package/dist/schema/companies.d.ts +17 -0
  58. package/dist/schema/companies.d.ts.map +1 -1
  59. package/dist/schema/companies.js +1 -0
  60. package/dist/schema/companies.js.map +1 -1
  61. package/dist/schema/company_secrets.d.ts +51 -0
  62. package/dist/schema/company_secrets.d.ts.map +1 -1
  63. package/dist/schema/company_secrets.js +27 -3
  64. package/dist/schema/company_secrets.js.map +1 -1
  65. package/dist/schema/company_skills.d.ts +788 -0
  66. package/dist/schema/company_skills.d.ts.map +1 -1
  67. package/dist/schema/company_skills.js +63 -0
  68. package/dist/schema/company_skills.js.map +1 -1
  69. package/dist/schema/cost_events.d.ts +17 -0
  70. package/dist/schema/cost_events.d.ts.map +1 -1
  71. package/dist/schema/cost_events.js +1 -0
  72. package/dist/schema/cost_events.js.map +1 -1
  73. package/dist/schema/document_annotation_comments.d.ts +17 -0
  74. package/dist/schema/document_annotation_comments.d.ts.map +1 -1
  75. package/dist/schema/document_annotation_comments.js +4 -1
  76. package/dist/schema/document_annotation_comments.js.map +1 -1
  77. package/dist/schema/document_annotation_threads.d.ts +17 -0
  78. package/dist/schema/document_annotation_threads.d.ts.map +1 -1
  79. package/dist/schema/document_annotation_threads.js +4 -1
  80. package/dist/schema/document_annotation_threads.js.map +1 -1
  81. package/dist/schema/heartbeat_runs.d.ts +17 -0
  82. package/dist/schema/heartbeat_runs.d.ts.map +1 -1
  83. package/dist/schema/heartbeat_runs.js +3 -0
  84. package/dist/schema/heartbeat_runs.js.map +1 -1
  85. package/dist/schema/inbox_dismissals.d.ts +36 -0
  86. package/dist/schema/inbox_dismissals.d.ts.map +1 -1
  87. package/dist/schema/inbox_dismissals.js +2 -0
  88. package/dist/schema/inbox_dismissals.js.map +1 -1
  89. package/dist/schema/index.d.ts +5 -1
  90. package/dist/schema/index.d.ts.map +1 -1
  91. package/dist/schema/index.js +5 -1
  92. package/dist/schema/index.js.map +1 -1
  93. package/dist/schema/issues.d.ts +34 -0
  94. package/dist/schema/issues.d.ts.map +1 -1
  95. package/dist/schema/issues.js +7 -0
  96. package/dist/schema/issues.js.map +1 -1
  97. package/dist/schema/project_memberships.d.ts +17 -0
  98. package/dist/schema/project_memberships.d.ts.map +1 -1
  99. package/dist/schema/project_memberships.js +2 -0
  100. package/dist/schema/project_memberships.js.map +1 -1
  101. package/dist/schema/routines.d.ts +85 -0
  102. package/dist/schema/routines.d.ts.map +1 -1
  103. package/dist/schema/routines.js +8 -0
  104. package/dist/schema/routines.js.map +1 -1
  105. package/dist/schema/secret_access_events.d.ts +103 -1
  106. package/dist/schema/secret_access_events.d.ts.map +1 -1
  107. package/dist/schema/secret_access_events.js +10 -1
  108. package/dist/schema/secret_access_events.js.map +1 -1
  109. package/dist/schema/user_secret_declarations.d.ts +229 -0
  110. package/dist/schema/user_secret_declarations.d.ts.map +1 -0
  111. package/dist/schema/user_secret_declarations.js +31 -0
  112. package/dist/schema/user_secret_declarations.js.map +1 -0
  113. package/dist/schema/user_secret_definitions.d.ts +316 -0
  114. package/dist/schema/user_secret_definitions.d.ts.map +1 -0
  115. package/dist/schema/user_secret_definitions.js +33 -0
  116. package/dist/schema/user_secret_definitions.js.map +1 -0
  117. package/dist/table-size-estimates.d.ts +372 -0
  118. package/dist/table-size-estimates.d.ts.map +1 -0
  119. package/dist/table-size-estimates.js +155 -0
  120. package/dist/table-size-estimates.js.map +1 -0
  121. package/package.json +3 -3
  122. package/dist/migrations/0126_issue_comment_derived_attribution.sql +0 -69
@@ -0,0 +1,150 @@
1
+ export const MIGRATION_SAFETY_BASELINE = [
2
+ {
3
+ id: "2cfa16c89e561306",
4
+ rule: "large-create-index-not-concurrently",
5
+ migration: "0000_mature_masked_marvel.sql",
6
+ table: "activity_log",
7
+ reason: "Initial schema history predates the migration-safety guard.",
8
+ },
9
+ {
10
+ id: "2e21c87a27d0ecf3",
11
+ rule: "large-create-index-not-concurrently",
12
+ migration: "0000_mature_masked_marvel.sql",
13
+ table: "issue_comments",
14
+ reason: "Initial schema history predates the migration-safety guard.",
15
+ },
16
+ {
17
+ id: "3fa7b338f437c89d",
18
+ rule: "large-create-index-not-concurrently",
19
+ migration: "0000_mature_masked_marvel.sql",
20
+ table: "issue_comments",
21
+ reason: "Initial schema history predates the migration-safety guard.",
22
+ },
23
+ {
24
+ id: "26bf13d0e36e3bd0",
25
+ rule: "large-create-index-not-concurrently",
26
+ migration: "0001_fast_northstar.sql",
27
+ table: "agent_wakeup_requests",
28
+ reason: "Historical migration predates the migration-safety guard.",
29
+ },
30
+ {
31
+ id: "da73c844de91f262",
32
+ rule: "large-create-index-not-concurrently",
33
+ migration: "0001_fast_northstar.sql",
34
+ table: "agent_wakeup_requests",
35
+ reason: "Historical migration predates the migration-safety guard.",
36
+ },
37
+ {
38
+ id: "b86e70ea500d5d9e",
39
+ rule: "large-create-index-not-concurrently",
40
+ migration: "0001_fast_northstar.sql",
41
+ table: "agent_wakeup_requests",
42
+ reason: "Historical migration predates the migration-safety guard.",
43
+ },
44
+ {
45
+ id: "d12aeab5a11d37fe",
46
+ rule: "large-create-index-not-concurrently",
47
+ migration: "0001_fast_northstar.sql",
48
+ table: "heartbeat_run_events",
49
+ reason: "Historical migration predates the migration-safety guard.",
50
+ },
51
+ {
52
+ id: "80d2cc53747b47bc",
53
+ rule: "large-create-index-not-concurrently",
54
+ migration: "0001_fast_northstar.sql",
55
+ table: "heartbeat_run_events",
56
+ reason: "Historical migration predates the migration-safety guard.",
57
+ },
58
+ {
59
+ id: "8985fd1ec26c0449",
60
+ rule: "large-create-index-not-concurrently",
61
+ migration: "0001_fast_northstar.sql",
62
+ table: "heartbeat_run_events",
63
+ reason: "Historical migration predates the migration-safety guard.",
64
+ },
65
+ {
66
+ id: "06065c3f2e8bca76",
67
+ rule: "large-create-index-not-concurrently",
68
+ migration: "0003_shallow_quentin_quire.sql",
69
+ table: "activity_log",
70
+ reason: "Historical migration predates the migration-safety guard.",
71
+ },
72
+ {
73
+ id: "d0cb536e5b329013",
74
+ rule: "large-create-index-not-concurrently",
75
+ migration: "0003_shallow_quentin_quire.sql",
76
+ table: "activity_log",
77
+ reason: "Historical migration predates the migration-safety guard.",
78
+ },
79
+ {
80
+ id: "b84802ae05be9943",
81
+ rule: "large-create-index-not-concurrently",
82
+ migration: "0024_far_beast.sql",
83
+ table: "issue_comments",
84
+ reason: "Historical migration predates the migration-safety guard.",
85
+ },
86
+ {
87
+ id: "3eaba6ddfa29a678",
88
+ rule: "large-create-index-not-concurrently",
89
+ migration: "0024_far_beast.sql",
90
+ table: "issue_comments",
91
+ reason: "Historical migration predates the migration-safety guard.",
92
+ },
93
+ {
94
+ id: "2874b94c3f294f53",
95
+ rule: "large-create-index-not-concurrently",
96
+ migration: "0051_young_korg.sql",
97
+ table: "issue_comments",
98
+ reason: "Historical migration predates the migration-safety guard.",
99
+ },
100
+ {
101
+ id: "f0a44a3401b28d62",
102
+ rule: "large-create-index-not-concurrently",
103
+ migration: "0060_orange_annihilus.sql",
104
+ table: "issue_reference_mentions",
105
+ reason: "Historical migration predates the migration-safety guard.",
106
+ },
107
+ {
108
+ id: "f1fbb786a033df8d",
109
+ rule: "large-create-index-not-concurrently",
110
+ migration: "0060_orange_annihilus.sql",
111
+ table: "issue_reference_mentions",
112
+ reason: "Historical migration predates the migration-safety guard.",
113
+ },
114
+ {
115
+ id: "f74aa7dfb0152788",
116
+ rule: "large-create-index-not-concurrently",
117
+ migration: "0060_orange_annihilus.sql",
118
+ table: "issue_reference_mentions",
119
+ reason: "Historical migration predates the migration-safety guard.",
120
+ },
121
+ {
122
+ id: "3c1237481d6ee00d",
123
+ rule: "large-create-index-not-concurrently",
124
+ migration: "0060_orange_annihilus.sql",
125
+ table: "issue_reference_mentions",
126
+ reason: "Historical migration predates the migration-safety guard.",
127
+ },
128
+ {
129
+ id: "21cf0a7bb66a4058",
130
+ rule: "large-create-index-not-concurrently",
131
+ migration: "0060_orange_annihilus.sql",
132
+ table: "issue_reference_mentions",
133
+ reason: "Historical migration predates the migration-safety guard.",
134
+ },
135
+ {
136
+ id: "567b97176f9f06c3",
137
+ rule: "large-create-index-not-concurrently",
138
+ migration: "0132_issue_comment_derived_attribution_fast.sql",
139
+ table: "issue_comments",
140
+ reason: "Existing issue-attribution backfill branch uses a temporary support index before this guard landed.",
141
+ },
142
+ {
143
+ id: "38d8055cc228913d",
144
+ rule: "full-table-mutation-large-table",
145
+ migration: "0132_issue_comment_derived_attribution_fast.sql",
146
+ table: "issue_comments",
147
+ reason: "Batched DO-loop backfill with keyset pagination (LIMIT 5000 per batch); reviewed and approved as part of PAP-1505 fix. Already merged to master before this guard landed.",
148
+ },
149
+ ];
150
+ //# sourceMappingURL=migration-safety-baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-safety-baseline.js","sourceRoot":"","sources":["../src/migration-safety-baseline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ CREATE TABLE IF NOT EXISTS "user_secret_definitions" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "key" text NOT NULL,
5
+ "name" text NOT NULL,
6
+ "description" text,
7
+ "status" text DEFAULT 'active' NOT NULL,
8
+ "provider" text DEFAULT 'local_encrypted' NOT NULL,
9
+ "managed_mode" text DEFAULT 'paperclip_managed' NOT NULL,
10
+ "provider_config_id" uuid,
11
+ "provider_metadata" jsonb,
12
+ "usage_guidance" text,
13
+ "created_by_agent_id" uuid,
14
+ "created_by_user_id" text,
15
+ "updated_by_agent_id" uuid,
16
+ "updated_by_user_id" text,
17
+ "deleted_at" timestamp with time zone,
18
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
19
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
20
+ );
21
+ --> statement-breakpoint
22
+ CREATE TABLE IF NOT EXISTS "user_secret_declarations" (
23
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
24
+ "company_id" uuid NOT NULL,
25
+ "user_secret_definition_id" uuid NOT NULL,
26
+ "target_type" text NOT NULL,
27
+ "target_id" text NOT NULL,
28
+ "config_path" text NOT NULL,
29
+ "env_key" text NOT NULL,
30
+ "version_selector" text DEFAULT 'latest' NOT NULL,
31
+ "required" boolean DEFAULT true NOT NULL,
32
+ "allow_missing_override" boolean DEFAULT false NOT NULL,
33
+ "label" text,
34
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
35
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
36
+ );
37
+ --> statement-breakpoint
38
+ ALTER TABLE "company_secrets" ADD COLUMN IF NOT EXISTS "scope" text DEFAULT 'company' NOT NULL;
39
+ --> statement-breakpoint
40
+ ALTER TABLE "company_secrets" ADD COLUMN IF NOT EXISTS "owner_user_id" text;
41
+ --> statement-breakpoint
42
+ ALTER TABLE "company_secrets" ADD COLUMN IF NOT EXISTS "user_secret_definition_id" uuid;
43
+ --> statement-breakpoint
44
+ UPDATE "company_secrets"
45
+ SET "scope" = 'company'
46
+ WHERE "scope" IS NULL;
47
+ --> statement-breakpoint
48
+ ALTER TABLE "secret_access_events" ALTER COLUMN "secret_id" DROP NOT NULL;
49
+ --> statement-breakpoint
50
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "user_secret_definition_id" uuid;
51
+ --> statement-breakpoint
52
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "secret_scope" text DEFAULT 'company' NOT NULL;
53
+ --> statement-breakpoint
54
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
55
+ --> statement-breakpoint
56
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "credential_owner_user_id" text;
57
+ --> statement-breakpoint
58
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "credential_subject_type" text;
59
+ --> statement-breakpoint
60
+ ALTER TABLE "secret_access_events" ADD COLUMN IF NOT EXISTS "credential_subject_id" text;
61
+ --> statement-breakpoint
62
+ ALTER TABLE "issues" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
63
+ --> statement-breakpoint
64
+ ALTER TABLE "heartbeat_runs" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
65
+ --> statement-breakpoint
66
+ ALTER TABLE "routines" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
67
+ --> statement-breakpoint
68
+ ALTER TABLE "routine_revisions" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
69
+ --> statement-breakpoint
70
+ ALTER TABLE "routine_runs" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
71
+ --> statement-breakpoint
72
+ DO $$ BEGIN
73
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_definitions_company_id_companies_id_fk') THEN
74
+ ALTER TABLE "user_secret_definitions" ADD CONSTRAINT "user_secret_definitions_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
75
+ END IF;
76
+ END $$;
77
+ --> statement-breakpoint
78
+ DO $$ BEGIN
79
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_definitions_provider_config_id_company_secret_provider_configs_id_fk') THEN
80
+ ALTER TABLE "user_secret_definitions" ADD CONSTRAINT "user_secret_definitions_provider_config_id_company_secret_provider_configs_id_fk" FOREIGN KEY ("provider_config_id") REFERENCES "public"."company_secret_provider_configs"("id") ON DELETE set null ON UPDATE no action;
81
+ END IF;
82
+ END $$;
83
+ --> statement-breakpoint
84
+ DO $$ BEGIN
85
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_definitions_created_by_agent_id_agents_id_fk') THEN
86
+ ALTER TABLE "user_secret_definitions" ADD CONSTRAINT "user_secret_definitions_created_by_agent_id_agents_id_fk" FOREIGN KEY ("created_by_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;
87
+ END IF;
88
+ END $$;
89
+ --> statement-breakpoint
90
+ DO $$ BEGIN
91
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_definitions_updated_by_agent_id_agents_id_fk') THEN
92
+ ALTER TABLE "user_secret_definitions" ADD CONSTRAINT "user_secret_definitions_updated_by_agent_id_agents_id_fk" FOREIGN KEY ("updated_by_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;
93
+ END IF;
94
+ END $$;
95
+ --> statement-breakpoint
96
+ DO $$ BEGIN
97
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_declarations_company_id_companies_id_fk') THEN
98
+ ALTER TABLE "user_secret_declarations" ADD CONSTRAINT "user_secret_declarations_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
99
+ END IF;
100
+ END $$;
101
+ --> statement-breakpoint
102
+ DO $$ BEGIN
103
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_secret_declarations_user_secret_definition_id_user_secret_definitions_id_fk') THEN
104
+ ALTER TABLE "user_secret_declarations" ADD CONSTRAINT "user_secret_declarations_user_secret_definition_id_user_secret_definitions_id_fk" FOREIGN KEY ("user_secret_definition_id") REFERENCES "public"."user_secret_definitions"("id") ON DELETE cascade ON UPDATE no action;
105
+ END IF;
106
+ END $$;
107
+ --> statement-breakpoint
108
+ DO $$ BEGIN
109
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_secrets_user_secret_definition_id_user_secret_definitions_id_fk') THEN
110
+ ALTER TABLE "company_secrets" ADD CONSTRAINT "company_secrets_user_secret_definition_id_user_secret_definitions_id_fk" FOREIGN KEY ("user_secret_definition_id") REFERENCES "public"."user_secret_definitions"("id") ON DELETE set null ON UPDATE no action;
111
+ END IF;
112
+ END $$;
113
+ --> statement-breakpoint
114
+ DO $$ BEGIN
115
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'secret_access_events_user_secret_definition_id_user_secret_definitions_id_fk') THEN
116
+ ALTER TABLE "secret_access_events" ADD CONSTRAINT "secret_access_events_user_secret_definition_id_user_secret_definitions_id_fk" FOREIGN KEY ("user_secret_definition_id") REFERENCES "public"."user_secret_definitions"("id") ON DELETE set null ON UPDATE no action;
117
+ END IF;
118
+ END $$;
119
+ --> statement-breakpoint
120
+ DO $$ BEGIN
121
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_secrets_scope_shape_check') THEN
122
+ ALTER TABLE "company_secrets" ADD CONSTRAINT "company_secrets_scope_shape_check" CHECK (
123
+ ("scope" = 'company' AND "owner_user_id" IS NULL AND "user_secret_definition_id" IS NULL)
124
+ OR
125
+ ("scope" = 'user' AND "owner_user_id" IS NOT NULL AND "user_secret_definition_id" IS NOT NULL)
126
+ );
127
+ END IF;
128
+ END $$;
129
+ --> statement-breakpoint
130
+ DROP INDEX IF EXISTS "company_secrets_company_name_uq";
131
+ --> statement-breakpoint
132
+ DROP INDEX IF EXISTS "company_secrets_company_key_uq";
133
+ --> statement-breakpoint
134
+ CREATE INDEX IF NOT EXISTS "user_secret_definitions_company_status_idx" ON "user_secret_definitions" USING btree ("company_id","status");
135
+ --> statement-breakpoint
136
+ CREATE INDEX IF NOT EXISTS "user_secret_definitions_company_provider_idx" ON "user_secret_definitions" USING btree ("company_id","provider");
137
+ --> statement-breakpoint
138
+ CREATE INDEX IF NOT EXISTS "user_secret_definitions_provider_config_idx" ON "user_secret_definitions" USING btree ("provider_config_id");
139
+ --> statement-breakpoint
140
+ CREATE UNIQUE INDEX IF NOT EXISTS "user_secret_definitions_company_key_uq" ON "user_secret_definitions" USING btree ("company_id","key") WHERE "user_secret_definitions"."deleted_at" IS NULL;
141
+ --> statement-breakpoint
142
+ CREATE INDEX IF NOT EXISTS "user_secret_declarations_company_idx" ON "user_secret_declarations" USING btree ("company_id");
143
+ --> statement-breakpoint
144
+ CREATE INDEX IF NOT EXISTS "user_secret_declarations_definition_idx" ON "user_secret_declarations" USING btree ("user_secret_definition_id");
145
+ --> statement-breakpoint
146
+ CREATE INDEX IF NOT EXISTS "user_secret_declarations_target_idx" ON "user_secret_declarations" USING btree ("company_id","target_type","target_id");
147
+ --> statement-breakpoint
148
+ CREATE INDEX IF NOT EXISTS "user_secret_declarations_company_required_idx" ON "user_secret_declarations" USING btree ("company_id","required");
149
+ --> statement-breakpoint
150
+ CREATE UNIQUE INDEX IF NOT EXISTS "user_secret_declarations_target_path_uq" ON "user_secret_declarations" USING btree ("company_id","target_type","target_id","config_path");
151
+ --> statement-breakpoint
152
+ CREATE INDEX IF NOT EXISTS "user_secret_declarations_required_override_idx" ON "user_secret_declarations" USING btree ("company_id","allow_missing_override") WHERE "user_secret_declarations"."allow_missing_override" = true;
153
+ --> statement-breakpoint
154
+ CREATE INDEX IF NOT EXISTS "company_secrets_company_scope_idx" ON "company_secrets" USING btree ("company_id","scope");
155
+ --> statement-breakpoint
156
+ CREATE INDEX IF NOT EXISTS "company_secrets_company_owner_idx" ON "company_secrets" USING btree ("company_id","owner_user_id");
157
+ --> statement-breakpoint
158
+ CREATE INDEX IF NOT EXISTS "company_secrets_user_definition_owner_idx" ON "company_secrets" USING btree ("company_id","user_secret_definition_id","owner_user_id");
159
+ --> statement-breakpoint
160
+ CREATE UNIQUE INDEX IF NOT EXISTS "company_secrets_company_name_uq" ON "company_secrets" USING btree ("company_id","name") WHERE "company_secrets"."scope" = 'company' AND "company_secrets"."deleted_at" IS NULL;
161
+ --> statement-breakpoint
162
+ CREATE UNIQUE INDEX IF NOT EXISTS "company_secrets_company_key_uq" ON "company_secrets" USING btree ("company_id","key") WHERE "company_secrets"."scope" = 'company' AND "company_secrets"."deleted_at" IS NULL;
163
+ --> statement-breakpoint
164
+ CREATE UNIQUE INDEX IF NOT EXISTS "company_secrets_user_definition_owner_uq" ON "company_secrets" USING btree ("company_id","user_secret_definition_id","owner_user_id") WHERE "company_secrets"."scope" = 'user' AND "company_secrets"."deleted_at" IS NULL;
165
+ --> statement-breakpoint
166
+ CREATE INDEX IF NOT EXISTS "secret_access_events_user_definition_created_idx" ON "secret_access_events" USING btree ("user_secret_definition_id","created_at");
167
+ --> statement-breakpoint
168
+ CREATE INDEX IF NOT EXISTS "secret_access_events_company_credential_owner_idx" ON "secret_access_events" USING btree ("company_id","credential_owner_user_id","created_at");
169
+ --> statement-breakpoint
170
+ CREATE INDEX IF NOT EXISTS "issues_company_responsible_user_idx" ON "issues" USING btree ("company_id","responsible_user_id");
171
+ --> statement-breakpoint
172
+ CREATE INDEX IF NOT EXISTS "heartbeat_runs_company_responsible_user_idx" ON "heartbeat_runs" USING btree ("company_id","responsible_user_id","created_at");
173
+ --> statement-breakpoint
174
+ CREATE INDEX IF NOT EXISTS "routines_company_responsible_user_idx" ON "routines" USING btree ("company_id","responsible_user_id");
175
+ --> statement-breakpoint
176
+ CREATE INDEX IF NOT EXISTS "routine_revisions_company_responsible_user_idx" ON "routine_revisions" USING btree ("company_id","responsible_user_id","created_at");
177
+ --> statement-breakpoint
178
+ CREATE INDEX IF NOT EXISTS "routine_runs_company_responsible_user_idx" ON "routine_runs" USING btree ("company_id","responsible_user_id","created_at");
@@ -0,0 +1,41 @@
1
+ ALTER TABLE "agent_api_keys" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;
2
+ --> statement-breakpoint
3
+ UPDATE "agent_api_keys" AS key
4
+ SET "responsible_user_id" = created_by."responsible_user_id"
5
+ FROM (
6
+ SELECT DISTINCT ON (key_id)
7
+ key_id,
8
+ responsible_user_id
9
+ FROM (
10
+ SELECT
11
+ log.details ->> 'keyId' AS key_id,
12
+ log.actor_id AS responsible_user_id,
13
+ log.created_at
14
+ FROM "activity_log" AS log
15
+ WHERE log.action = 'agent.key_created'
16
+ AND log.actor_type = 'user'
17
+ AND log.details ->> 'keyId' IS NOT NULL
18
+ AND log.actor_id IS NOT NULL
19
+ AND log.actor_id <> ''
20
+
21
+ UNION ALL
22
+
23
+ SELECT
24
+ log.entity_id AS key_id,
25
+ request.approved_by_user_id AS responsible_user_id,
26
+ log.created_at
27
+ FROM "activity_log" AS log
28
+ INNER JOIN "join_requests" AS request
29
+ ON request.id::text = log.details ->> 'joinRequestId'
30
+ WHERE log.action = 'agent_api_key.claimed'
31
+ AND log.entity_type = 'agent_api_key'
32
+ AND log.entity_id IS NOT NULL
33
+ AND request.approved_by_user_id IS NOT NULL
34
+ AND request.approved_by_user_id <> ''
35
+ ) AS candidates
36
+ WHERE responsible_user_id IS NOT NULL
37
+ AND responsible_user_id <> ''
38
+ ORDER BY key_id, created_at ASC
39
+ ) AS created_by
40
+ WHERE key.id::text = created_by.key_id
41
+ AND key.responsible_user_id IS NULL;
@@ -0,0 +1,67 @@
1
+ WITH extracted_run_refs AS (
2
+ SELECT
3
+ h."id" AS "run_id",
4
+ h."company_id",
5
+ NULLIF(h."context_snapshot" ->> 'issueId', '') AS "issue_ref",
6
+ 1 AS "ref_priority"
7
+ FROM "heartbeat_runs" AS h
8
+ WHERE h."responsible_user_id" IS NULL
9
+ AND NULLIF(h."context_snapshot" ->> 'issueId', '') IS NOT NULL
10
+
11
+ UNION ALL
12
+
13
+ SELECT
14
+ h."id" AS "run_id",
15
+ h."company_id",
16
+ NULLIF(h."context_snapshot" ->> 'taskId', '') AS "issue_ref",
17
+ 2 AS "ref_priority"
18
+ FROM "heartbeat_runs" AS h
19
+ WHERE h."responsible_user_id" IS NULL
20
+ AND NULLIF(h."context_snapshot" ->> 'taskId', '') IS NOT NULL
21
+ ),
22
+ uuid_run_refs AS (
23
+ SELECT
24
+ "run_id",
25
+ "company_id",
26
+ "issue_ref"::uuid AS "issue_id",
27
+ "ref_priority"
28
+ FROM extracted_run_refs
29
+ WHERE "issue_ref" ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
30
+ ),
31
+ resolved_run_users AS (
32
+ SELECT DISTINCT ON ("run_id")
33
+ "run_id",
34
+ "responsible_user_id"
35
+ FROM (
36
+ SELECT
37
+ refs."run_id",
38
+ i."responsible_user_id",
39
+ refs."ref_priority",
40
+ 1 AS "match_priority"
41
+ FROM uuid_run_refs AS refs
42
+ JOIN "issues" AS i
43
+ ON i."id" = refs."issue_id"
44
+ AND i."company_id" = refs."company_id"
45
+ WHERE i."responsible_user_id" IS NOT NULL
46
+
47
+ UNION ALL
48
+
49
+ SELECT
50
+ refs."run_id",
51
+ i."responsible_user_id",
52
+ refs."ref_priority",
53
+ 2 AS "match_priority"
54
+ FROM extracted_run_refs AS refs
55
+ JOIN "issues" AS i
56
+ ON i."identifier" = refs."issue_ref"
57
+ AND i."company_id" = refs."company_id"
58
+ WHERE i."responsible_user_id" IS NOT NULL
59
+ ) AS candidates
60
+ ORDER BY "run_id", "ref_priority" ASC, "match_priority" ASC
61
+ )
62
+ UPDATE "heartbeat_runs" AS h
63
+ SET "responsible_user_id" = resolved_run_users."responsible_user_id",
64
+ "updated_at" = now()
65
+ FROM resolved_run_users
66
+ WHERE h."id" = resolved_run_users."run_id"
67
+ AND h."responsible_user_id" IS NULL;
@@ -0,0 +1,82 @@
1
+ ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "derived_author_agent_id" uuid;--> statement-breakpoint
2
+ ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "derived_created_by_run_id" uuid;--> statement-breakpoint
3
+ ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "derived_author_source" text;--> statement-breakpoint
4
+ DO $$ BEGIN
5
+ IF NOT EXISTS (
6
+ SELECT 1 FROM "pg_constraint" WHERE "conname" = 'issue_comments_derived_author_agent_id_agents_id_fk'
7
+ ) THEN
8
+ ALTER TABLE "issue_comments" ADD CONSTRAINT "issue_comments_derived_author_agent_id_agents_id_fk" FOREIGN KEY ("derived_author_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;
9
+ END IF;
10
+ END $$;--> statement-breakpoint
11
+ DO $$ BEGIN
12
+ IF NOT EXISTS (
13
+ SELECT 1 FROM "pg_constraint" WHERE "conname" = 'issue_comments_derived_created_by_run_id_heartbeat_runs_id_fk'
14
+ ) THEN
15
+ ALTER TABLE "issue_comments" ADD CONSTRAINT "issue_comments_derived_created_by_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("derived_created_by_run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE set null ON UPDATE no action;
16
+ END IF;
17
+ END $$;--> statement-breakpoint
18
+ -- Temporary support for the forward-only backfill. The keyset loop below
19
+ -- advances over this partial index by comment id, so each eligible slice is
20
+ -- visited once instead of re-scanning issue_comments from the beginning on
21
+ -- every batch.
22
+ CREATE INDEX IF NOT EXISTS "issue_comments_derived_attribution_backfill_idx"
23
+ ON "issue_comments" USING btree ("id")
24
+ WHERE "author_agent_id" IS NULL
25
+ AND "derived_author_agent_id" IS NULL
26
+ AND "author_user_id" IS NOT NULL
27
+ AND "created_by_run_id" IS NOT NULL;--> statement-breakpoint
28
+ ANALYZE "issue_comments";--> statement-breakpoint
29
+ DO $$
30
+ DECLARE
31
+ last_comment_id uuid := '00000000-0000-0000-0000-000000000000'::uuid;
32
+ next_last_comment_id uuid;
33
+ BEGIN
34
+ LOOP
35
+ next_last_comment_id := NULL;
36
+
37
+ WITH batch AS MATERIALIZED (
38
+ SELECT c."id" AS comment_id, hr."agent_id", hr."id" AS run_id
39
+ FROM "issue_comments" c
40
+ JOIN "heartbeat_runs" hr ON hr."id" = c."created_by_run_id"
41
+ LEFT JOIN "user" u ON u."id" = c."author_user_id"
42
+ WHERE c."id" > last_comment_id
43
+ AND c."author_agent_id" IS NULL
44
+ AND c."derived_author_agent_id" IS NULL
45
+ AND c."author_user_id" IS NOT NULL
46
+ AND c."created_by_run_id" IS NOT NULL
47
+ AND (
48
+ c."author_user_id" = 'local-board'
49
+ OR u."id" IS NULL
50
+ )
51
+ ORDER BY c."id"
52
+ LIMIT 5000
53
+ ),
54
+ updated AS (
55
+ UPDATE "issue_comments" c
56
+ SET "derived_author_agent_id" = b."agent_id",
57
+ "derived_created_by_run_id" = b."run_id",
58
+ "derived_author_source" = 'run_id'
59
+ FROM batch b
60
+ WHERE c."id" = b."comment_id"
61
+ RETURNING c."id"
62
+ )
63
+ SELECT b."comment_id"
64
+ INTO next_last_comment_id
65
+ FROM batch b
66
+ LEFT JOIN updated u ON u."id" = b."comment_id"
67
+ ORDER BY b."comment_id" DESC
68
+ LIMIT 1;
69
+
70
+ EXIT WHEN next_last_comment_id IS NULL;
71
+ last_comment_id := next_last_comment_id;
72
+ END LOOP;
73
+ END $$;--> statement-breakpoint
74
+ DROP INDEX IF EXISTS "issue_comments_derived_attribution_backfill_idx";--> statement-breakpoint
75
+ -- Keep the Option-A cleanup at the end as well, matching the original 0126
76
+ -- terminal state if any timing-tier rows are introduced before this migration
77
+ -- is retried.
78
+ UPDATE "issue_comments"
79
+ SET "derived_author_agent_id" = NULL,
80
+ "derived_created_by_run_id" = NULL,
81
+ "derived_author_source" = NULL
82
+ WHERE "derived_author_source" IN ('run_window_unique', 'run_window_agent_unique');
@@ -0,0 +1,7 @@
1
+ ALTER TABLE "agent_memberships" ADD COLUMN IF NOT EXISTS "starred_at" timestamp with time zone;
2
+ --> statement-breakpoint
3
+ ALTER TABLE "project_memberships" ADD COLUMN IF NOT EXISTS "starred_at" timestamp with time zone;
4
+ --> statement-breakpoint
5
+ CREATE INDEX IF NOT EXISTS "agent_memberships_company_user_starred_idx" ON "agent_memberships" USING btree ("company_id","user_id","starred_at");
6
+ --> statement-breakpoint
7
+ CREATE INDEX IF NOT EXISTS "project_memberships_company_user_starred_idx" ON "project_memberships" USING btree ("company_id","user_id","starred_at");