@paperclipai/db 2026.817.0 → 2026.818.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/adapter-auth-sessions-schema.test.d.ts +2 -0
  2. package/dist/adapter-auth-sessions-schema.test.d.ts.map +1 -0
  3. package/dist/adapter-auth-sessions-schema.test.js +57 -0
  4. package/dist/adapter-auth-sessions-schema.test.js.map +1 -0
  5. package/dist/claude-setup-token-sessions-schema.test.d.ts +2 -0
  6. package/dist/claude-setup-token-sessions-schema.test.d.ts.map +1 -0
  7. package/dist/claude-setup-token-sessions-schema.test.js +102 -0
  8. package/dist/claude-setup-token-sessions-schema.test.js.map +1 -0
  9. package/dist/company-secret-proposals-migration.test.js +6 -1
  10. package/dist/company-secret-proposals-migration.test.js.map +1 -1
  11. package/dist/issue-thread-interaction-resolver-policy-migration.test.d.ts +2 -0
  12. package/dist/issue-thread-interaction-resolver-policy-migration.test.d.ts.map +1 -0
  13. package/dist/issue-thread-interaction-resolver-policy-migration.test.js +146 -0
  14. package/dist/issue-thread-interaction-resolver-policy-migration.test.js.map +1 -0
  15. package/dist/migrations/0212_onboarding_first_task_unique.sql +3 -0
  16. package/dist/migrations/0213_complete_mystique.sql +24 -0
  17. package/dist/migrations/0214_lively_lord_tyger.sql +22 -0
  18. package/dist/migrations/0215_flat_daimon_hellstrom.sql +1 -0
  19. package/dist/migrations/0216_company_onboarding_seeds.sql +42 -0
  20. package/dist/migrations/0217_yielding_starbolt.sql +21 -0
  21. package/dist/migrations/0218_mushy_jack_murdock.sql +38 -0
  22. package/dist/migrations/0219_runtime_service_exposure.sql +3 -0
  23. package/dist/migrations/0220_execution_workspace_runtime_leases.sql +26 -0
  24. package/dist/migrations/0221_swift_justin_hammer.sql +20 -0
  25. package/dist/migrations/0222_orphan_cleanup_env_reference_survives_delete.sql +4 -0
  26. package/dist/migrations/meta/0213_snapshot.json +38886 -0
  27. package/dist/migrations/meta/0214_snapshot.json +39091 -0
  28. package/dist/migrations/meta/0215_snapshot.json +39097 -0
  29. package/dist/migrations/meta/0217_snapshot.json +39267 -0
  30. package/dist/migrations/meta/0218_snapshot.json +39281 -0
  31. package/dist/migrations/meta/0221_snapshot.json +39714 -0
  32. package/dist/migrations/meta/0222_snapshot.json +39714 -0
  33. package/dist/migrations/meta/_journal.json +78 -1
  34. package/dist/schema/adapter_auth_sessions.d.ts +234 -0
  35. package/dist/schema/adapter_auth_sessions.d.ts.map +1 -0
  36. package/dist/schema/adapter_auth_sessions.js +47 -0
  37. package/dist/schema/adapter_auth_sessions.js.map +1 -0
  38. package/dist/schema/claude_setup_token_sessions.d.ts +227 -0
  39. package/dist/schema/claude_setup_token_sessions.d.ts.map +1 -0
  40. package/dist/schema/claude_setup_token_sessions.js +58 -0
  41. package/dist/schema/claude_setup_token_sessions.js.map +1 -0
  42. package/dist/schema/company_onboarding_seeds.d.ts +257 -0
  43. package/dist/schema/company_onboarding_seeds.d.ts.map +1 -0
  44. package/dist/schema/company_onboarding_seeds.js +35 -0
  45. package/dist/schema/company_onboarding_seeds.js.map +1 -0
  46. package/dist/schema/company_transfer_runs.d.ts +297 -0
  47. package/dist/schema/company_transfer_runs.d.ts.map +1 -0
  48. package/dist/schema/company_transfer_runs.js +42 -0
  49. package/dist/schema/company_transfer_runs.js.map +1 -0
  50. package/dist/schema/cost_events.js +1 -1
  51. package/dist/schema/cost_events.js.map +1 -1
  52. package/dist/schema/environment_leases.d.ts +1 -1
  53. package/dist/schema/environment_leases.d.ts.map +1 -1
  54. package/dist/schema/environment_leases.js +8 -1
  55. package/dist/schema/environment_leases.js.map +1 -1
  56. package/dist/schema/execution_workspace_runtime_leases.d.ts +248 -0
  57. package/dist/schema/execution_workspace_runtime_leases.d.ts.map +1 -0
  58. package/dist/schema/execution_workspace_runtime_leases.js +35 -0
  59. package/dist/schema/execution_workspace_runtime_leases.js.map +1 -0
  60. package/dist/schema/feedback_votes.js +1 -1
  61. package/dist/schema/feedback_votes.js.map +1 -1
  62. package/dist/schema/finance_events.js +1 -1
  63. package/dist/schema/finance_events.js.map +1 -1
  64. package/dist/schema/index.d.ts +5 -0
  65. package/dist/schema/index.d.ts.map +1 -1
  66. package/dist/schema/index.js +5 -0
  67. package/dist/schema/index.js.map +1 -1
  68. package/dist/schema/issue_comments.js +1 -1
  69. package/dist/schema/issue_comments.js.map +1 -1
  70. package/dist/schema/issue_inbox_archives.js +1 -1
  71. package/dist/schema/issue_inbox_archives.js.map +1 -1
  72. package/dist/schema/issue_read_states.js +1 -1
  73. package/dist/schema/issue_read_states.js.map +1 -1
  74. package/dist/schema/issue_thread_interactions.d.ts +42 -4
  75. package/dist/schema/issue_thread_interactions.d.ts.map +1 -1
  76. package/dist/schema/issue_thread_interactions.js +11 -3
  77. package/dist/schema/issue_thread_interactions.js.map +1 -1
  78. package/dist/schema/issues.d.ts.map +1 -1
  79. package/dist/schema/issues.js +7 -0
  80. package/dist/schema/issues.js.map +1 -1
  81. package/dist/schema/summary_slots.d.ts +2 -2
  82. package/dist/schema/workspace_runtime_services.d.ts +54 -0
  83. package/dist/schema/workspace_runtime_services.d.ts.map +1 -1
  84. package/dist/schema/workspace_runtime_services.js +9 -0
  85. package/dist/schema/workspace_runtime_services.js.map +1 -1
  86. package/dist/status-card-migrations.test.js +5 -1
  87. package/dist/status-card-migrations.test.js.map +1 -1
  88. package/package.json +3 -3
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapter-auth-sessions-schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-auth-sessions-schema.test.d.ts","sourceRoot":"","sources":["../src/adapter-auth-sessions-schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import fs from "node:fs";
2
+ import { getTableConfig } from "drizzle-orm/pg-core";
3
+ import { describe, expect, it } from "vitest";
4
+ import { adapterAuthSessions } from "./schema/adapter_auth_sessions.js";
5
+ function findIndex(table, indexName) {
6
+ return getTableConfig(table).indexes.find((candidate) => candidate.config.name === indexName);
7
+ }
8
+ function indexColumns(table, indexName) {
9
+ const index = findIndex(table, indexName);
10
+ if (!index)
11
+ return [];
12
+ return index.config.columns.map((column) => column.name);
13
+ }
14
+ function columnIsNotNull(table, columnName) {
15
+ const column = getTableConfig(table).columns.find((candidate) => candidate.name === columnName);
16
+ return column?.notNull ?? false;
17
+ }
18
+ // The migration that creates the table. The test locates it by content, so a
19
+ // later re-generation with a different name does not break the test.
20
+ function activeIndexMigrationSql() {
21
+ const migrationsDir = new URL("./migrations/", import.meta.url);
22
+ const files = fs.readdirSync(migrationsDir).filter((name) => name.endsWith(".sql"));
23
+ for (const name of files) {
24
+ const content = fs.readFileSync(new URL(name, migrationsDir), "utf8");
25
+ if (content.includes("adapter_auth_sessions_company_adapter_active_uq")) {
26
+ return content;
27
+ }
28
+ }
29
+ throw new Error("no migration creates adapter_auth_sessions_company_adapter_active_uq");
30
+ }
31
+ describe("adapter auth sessions schema", () => {
32
+ it("serializes on the company credential slot over the active statuses", () => {
33
+ const active = findIndex(adapterAuthSessions, "adapter_auth_sessions_company_adapter_active_uq");
34
+ expect(active).toBeDefined();
35
+ expect(active?.config.unique).toBe(true);
36
+ expect(indexColumns(adapterAuthSessions, "adapter_auth_sessions_company_adapter_active_uq")).toEqual([
37
+ "company_id",
38
+ "adapter_type",
39
+ ]);
40
+ // The active index is partial; the where clause is present.
41
+ expect(active?.config.where).toBeDefined();
42
+ });
43
+ it("keeps the owner principal non-null and out of the uniqueness key", () => {
44
+ expect(columnIsNotNull(adapterAuthSessions, "started_by_user_id")).toBe(true);
45
+ const activeColumns = indexColumns(adapterAuthSessions, "adapter_auth_sessions_company_adapter_active_uq");
46
+ expect(activeColumns).not.toContain("started_by_user_id");
47
+ expect(activeColumns).not.toContain("environment_id");
48
+ });
49
+ it("generates a partial unique index over the three active statuses", () => {
50
+ const sql = activeIndexMigrationSql();
51
+ expect(sql).toContain('CREATE UNIQUE INDEX "adapter_auth_sessions_company_adapter_active_uq"');
52
+ expect(sql).toContain('("company_id","adapter_type")');
53
+ expect(sql).toContain("'starting', 'waiting_for_user', 'promoting'");
54
+ expect(sql).toContain('"started_by_user_id" text NOT NULL');
55
+ });
56
+ });
57
+ //# sourceMappingURL=adapter-auth-sessions-schema.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-auth-sessions-schema.test.js","sourceRoot":"","sources":["../src/adapter-auth-sessions-schema.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claude-setup-token-sessions-schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-setup-token-sessions-schema.test.d.ts","sourceRoot":"","sources":["../src/claude-setup-token-sessions-schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import fs from "node:fs";
2
+ import { getTableConfig } from "drizzle-orm/pg-core";
3
+ import { describe, expect, it } from "vitest";
4
+ import { claudeSetupTokenSessions } from "./schema/claude_setup_token_sessions.js";
5
+ function findIndex(table, indexName) {
6
+ return getTableConfig(table).indexes.find((candidate) => candidate.config.name === indexName);
7
+ }
8
+ function indexColumns(table, indexName) {
9
+ const index = findIndex(table, indexName);
10
+ if (!index)
11
+ return [];
12
+ return index.config.columns.map((column) => column.name);
13
+ }
14
+ function column(table, columnName) {
15
+ return getTableConfig(table).columns.find((candidate) => candidate.name === columnName);
16
+ }
17
+ function columnIsNotNull(table, columnName) {
18
+ return column(table, columnName)?.notNull ?? false;
19
+ }
20
+ const ACTIVE_INDEX = "claude_setup_token_sessions_active_uq";
21
+ // The migration that creates the table. The test locates it by content, so a
22
+ // later re-generation with a different name does not break the test.
23
+ function activeIndexMigrationSql() {
24
+ const migrationsDir = new URL("./migrations/", import.meta.url);
25
+ const files = fs.readdirSync(migrationsDir).filter((name) => name.endsWith(".sql"));
26
+ for (const name of files) {
27
+ const content = fs.readFileSync(new URL(name, migrationsDir), "utf8");
28
+ if (content.includes(ACTIVE_INDEX)) {
29
+ return content;
30
+ }
31
+ }
32
+ throw new Error(`no migration creates ${ACTIVE_INDEX}`);
33
+ }
34
+ describe("claude setup token sessions schema", () => {
35
+ it("keeps the scope columns and the deadline non-null", () => {
36
+ expect(columnIsNotNull(claudeSetupTokenSessions, "session_id")).toBe(true);
37
+ expect(columnIsNotNull(claudeSetupTokenSessions, "company_id")).toBe(true);
38
+ expect(columnIsNotNull(claudeSetupTokenSessions, "owner_user_id")).toBe(true);
39
+ expect(columnIsNotNull(claudeSetupTokenSessions, "adapter_type")).toBe(true);
40
+ expect(columnIsNotNull(claudeSetupTokenSessions, "environment_id")).toBe(true);
41
+ expect(columnIsNotNull(claudeSetupTokenSessions, "state")).toBe(true);
42
+ expect(columnIsNotNull(claudeSetupTokenSessions, "deadline_at")).toBe(true);
43
+ });
44
+ it("keeps the claim marker and the lease reference nullable", () => {
45
+ // A row starts with no claim consumption and no lease. The service fills
46
+ // `bound_at` only when the create path consumes the stored claim.
47
+ expect(column(claudeSetupTokenSessions, "bound_at")).toBeDefined();
48
+ expect(columnIsNotNull(claudeSetupTokenSessions, "bound_at")).toBe(false);
49
+ expect(column(claudeSetupTokenSessions, "lease_id")).toBeDefined();
50
+ expect(columnIsNotNull(claudeSetupTokenSessions, "lease_id")).toBe(false);
51
+ });
52
+ it("references the company and the environment", () => {
53
+ const foreignKeys = getTableConfig(claudeSetupTokenSessions).foreignKeys;
54
+ const referencedTables = foreignKeys.map((fk) => fk.reference().foreignTable);
55
+ const referencedNames = referencedTables.map((table) => getTableConfig(table).name);
56
+ expect(referencedNames).toContain("companies");
57
+ expect(referencedNames).toContain("environments");
58
+ });
59
+ it("holds no secret-bearing column", () => {
60
+ // The durable store keeps only ids, the state, and the deadlines. It never
61
+ // holds the login URL, the browser code, the token, or a process chunk.
62
+ const names = getTableConfig(claudeSetupTokenSessions).columns.map((c) => c.name);
63
+ const forbidden = ["token", "code", "url", "secret", "credential", "prompt", "output"];
64
+ for (const name of names) {
65
+ for (const needle of forbidden) {
66
+ expect(name.includes(needle)).toBe(false);
67
+ }
68
+ }
69
+ });
70
+ it("serializes the active session over the full owner scope", () => {
71
+ const active = findIndex(claudeSetupTokenSessions, ACTIVE_INDEX);
72
+ expect(active).toBeDefined();
73
+ expect(active?.config.unique).toBe(true);
74
+ expect(indexColumns(claudeSetupTokenSessions, ACTIVE_INDEX)).toEqual([
75
+ "company_id",
76
+ "owner_user_id",
77
+ "adapter_type",
78
+ "environment_id",
79
+ ]);
80
+ // The active index is partial; the where clause is present.
81
+ expect(active?.config.where).toBeDefined();
82
+ });
83
+ it("scopes the active partial unique index to the active states only", () => {
84
+ const sql = activeIndexMigrationSql();
85
+ expect(sql).toContain(`CREATE UNIQUE INDEX "${ACTIVE_INDEX}"`);
86
+ expect(sql).toContain('("company_id","owner_user_id","adapter_type","environment_id")');
87
+ // The active states are in the predicate.
88
+ expect(sql).toContain("'starting'");
89
+ expect(sql).toContain("'awaiting_code'");
90
+ expect(sql).toContain("'submitting'");
91
+ expect(sql).toContain("'persisting'");
92
+ // The stored state and the terminal states stay out of the predicate.
93
+ const predicate = sql.slice(sql.indexOf(ACTIVE_INDEX));
94
+ const whereClause = predicate.slice(predicate.indexOf("WHERE"), predicate.indexOf(";"));
95
+ expect(whereClause).not.toContain("'stored'");
96
+ expect(whereClause).not.toContain("'completed'");
97
+ expect(whereClause).not.toContain("'failed'");
98
+ expect(whereClause).not.toContain("'timed_out'");
99
+ expect(whereClause).not.toContain("'cancelled'");
100
+ });
101
+ });
102
+ //# sourceMappingURL=claude-setup-token-sessions-schema.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-setup-token-sessions-schema.test.js","sourceRoot":"","sources":["../src/claude-setup-token-sessions-schema.test.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,11 @@ if (!embeddedPostgresSupport.supported) {
17
17
  }
18
18
  describeEmbeddedPostgres("company secret proposals migration", () => {
19
19
  afterEach(async () => Promise.all(cleanups.splice(0).map((cleanup) => cleanup())));
20
+ // Starting an embedded Postgres and replaying a migration against it does not
21
+ // fit vitest's 5s default: the neighbouring replay suites measure 7-12s on
22
+ // CI. Every other embedded-Postgres migration test in this package carries an
23
+ // explicit timeout for that reason; this one did not, so it failed on any
24
+ // runner that was not unusually fast.
20
25
  it("can be reapplied after its migration journal entry is removed", async () => {
21
26
  const database = await startEmbeddedPostgresTestDatabase("paperclip-secret-proposals-migration-");
22
27
  cleanups.push(database.cleanup);
@@ -30,6 +35,6 @@ describeEmbeddedPostgres("company secret proposals migration", () => {
30
35
  (SELECT count(*)::int FROM pg_indexes WHERE tablename = 'company_secret_proposals') AS indexes
31
36
  `;
32
37
  expect(result).toEqual({ constraints: 13, indexes: 5 });
33
- });
38
+ }, 30_000);
34
39
  });
35
40
  //# sourceMappingURL=company-secret-proposals-migration.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"company-secret-proposals-migration.test.js","sourceRoot":"","sources":["../src/company-secret-proposals-migration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,8BAA8B,EAAE,iCAAiC,EAAE,MAAM,6BAA6B,CAAC;AAEhH,MAAM,cAAc,GAAG,4BAA4B,CAAC;AACpD,MAAM,QAAQ,GAA+B,EAAE,CAAC;AAChD,MAAM,uBAAuB,GAAG,MAAM,8BAA8B,EAAE,CAAC;AACvE,MAAM,wBAAwB,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAE9F,KAAK,UAAU,aAAa;IAC1B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,gBAAgB,cAAc,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/G,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,CAAC;IACvC,OAAO,CAAC,IAAI,CACV,qFAAqF,uBAAuB,CAAC,MAAM,IAAI,yBAAyB,EAAE,CACnJ,CAAC;AACJ,CAAC;AAED,wBAAwB,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClE,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnF,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,QAAQ,GAAG,MAAM,iCAAiC,CAAC,uCAAuC,CAAC,CAAC;QAClG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAErC,MAAM,GAAG,CAAA,+DAA+D,MAAM,aAAa,EAAE,EAAE,CAAC;QAEhG,MAAM,MAAM,CAAC,sBAAsB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEzF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAA4C;;;;KAIrE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"company-secret-proposals-migration.test.js","sourceRoot":"","sources":["../src/company-secret-proposals-migration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,8BAA8B,EAAE,iCAAiC,EAAE,MAAM,6BAA6B,CAAC;AAEhH,MAAM,cAAc,GAAG,4BAA4B,CAAC;AACpD,MAAM,QAAQ,GAA+B,EAAE,CAAC;AAChD,MAAM,uBAAuB,GAAG,MAAM,8BAA8B,EAAE,CAAC;AACvE,MAAM,wBAAwB,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAE9F,KAAK,UAAU,aAAa;IAC1B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,gBAAgB,cAAc,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/G,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,CAAC;IACvC,OAAO,CAAC,IAAI,CACV,qFAAqF,uBAAuB,CAAC,MAAM,IAAI,yBAAyB,EAAE,CACnJ,CAAC;AACJ,CAAC;AAED,wBAAwB,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClE,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnF,8EAA8E;IAC9E,2EAA2E;IAC3E,8EAA8E;IAC9E,0EAA0E;IAC1E,sCAAsC;IACtC,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,QAAQ,GAAG,MAAM,iCAAiC,CAAC,uCAAuC,CAAC,CAAC;QAClG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAErC,MAAM,GAAG,CAAA,+DAA+D,MAAM,aAAa,EAAE,EAAE,CAAC;QAEhG,MAAM,MAAM,CAAC,sBAAsB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEzF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAA4C;;;;KAIrE,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=issue-thread-interaction-resolver-policy-migration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-thread-interaction-resolver-policy-migration.test.d.ts","sourceRoot":"","sources":["../src/issue-thread-interaction-resolver-policy-migration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import postgres from "postgres";
6
+ import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase, } from "./test-embedded-postgres.js";
7
+ const cleanups = [];
8
+ const support = await getEmbeddedPostgresTestSupport();
9
+ const d = support.supported ? describe : describe.skip;
10
+ afterEach(async () => {
11
+ while (cleanups.length > 0)
12
+ await cleanups.pop()?.();
13
+ });
14
+ async function resolverPolicyMigrationStatements() {
15
+ const migrationSql = await readFile(fileURLToPath(new URL("./migrations/0218_mushy_jack_murdock.sql", import.meta.url)), "utf8");
16
+ return migrationSql
17
+ .split("--> statement-breakpoint")
18
+ .map((statement) => statement.trim())
19
+ .filter((statement) => statement.length > 0);
20
+ }
21
+ d("issue interaction resolver policy migration", () => {
22
+ it("replays safely and completes a partial prior run", async () => {
23
+ const dbh = await startEmbeddedPostgresTestDatabase("resolver-policy-migration-");
24
+ cleanups.push(() => dbh.cleanup());
25
+ const sql = postgres(dbh.connectionString, { max: 1, onnotice: () => { } });
26
+ cleanups.push(async () => {
27
+ await sql.end();
28
+ });
29
+ const companyId = randomUUID();
30
+ const issueId = randomUUID();
31
+ const legacyInteractionId = randomUUID();
32
+ const partialInteractionId = randomUUID();
33
+ await sql `
34
+ INSERT INTO "companies" ("id", "name", "issue_prefix")
35
+ VALUES (${companyId}, 'Resolver migration test', 'RMT')
36
+ `;
37
+ await sql `
38
+ INSERT INTO "issues" ("id", "company_id", "title", "identifier")
39
+ VALUES (${issueId}, ${companyId}, 'Test migration replay', 'RMT-1')
40
+ `;
41
+ await sql.unsafe('ALTER TABLE "issue_thread_interactions" ALTER COLUMN "resolver_policy_provenance" DROP NOT NULL');
42
+ await sql.unsafe('ALTER TABLE "issue_thread_interactions" ALTER COLUMN "effective_resolver_policy_source" DROP NOT NULL');
43
+ await sql `
44
+ INSERT INTO "issue_thread_interactions" (
45
+ "id",
46
+ "company_id",
47
+ "issue_id",
48
+ "kind",
49
+ "requested_resolver_policy",
50
+ "effective_resolver_policy",
51
+ "resolver_policy_provenance",
52
+ "effective_resolver_policy_source",
53
+ "payload"
54
+ )
55
+ VALUES
56
+ (
57
+ ${legacyInteractionId},
58
+ ${companyId},
59
+ ${issueId},
60
+ 'request_confirmation',
61
+ 'board_or_agents',
62
+ 'board_only',
63
+ NULL,
64
+ NULL,
65
+ '{}'::jsonb
66
+ ),
67
+ (
68
+ ${partialInteractionId},
69
+ ${companyId},
70
+ ${issueId},
71
+ 'request_confirmation',
72
+ 'human_only',
73
+ 'human_only',
74
+ 'explicit',
75
+ NULL,
76
+ '{}'::jsonb
77
+ )
78
+ `;
79
+ const statements = await resolverPolicyMigrationStatements();
80
+ expect(statements.length).toBeGreaterThan(0);
81
+ for (const statement of statements)
82
+ await sql.unsafe(statement);
83
+ const rowsAfterFirstRun = await sql `
84
+ SELECT
85
+ "id",
86
+ "requested_resolver_policy",
87
+ "effective_resolver_policy",
88
+ "resolver_policy_provenance",
89
+ "effective_resolver_policy_source"
90
+ FROM "issue_thread_interactions"
91
+ WHERE "id" IN (${legacyInteractionId}, ${partialInteractionId})
92
+ ORDER BY "id"
93
+ `;
94
+ expect(rowsAfterFirstRun).toEqual([
95
+ {
96
+ id: legacyInteractionId,
97
+ requested_resolver_policy: "not_creator",
98
+ effective_resolver_policy: "human_only",
99
+ resolver_policy_provenance: "legacy_inherited_restriction",
100
+ effective_resolver_policy_source: "company_cap",
101
+ },
102
+ {
103
+ id: partialInteractionId,
104
+ requested_resolver_policy: "human_only",
105
+ effective_resolver_policy: "human_only",
106
+ resolver_policy_provenance: "explicit",
107
+ effective_resolver_policy_source: "requested",
108
+ },
109
+ ].sort((left, right) => left.id.localeCompare(right.id)));
110
+ for (const statement of statements)
111
+ await sql.unsafe(statement);
112
+ const rowsAfterReplay = await sql `
113
+ SELECT
114
+ "id",
115
+ "requested_resolver_policy",
116
+ "effective_resolver_policy",
117
+ "resolver_policy_provenance",
118
+ "effective_resolver_policy_source"
119
+ FROM "issue_thread_interactions"
120
+ WHERE "id" IN (${legacyInteractionId}, ${partialInteractionId})
121
+ ORDER BY "id"
122
+ `;
123
+ expect(rowsAfterReplay).toEqual(rowsAfterFirstRun);
124
+ const columns = await sql `
125
+ SELECT "column_name", "is_nullable", "column_default"
126
+ FROM "information_schema"."columns"
127
+ WHERE "table_schema" = 'public'
128
+ AND "table_name" = 'issue_thread_interactions'
129
+ AND "column_name" IN ('resolver_policy_provenance', 'effective_resolver_policy_source')
130
+ ORDER BY "column_name"
131
+ `;
132
+ expect(columns).toEqual([
133
+ {
134
+ column_name: "effective_resolver_policy_source",
135
+ is_nullable: "NO",
136
+ column_default: "'requested'::text",
137
+ },
138
+ {
139
+ column_name: "resolver_policy_provenance",
140
+ is_nullable: "NO",
141
+ column_default: "'inherited'::text",
142
+ },
143
+ ]);
144
+ }, 240_000);
145
+ });
146
+ //# sourceMappingURL=issue-thread-interaction-resolver-policy-migration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-thread-interaction-resolver-policy-migration.test.js","sourceRoot":"","sources":["../src/issue-thread-interaction-resolver-policy-migration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ CREATE UNIQUE INDEX IF NOT EXISTS "issues_onboarding_first_task_uq"
2
+ ON "issues" USING btree ("company_id")
3
+ WHERE "origin_kind" = 'onboarding_first_task';
@@ -0,0 +1,24 @@
1
+ CREATE TABLE "company_transfer_runs" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid,
4
+ "direction" text NOT NULL,
5
+ "status" text DEFAULT 'pending' NOT NULL,
6
+ "actor_key" text NOT NULL,
7
+ "container_ref" jsonb NOT NULL,
8
+ "idempotency_key" text NOT NULL,
9
+ "manifest_sha256" text,
10
+ "manifest" jsonb,
11
+ "chunk_count" integer DEFAULT 0 NOT NULL,
12
+ "blob_count" integer DEFAULT 0 NOT NULL,
13
+ "completed_parts" jsonb DEFAULT '[]'::jsonb NOT NULL,
14
+ "error" text,
15
+ "started_at" timestamp with time zone,
16
+ "finished_at" timestamp with time zone,
17
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
18
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
19
+ );
20
+ --> statement-breakpoint
21
+ ALTER TABLE "company_transfer_runs" ADD CONSTRAINT "company_transfer_runs_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
22
+ CREATE INDEX "company_transfer_runs_company_idx" ON "company_transfer_runs" USING btree ("company_id");--> statement-breakpoint
23
+ CREATE INDEX "company_transfer_runs_idempotency_direction_idx" ON "company_transfer_runs" USING btree ("idempotency_key","direction");--> statement-breakpoint
24
+ CREATE INDEX "company_transfer_runs_actor_status_idx" ON "company_transfer_runs" USING btree ("actor_key","status");
@@ -0,0 +1,22 @@
1
+ CREATE TABLE "adapter_auth_sessions" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "environment_id" uuid NOT NULL,
5
+ "adapter_type" text NOT NULL,
6
+ "started_by_user_id" text NOT NULL,
7
+ "provider_lease_id" text,
8
+ "status" text DEFAULT 'starting' NOT NULL,
9
+ "expires_at" timestamp with time zone,
10
+ "finished_at" timestamp with time zone,
11
+ "failure_reason" text,
12
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
13
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ ALTER TABLE "adapter_auth_sessions" ADD CONSTRAINT "adapter_auth_sessions_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
17
+ ALTER TABLE "adapter_auth_sessions" ADD CONSTRAINT "adapter_auth_sessions_environment_id_environments_id_fk" FOREIGN KEY ("environment_id") REFERENCES "public"."environments"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
18
+ CREATE INDEX "adapter_auth_sessions_company_status_idx" ON "adapter_auth_sessions" USING btree ("company_id","status");--> statement-breakpoint
19
+ CREATE UNIQUE INDEX "adapter_auth_sessions_company_adapter_active_uq" ON "adapter_auth_sessions" USING btree ("company_id","adapter_type") WHERE "adapter_auth_sessions"."status" IN ('starting', 'waiting_for_user', 'promoting');--> statement-breakpoint
20
+ CREATE INDEX "adapter_auth_sessions_environment_idx" ON "adapter_auth_sessions" USING btree ("environment_id");--> statement-breakpoint
21
+ CREATE INDEX "adapter_auth_sessions_expires_idx" ON "adapter_auth_sessions" USING btree ("expires_at");--> statement-breakpoint
22
+ CREATE INDEX "adapter_auth_sessions_provider_lease_idx" ON "adapter_auth_sessions" USING btree ("provider_lease_id");
@@ -0,0 +1 @@
1
+ ALTER TABLE "adapter_auth_sessions" ADD COLUMN "promotion_expires_at" timestamp with time zone;
@@ -0,0 +1,42 @@
1
+ CREATE TABLE IF NOT EXISTS "company_onboarding_seeds" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "revision" text NOT NULL,
5
+ "mission" text,
6
+ "agent_name" text,
7
+ "agent_role" text,
8
+ "first_task_title" text,
9
+ "first_task_details" text,
10
+ "goal_id" uuid,
11
+ "agent_id" uuid,
12
+ "issue_id" uuid,
13
+ "applied_at" timestamp with time zone DEFAULT now() NOT NULL,
14
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
15
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
16
+ );
17
+ --> statement-breakpoint
18
+ DO $$ BEGIN
19
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_onboarding_seeds_company_id_companies_id_fk' AND conrelid = 'company_onboarding_seeds'::regclass) THEN
20
+ ALTER TABLE "company_onboarding_seeds" ADD CONSTRAINT "company_onboarding_seeds_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "companies"("id") ON DELETE cascade;
21
+ END IF;
22
+ END $$;
23
+ --> statement-breakpoint
24
+ DO $$ BEGIN
25
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_onboarding_seeds_goal_id_goals_id_fk' AND conrelid = 'company_onboarding_seeds'::regclass) THEN
26
+ ALTER TABLE "company_onboarding_seeds" ADD CONSTRAINT "company_onboarding_seeds_goal_id_goals_id_fk" FOREIGN KEY ("goal_id") REFERENCES "goals"("id") ON DELETE set null;
27
+ END IF;
28
+ END $$;
29
+ --> statement-breakpoint
30
+ DO $$ BEGIN
31
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_onboarding_seeds_agent_id_agents_id_fk' AND conrelid = 'company_onboarding_seeds'::regclass) THEN
32
+ ALTER TABLE "company_onboarding_seeds" ADD CONSTRAINT "company_onboarding_seeds_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "agents"("id") ON DELETE set null;
33
+ END IF;
34
+ END $$;
35
+ --> statement-breakpoint
36
+ DO $$ BEGIN
37
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_onboarding_seeds_issue_id_issues_id_fk' AND conrelid = 'company_onboarding_seeds'::regclass) THEN
38
+ ALTER TABLE "company_onboarding_seeds" ADD CONSTRAINT "company_onboarding_seeds_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "issues"("id") ON DELETE set null;
39
+ END IF;
40
+ END $$;
41
+ --> statement-breakpoint
42
+ CREATE UNIQUE INDEX IF NOT EXISTS "company_onboarding_seeds_company_uq" ON "company_onboarding_seeds" ("company_id");
@@ -0,0 +1,21 @@
1
+ ALTER TABLE "cost_events" DROP CONSTRAINT "cost_events_issue_id_issues_id_fk";
2
+ --> statement-breakpoint
3
+ ALTER TABLE "feedback_votes" DROP CONSTRAINT "feedback_votes_issue_id_issues_id_fk";
4
+ --> statement-breakpoint
5
+ ALTER TABLE "finance_events" DROP CONSTRAINT "finance_events_issue_id_issues_id_fk";
6
+ --> statement-breakpoint
7
+ ALTER TABLE "issue_comments" DROP CONSTRAINT "issue_comments_issue_id_issues_id_fk";
8
+ --> statement-breakpoint
9
+ ALTER TABLE "issue_inbox_archives" DROP CONSTRAINT "issue_inbox_archives_issue_id_issues_id_fk";
10
+ --> statement-breakpoint
11
+ ALTER TABLE "issue_read_states" DROP CONSTRAINT "issue_read_states_issue_id_issues_id_fk";
12
+ --> statement-breakpoint
13
+ ALTER TABLE "issue_thread_interactions" DROP CONSTRAINT "issue_thread_interactions_issue_id_issues_id_fk";
14
+ --> statement-breakpoint
15
+ ALTER TABLE "cost_events" ADD CONSTRAINT "cost_events_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
16
+ ALTER TABLE "feedback_votes" ADD CONSTRAINT "feedback_votes_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
17
+ ALTER TABLE "finance_events" ADD CONSTRAINT "finance_events_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
18
+ ALTER TABLE "issue_comments" ADD CONSTRAINT "issue_comments_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
19
+ ALTER TABLE "issue_inbox_archives" ADD CONSTRAINT "issue_inbox_archives_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
20
+ ALTER TABLE "issue_read_states" ADD CONSTRAINT "issue_read_states_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
21
+ ALTER TABLE "issue_thread_interactions" ADD CONSTRAINT "issue_thread_interactions_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,38 @@
1
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "requested_resolver_policy" SET DEFAULT 'anyone';--> statement-breakpoint
2
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "effective_resolver_policy" SET DEFAULT 'anyone';--> statement-breakpoint
3
+ ALTER TABLE "issue_thread_interactions" ADD COLUMN IF NOT EXISTS "resolver_policy_provenance" text;--> statement-breakpoint
4
+ ALTER TABLE "issue_thread_interactions" ADD COLUMN IF NOT EXISTS "effective_resolver_policy_source" text;--> statement-breakpoint
5
+ -- Existing rows predate provenance, so their explicit-vs-default origin cannot
6
+ -- be proven. Preserve the old creator-excluding board_or_agents behavior as
7
+ -- not_creator and the old board_only behavior as human_only. This deliberately
8
+ -- avoids widening any ambiguous pending card during migration.
9
+ UPDATE "issue_thread_interactions"
10
+ SET
11
+ "requested_resolver_policy" = CASE "requested_resolver_policy"
12
+ WHEN 'board_or_agents' THEN 'not_creator'
13
+ WHEN 'board_only' THEN 'human_only'
14
+ ELSE "requested_resolver_policy"
15
+ END,
16
+ "effective_resolver_policy" = CASE "effective_resolver_policy"
17
+ WHEN 'board_or_agents' THEN 'not_creator'
18
+ WHEN 'board_only' THEN 'human_only'
19
+ ELSE "effective_resolver_policy"
20
+ END,
21
+ "resolver_policy_provenance" = COALESCE(
22
+ "resolver_policy_provenance",
23
+ 'legacy_inherited_restriction'
24
+ ),
25
+ "effective_resolver_policy_source" = COALESCE(
26
+ "effective_resolver_policy_source",
27
+ CASE
28
+ WHEN "kind" = 'request_confirmation' AND "payload" ? 'toolAction' THEN 'governed_action'
29
+ WHEN "effective_resolver_policy" IS DISTINCT FROM "requested_resolver_policy" THEN 'company_cap'
30
+ ELSE 'requested'
31
+ END
32
+ )
33
+ WHERE "resolver_policy_provenance" IS NULL
34
+ OR "effective_resolver_policy_source" IS NULL;--> statement-breakpoint
35
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "resolver_policy_provenance" SET DEFAULT 'inherited';--> statement-breakpoint
36
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "resolver_policy_provenance" SET NOT NULL;--> statement-breakpoint
37
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "effective_resolver_policy_source" SET DEFAULT 'requested';--> statement-breakpoint
38
+ ALTER TABLE "issue_thread_interactions" ALTER COLUMN "effective_resolver_policy_source" SET NOT NULL;
@@ -0,0 +1,3 @@
1
+ ALTER TABLE "workspace_runtime_services" ADD COLUMN "exposure" jsonb;
2
+ ALTER TABLE "workspace_runtime_services" ADD COLUMN "exposure_handle" text;
3
+ ALTER TABLE "workspace_runtime_services" ADD COLUMN "backend_url" text;
@@ -0,0 +1,26 @@
1
+ CREATE TABLE "execution_workspace_runtime_leases" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "execution_workspace_id" uuid NOT NULL,
5
+ "owner_key" text NOT NULL,
6
+ "owner_issue_id" uuid,
7
+ "owner_run_id" uuid,
8
+ "owner_agent_id" uuid,
9
+ "last_action" text NOT NULL,
10
+ "claimed_at" timestamp with time zone DEFAULT now() NOT NULL,
11
+ "renewed_at" timestamp with time zone DEFAULT now() NOT NULL,
12
+ "expires_at" timestamp with time zone NOT NULL,
13
+ "metadata" jsonb,
14
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
15
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
16
+ CONSTRAINT "execution_workspace_runtime_leases_execution_workspace_id_unique" UNIQUE("execution_workspace_id")
17
+ );
18
+ --> statement-breakpoint
19
+ ALTER TABLE "execution_workspace_runtime_leases" ADD CONSTRAINT "execution_workspace_runtime_leases_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
20
+ ALTER TABLE "execution_workspace_runtime_leases" ADD CONSTRAINT "execution_workspace_runtime_leases_execution_workspace_id_execution_workspaces_id_fk" FOREIGN KEY ("execution_workspace_id") REFERENCES "public"."execution_workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
21
+ ALTER TABLE "execution_workspace_runtime_leases" ADD CONSTRAINT "execution_workspace_runtime_leases_owner_issue_id_issues_id_fk" FOREIGN KEY ("owner_issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
22
+ ALTER TABLE "execution_workspace_runtime_leases" ADD CONSTRAINT "execution_workspace_runtime_leases_owner_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("owner_run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
23
+ ALTER TABLE "execution_workspace_runtime_leases" ADD CONSTRAINT "execution_workspace_runtime_leases_owner_agent_id_agents_id_fk" FOREIGN KEY ("owner_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
24
+ CREATE INDEX "execution_workspace_runtime_leases_company_workspace_idx" ON "execution_workspace_runtime_leases" USING btree ("company_id","execution_workspace_id");--> statement-breakpoint
25
+ CREATE INDEX "execution_workspace_runtime_leases_company_owner_idx" ON "execution_workspace_runtime_leases" USING btree ("company_id","owner_key");--> statement-breakpoint
26
+ CREATE INDEX "execution_workspace_runtime_leases_expires_at_idx" ON "execution_workspace_runtime_leases" USING btree ("expires_at");
@@ -0,0 +1,20 @@
1
+ CREATE TABLE "claude_setup_token_sessions" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "session_id" text NOT NULL,
4
+ "company_id" uuid NOT NULL,
5
+ "owner_user_id" text NOT NULL,
6
+ "adapter_type" text NOT NULL,
7
+ "environment_id" uuid NOT NULL,
8
+ "lease_id" text,
9
+ "state" text DEFAULT 'starting' NOT NULL,
10
+ "deadline_at" timestamp with time zone NOT NULL,
11
+ "bound_at" timestamp with time zone,
12
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
13
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ ALTER TABLE "claude_setup_token_sessions" ADD CONSTRAINT "claude_setup_token_sessions_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
17
+ ALTER TABLE "claude_setup_token_sessions" ADD CONSTRAINT "claude_setup_token_sessions_environment_id_environments_id_fk" FOREIGN KEY ("environment_id") REFERENCES "public"."environments"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
18
+ CREATE UNIQUE INDEX "claude_setup_token_sessions_active_uq" ON "claude_setup_token_sessions" USING btree ("company_id","owner_user_id","adapter_type","environment_id") WHERE "claude_setup_token_sessions"."state" IN ('starting', 'awaiting_code', 'submitting', 'persisting');--> statement-breakpoint
19
+ CREATE UNIQUE INDEX "claude_setup_token_sessions_session_id_uq" ON "claude_setup_token_sessions" USING btree ("session_id");--> statement-breakpoint
20
+ CREATE INDEX "claude_setup_token_sessions_deadline_idx" ON "claude_setup_token_sessions" USING btree ("deadline_at");
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "environment_leases" DROP CONSTRAINT "environment_leases_environment_id_environments_id_fk";
2
+ --> statement-breakpoint
3
+ ALTER TABLE "environment_leases" ALTER COLUMN "environment_id" DROP NOT NULL;--> statement-breakpoint
4
+ ALTER TABLE "environment_leases" ADD CONSTRAINT "environment_leases_environment_id_environments_id_fk" FOREIGN KEY ("environment_id") REFERENCES "public"."environments"("id") ON DELETE set null ON UPDATE no action;