@maudecode/kanvil 0.5.1 → 0.7.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 (137) hide show
  1. package/apps/server/dist/{auth-Bm6cIseE.mjs → auth-D43XyHdK.mjs} +266 -68
  2. package/apps/server/dist/client.mjs +2 -2
  3. package/apps/server/dist/{config-CrJuk5mY.mjs → config-CQVdVhXv.mjs} +1 -1
  4. package/apps/server/dist/index.mjs +167 -45
  5. package/apps/server/dist/migrate.mjs +1 -1
  6. package/apps/server/dist/recover.mjs +3 -3
  7. package/apps/server/dist/{src-D80LNZKP.mjs → src-D70GmZ5R.mjs} +170 -28
  8. package/apps/server/drizzle/0039_intake_credential.sql +2 -0
  9. package/apps/server/drizzle/0040_upload_urls.sql +20 -0
  10. package/apps/server/drizzle/0041_project_repositories.sql +2 -0
  11. package/apps/server/drizzle/meta/0039_snapshot.json +7020 -0
  12. package/apps/server/drizzle/meta/0040_snapshot.json +7170 -0
  13. package/apps/server/drizzle/meta/0041_snapshot.json +7183 -0
  14. package/apps/server/drizzle/meta/_journal.json +21 -0
  15. package/apps/web/dist/assets/{CompositeItem-Tueq2VKR.js → CompositeItem-DLTRsada.js} +1 -1
  16. package/apps/web/dist/assets/{Trans-BgU0eWAX.js → Trans-DqX-qhvQ.js} +1 -1
  17. package/apps/web/dist/assets/admin-settings-BQzdZII5.js +1 -0
  18. package/apps/web/dist/assets/{archive-restore-CSpoH6mS.js → archive-restore-BO1qng5Y.js} +1 -1
  19. package/apps/web/dist/assets/az-AZ-SXqDBPA2.js +1 -0
  20. package/apps/web/dist/assets/{az-DUcDY8Bp.js → az-CEW7-a7J.js} +1 -1
  21. package/apps/web/dist/assets/configuration-D0zvwrXt.js +1 -0
  22. package/apps/web/dist/assets/{corner-left-up-C3OGlXIB.js → corner-left-up-Be7Z9Uhf.js} +1 -1
  23. package/apps/web/dist/assets/{de-89C1V8Ut.js → de-B-oGVMYL.js} +1 -1
  24. package/apps/web/dist/assets/de-DE-CB7aQ6b-.js +1 -0
  25. package/apps/web/dist/assets/default-CCI1vZxa.js +56 -0
  26. package/apps/web/dist/assets/delivery-settings-BrwSrFIN.js +1 -0
  27. package/apps/web/dist/assets/{el-D6CICkhi.js → el-Cp69kezM.js} +1 -1
  28. package/apps/web/dist/assets/el-GR-D1ntYXIt.js +1 -0
  29. package/apps/web/dist/assets/{ellipsis-lJJU8zB7.js → ellipsis-B0AE8ax3.js} +1 -1
  30. package/apps/web/dist/assets/{es-B20Izib2.js → es-CwOMVSTx.js} +1 -1
  31. package/apps/web/dist/assets/es-ES-CllsaxcB.js +1 -0
  32. package/apps/web/dist/assets/{forms--87R7VQW.js → forms-CkVpTx29.js} +1 -1
  33. package/apps/web/dist/assets/{fr-DVlGnGsu.js → fr-Cy4co9ic.js} +1 -1
  34. package/apps/web/dist/assets/fr-FR-DxTw6LgI.js +1 -0
  35. package/apps/web/dist/assets/{hi-D1F5Pi_I.js → hi-DbO9TKwg.js} +1 -1
  36. package/apps/web/dist/assets/hi-IN-CaQga-0l.js +1 -0
  37. package/apps/web/dist/assets/{highlight-ygDJPvRy.js → highlight-zMg1BK-r.js} +1 -1
  38. package/apps/web/dist/assets/{id-LESXKW7G.js → id-B6NKsmCm.js} +1 -1
  39. package/apps/web/dist/assets/id-ID-DBfwAAqU.js +1 -0
  40. package/apps/web/dist/assets/index-CZuFd4LM.js +17 -0
  41. package/apps/web/dist/assets/index-DPT5LAs1.css +2 -0
  42. package/apps/web/dist/assets/invitations-Dp40BfHj.js +1 -0
  43. package/apps/web/dist/assets/it-IT-BckuH9Nl.js +1 -0
  44. package/apps/web/dist/assets/{it-CgRGAs6u.js → it-ilGYCq2T.js} +1 -1
  45. package/apps/web/dist/assets/item-DQR89bKm.js +1 -0
  46. package/apps/web/dist/assets/{ja-B7arhzgX.js → ja-D-hJRTgP.js} +1 -1
  47. package/apps/web/dist/assets/ja-JP-BAGgJKZ4.js +1 -0
  48. package/apps/web/dist/assets/ko-KR-srIEsTP5.js +1 -0
  49. package/apps/web/dist/assets/{ko-Ro_UonyA.js → ko-ajkkoJ_d.js} +1 -1
  50. package/apps/web/dist/assets/label-settings-ChnKkA97.js +1 -0
  51. package/apps/web/dist/assets/{markdown-blocks-toSPlHSc.js → markdown-blocks-CpzrwyQG.js} +1 -1
  52. package/apps/web/dist/assets/member-directory-XK0ZEGUq.js +1 -0
  53. package/apps/web/dist/assets/{mk-DR3kmrIp.js → mk-C_sMyEHX.js} +1 -1
  54. package/apps/web/dist/assets/mk-MK-BTa1NMAF.js +1 -0
  55. package/apps/web/dist/assets/{nl-D3uRJJLT.js → nl-D9-P4UPR.js} +1 -1
  56. package/apps/web/dist/assets/nl-NL-CQduhDqs.js +1 -0
  57. package/apps/web/dist/assets/{pl-CtzDOLdV.js → pl-CiQM7fSB.js} +1 -1
  58. package/apps/web/dist/assets/pl-PL-BdZMf7Ni.js +1 -0
  59. package/apps/web/dist/assets/project-lifecycle-VYecJuiP.js +1 -0
  60. package/apps/web/dist/assets/project-settings-Bs6YEpo9.js +1 -0
  61. package/apps/web/dist/assets/{pt-BR-FarXHHuf.js → pt-BR-CP7dhuqF.js} +1 -1
  62. package/apps/web/dist/assets/pt-BR-DZEXJNHg.js +1 -0
  63. package/apps/web/dist/assets/public-project-DUfWDao9.js +1 -0
  64. package/apps/web/dist/assets/{rotate-ccw-Byx7O3RH.js → rotate-ccw-Cxh9ec2s.js} +1 -1
  65. package/apps/web/dist/assets/{ru-DHMEVxvB.js → ru-DxJ6vF4E.js} +1 -1
  66. package/apps/web/dist/assets/ru-RU-CZKEe7P8.js +1 -0
  67. package/apps/web/dist/assets/search-DfbsqO7M.js +85 -0
  68. package/apps/web/dist/assets/{send-DlGV2XQS.js → send-DrJl0BKm.js} +1 -1
  69. package/apps/web/dist/assets/settings-BN8uIiBG.js +1 -0
  70. package/apps/web/dist/assets/{sliders-horizontal-CEHGGft_.js → sliders-horizontal-DM47MLe7.js} +1 -1
  71. package/apps/web/dist/assets/switch-CJTVGtE9.js +1 -0
  72. package/apps/web/dist/assets/{table-2AEfwytk.js → table-BLLjFPWD.js} +1 -1
  73. package/apps/web/dist/assets/ticket-detail-BTy_3JeU.js +2 -0
  74. package/apps/web/dist/assets/ticket-editor-Bb_lyxnJ.js +2 -0
  75. package/apps/web/dist/assets/ticket-list-Botp5qf5.js +6 -0
  76. package/apps/web/dist/assets/ticket-list-controls-Dmkno4pm.js +1 -0
  77. package/apps/web/dist/assets/{tr-CjdSDu0z.js → tr-9IkdRLIk.js} +1 -1
  78. package/apps/web/dist/assets/tr-TR-Y8wBLO8I.js +1 -0
  79. package/apps/web/dist/assets/{uk-C8od6u_H.js → uk-Btampsdw.js} +1 -1
  80. package/apps/web/dist/assets/uk-UA-CVpasGUS.js +1 -0
  81. package/apps/web/dist/assets/{upload-BeTAGU_W.js → upload-HARy4VC_.js} +1 -1
  82. package/apps/web/dist/assets/{useQueries-BtRgTciJ.js → useQueries-CTeEF--U.js} +1 -1
  83. package/apps/web/dist/assets/{vi-BwdBtgfS.js → vi-BVZzOn_n.js} +1 -1
  84. package/apps/web/dist/assets/vi-VN-BMy-iJD-.js +1 -0
  85. package/apps/web/dist/assets/visual-editor-DKBPjqV-.js +208 -0
  86. package/apps/web/dist/assets/workspace-settings-DqzBNw60.js +1 -0
  87. package/apps/web/dist/assets/{zh-CN-DM-UoFmL.js → zh-CN-BoUvF2do.js} +1 -1
  88. package/apps/web/dist/assets/zh-CN-Cds_v0R8.js +1 -0
  89. package/apps/web/dist/assets/{zh-TW-q2nrwFjt.js → zh-TW-CEIDGTWe.js} +1 -1
  90. package/apps/web/dist/assets/zh-TW-DCCYakXz.js +1 -0
  91. package/apps/web/dist/index.html +9 -9
  92. package/docs/api.md +35 -5
  93. package/docs/cli.md +1 -1
  94. package/docs/mobile.md +67 -4
  95. package/docs/releasing.md +6 -4
  96. package/package.json +1 -1
  97. package/apps/web/dist/assets/admin-settings-Ckis3XJG.js +0 -1
  98. package/apps/web/dist/assets/az-AZ-bFxpMMZN.js +0 -1
  99. package/apps/web/dist/assets/de-DE-BeXI30Ll.js +0 -1
  100. package/apps/web/dist/assets/default-Dnep8Yat.js +0 -56
  101. package/apps/web/dist/assets/delivery-settings-cMldZ9K7.js +0 -1
  102. package/apps/web/dist/assets/el-GR-SgRHlWhY.js +0 -1
  103. package/apps/web/dist/assets/es-ES-BF1J5vap.js +0 -1
  104. package/apps/web/dist/assets/fr-FR-D_sldwf6.js +0 -1
  105. package/apps/web/dist/assets/hi-IN-CfOw4TWf.js +0 -1
  106. package/apps/web/dist/assets/id-ID-CLKtHO7Q.js +0 -1
  107. package/apps/web/dist/assets/index-Bn-MADyj.css +0 -2
  108. package/apps/web/dist/assets/index-Ds3IHeIi.js +0 -17
  109. package/apps/web/dist/assets/invitations-C5WbdDUQ.js +0 -1
  110. package/apps/web/dist/assets/it-IT-eVZNW5qX.js +0 -1
  111. package/apps/web/dist/assets/item-BD1Poxfs.js +0 -1
  112. package/apps/web/dist/assets/ja-JP-D96njn-P.js +0 -1
  113. package/apps/web/dist/assets/ko-KR-Bash_ieA.js +0 -1
  114. package/apps/web/dist/assets/label-settings-BaikCfal.js +0 -1
  115. package/apps/web/dist/assets/member-directory-BjUy1KuK.js +0 -1
  116. package/apps/web/dist/assets/mk-MK-BWQWGIRx.js +0 -1
  117. package/apps/web/dist/assets/nl-NL-D1tvo0Gd.js +0 -1
  118. package/apps/web/dist/assets/pl-PL-DNgGUEcQ.js +0 -1
  119. package/apps/web/dist/assets/project-lifecycle-BBHcRi6p.js +0 -1
  120. package/apps/web/dist/assets/project-settings-BaYuxYjg.js +0 -1
  121. package/apps/web/dist/assets/pt-BR-CZsUZQ6P.js +0 -1
  122. package/apps/web/dist/assets/public-project-DGf3nkg2.js +0 -1
  123. package/apps/web/dist/assets/ru-RU-4ew92YE_.js +0 -1
  124. package/apps/web/dist/assets/search-DwsPEC4E.js +0 -85
  125. package/apps/web/dist/assets/settings-C_sN8Y1h.js +0 -1
  126. package/apps/web/dist/assets/switch-B_rsZYBf.js +0 -1
  127. package/apps/web/dist/assets/ticket-detail-C2l8nwF-.js +0 -2
  128. package/apps/web/dist/assets/ticket-editor-B0UB98HS.js +0 -2
  129. package/apps/web/dist/assets/ticket-list-D_MHudj1.js +0 -6
  130. package/apps/web/dist/assets/ticket-list-controls-jKg4i-NA.js +0 -1
  131. package/apps/web/dist/assets/tr-TR-CM381XCw.js +0 -1
  132. package/apps/web/dist/assets/uk-UA-AeOiWCVo.js +0 -1
  133. package/apps/web/dist/assets/vi-VN-td08xXv9.js +0 -1
  134. package/apps/web/dist/assets/visual-editor-CzB_qwvB.js +0 -208
  135. package/apps/web/dist/assets/workspace-settings-DOr9j8X1.js +0 -1
  136. package/apps/web/dist/assets/zh-CN-D3dhEYLS.js +0 -1
  137. package/apps/web/dist/assets/zh-TW-CfhOEFo8.js +0 -1
@@ -1,5 +1,79 @@
1
1
  import { z } from "zod";
2
2
  import i18next from "i18next";
3
+ //#region ../../packages/contracts/src/icons.ts
4
+ const ticketSymbols = {
5
+ status: {
6
+ backlog: {
7
+ icon: "circle-dashed",
8
+ tone: "muted"
9
+ },
10
+ todo: {
11
+ icon: "circle",
12
+ tone: "muted"
13
+ },
14
+ in_progress: {
15
+ icon: "circle-dot",
16
+ tone: "accent"
17
+ },
18
+ in_review: {
19
+ icon: "clock",
20
+ tone: "warning"
21
+ },
22
+ done: {
23
+ icon: "circle-check",
24
+ tone: "success"
25
+ },
26
+ cancelled: {
27
+ icon: "circle-x",
28
+ tone: "muted"
29
+ }
30
+ },
31
+ priority: {
32
+ urgent: {
33
+ icon: "octagon-alert",
34
+ tone: "danger"
35
+ },
36
+ high: {
37
+ icon: "arrow-up",
38
+ tone: "warning"
39
+ },
40
+ medium: {
41
+ icon: "equal",
42
+ tone: "foreground"
43
+ },
44
+ low: {
45
+ icon: "arrow-down",
46
+ tone: "accent"
47
+ },
48
+ none: {
49
+ icon: "minus",
50
+ tone: "muted"
51
+ }
52
+ },
53
+ kind: {
54
+ feature: {
55
+ icon: "sparkles",
56
+ tone: "muted"
57
+ },
58
+ bug: {
59
+ icon: "bug",
60
+ tone: "muted"
61
+ },
62
+ chore: {
63
+ icon: "wrench",
64
+ tone: "muted"
65
+ },
66
+ research: {
67
+ icon: "flask-conical",
68
+ tone: "muted"
69
+ },
70
+ documentation: {
71
+ icon: "book-open",
72
+ tone: "muted"
73
+ }
74
+ }
75
+ };
76
+ //#endregion
3
77
  //#region ../../packages/contracts/src/instance.ts
4
78
  const endpoint$1 = z.url({ protocol: /^https?$/ }).refine((value) => !/^https?:\/\/[^/]*@/.test(value) && !/[?#]/.test(value), "Use an HTTP(S) endpoint without embedded credentials");
5
79
  const s3SettingsSchema = z.object({
@@ -216,10 +290,15 @@ var en_US_default = {
216
290
  priority: "Priority",
217
291
  kind: "Kind",
218
292
  difficulty: "Difficulty",
293
+ automation: "Agent readiness",
219
294
  label: "Label",
220
295
  assigneeId: "Assignee",
221
296
  customField: "Field"
222
297
  },
298
+ automationFilter: {
299
+ ready: "Ready for agents",
300
+ manual: "Needs a person"
301
+ },
223
302
  sort: {
224
303
  priority: "Priority",
225
304
  updated: "Recently updated",
@@ -461,6 +540,7 @@ var en_US_default = {
461
540
  time_entry_conflict: "This actor already has a running entry on the ticket.",
462
541
  claim_conflict: "Another worker holds this ticket.",
463
542
  idempotency_conflict: "This request was already used for another change.",
543
+ duplicate_repository: "Another project in this workspace links this repository.",
464
544
  project_archived: "Restore the archived project before changing it.",
465
545
  rate_limited: "Too many changes in a short time. Wait and retry.",
466
546
  snapshot_required: "The live feed fell behind. Reload to continue.",
@@ -930,6 +1010,7 @@ var en_US_default = {
930
1010
  },
931
1011
  ticket: {
932
1012
  list: {
1013
+ manageViews: "Manage views",
933
1014
  selectSection: "Select {{section}} tickets",
934
1015
  expandSection: "Expand {{section}} tickets",
935
1016
  collapseSection: "Collapse {{section}} tickets",
@@ -1058,6 +1139,7 @@ var en_US_default = {
1058
1139
  noDue: "No due date"
1059
1140
  },
1060
1141
  filter: {
1142
+ add: "Add filter",
1061
1143
  me: "Me",
1062
1144
  searchTickets: "Search tickets",
1063
1145
  searchTicketsPlaceholder: "Search tickets…",
@@ -1086,6 +1168,7 @@ var en_US_default = {
1086
1168
  priority: "All priorities",
1087
1169
  kind: "All kinds",
1088
1170
  difficulty: "All difficulties",
1171
+ automation: "Any readiness",
1089
1172
  label: "All labels",
1090
1173
  assigneeId: "Anyone",
1091
1174
  customField: "Any field value"
@@ -1095,6 +1178,7 @@ var en_US_default = {
1095
1178
  priority: "Search priorities",
1096
1179
  kind: "Search kinds",
1097
1180
  difficulty: "Search difficulties",
1181
+ automation: "Search readiness",
1098
1182
  label: "Search labels",
1099
1183
  assigneeId: "Search people",
1100
1184
  customField: "Search fields"
@@ -1550,7 +1634,7 @@ var en_US_default = {
1550
1634
  permission: {
1551
1635
  intake: {
1552
1636
  name: "Submit reports",
1553
- description: "Create quarantined tickets only. Cannot read or edit tickets. Use alone."
1637
+ description: "Create quarantined tickets and attach files to them only. Cannot read or edit tickets. Use alone."
1554
1638
  },
1555
1639
  read: {
1556
1640
  name: "Read tickets",
@@ -1627,6 +1711,9 @@ var en_US_default = {
1627
1711
  changePrefixDescription: "Every ticket in {{name}} takes the new prefix and keeps its number.",
1628
1712
  changing: "Changing…",
1629
1713
  prefixChanged: "Tickets now use {{key}}",
1714
+ repositories: "Repositories",
1715
+ repositoriesDescription: "Agents can pass one of these git remotes as the project ID.",
1716
+ repositoriesInvalid: "Enter up to 20 git remotes, such as git@github.com:owner/repo.git.",
1630
1717
  publicLink: "Public link",
1631
1718
  publicDisclosure: "Anyone with the link can read every unarchived ticket's title, description, acceptance criteria, status, priority, kind, difficulty, labels, scopes, dates, and links to other tickets in this project. People, comments, activity, attachments, evidence, and claims stay private.",
1632
1719
  publicOn: "Public link on",
@@ -2497,6 +2584,9 @@ var en_US_default = {
2497
2584
  }
2498
2585
  },
2499
2586
  native: {
2587
+ "navigation.projectButton": "{{project}} ⌄",
2588
+ "navigation.recentProjects": "Recent projects",
2589
+ "navigation.switchProject": "Switch workspace or project",
2500
2590
  labelValue: "{{label}}: {{value}}",
2501
2591
  ui: {
2502
2592
  dismiss: "Dismiss",
@@ -2545,6 +2635,10 @@ var en_US_default = {
2545
2635
  create: "Create project"
2546
2636
  },
2547
2637
  tickets: {
2638
+ options: "List options",
2639
+ expandAll: "Expand all sections",
2640
+ collapseAll: "Collapse all sections",
2641
+ select: "Select tickets",
2548
2642
  search: "Search tickets",
2549
2643
  searchPlaceholder: "Title, description, or key",
2550
2644
  allStatuses: "All statuses",
@@ -2671,6 +2765,7 @@ var en_US_default = {
2671
2765
  next: "Next activity"
2672
2766
  },
2673
2767
  inbox: {
2768
+ read: "Read",
2674
2769
  markAllRead: "Mark all read",
2675
2770
  empty: "No notifications"
2676
2771
  },
@@ -2853,8 +2948,10 @@ const scopes = [
2853
2948
  ];
2854
2949
  const attachmentLimit = 1e7;
2855
2950
  const stagedUploadLifetime = 864e5;
2951
+ const uploadUrlLifetime = 9e5;
2856
2952
  const stateLabels = labelTable(states, (value) => t(`common.status.${value}`));
2857
2953
  const priorityLabels = labelTable(priorities, (value) => t(`common.priority.${value}`));
2954
+ ticketSymbols.status.backlog.tone, ticketSymbols.status.todo.tone, ticketSymbols.status.in_progress.tone, ticketSymbols.status.in_review.tone, ticketSymbols.status.done.tone, ticketSymbols.status.cancelled.tone;
2858
2955
  const id = z.string().min(1).max(80);
2859
2956
  const timestamp = z.iso.datetime();
2860
2957
  const version = z.number().int().positive();
@@ -2968,9 +3065,30 @@ const placement = {
2968
3065
  after: id.optional()
2969
3066
  };
2970
3067
  const oneNeighbor = (input) => input.before === void 0 || input.after === void 0;
2971
- const projectInput = z.object({ projectId: id });
3068
+ const projectInput = z.object({ projectId: z.string().min(1).max(300) });
2972
3069
  const ticketInput = projectInput.extend({ ticketId: id });
2973
3070
  const projectKey = z.string().trim().regex(/^[A-Z][A-Z0-9]{1,9}$/);
3071
+ const remoteHost = "(?<host>[a-z0-9][a-z0-9.-]*)";
3072
+ const remotePath = "(?<path>[^?#]+)";
3073
+ const remoteForms = [
3074
+ new RegExp(`^(?<scheme>https|ssh)://(?:[^/]*@)?${remoteHost}(?::(?<port>\\d+))?/${remotePath}$`),
3075
+ new RegExp(`^[^/:@]+@${remoteHost}:${remotePath}$`),
3076
+ new RegExp(`^${remoteHost}(?::(?<port>\\d+))?/${remotePath}$`)
3077
+ ];
3078
+ const defaultRemotePorts = {
3079
+ https: "443",
3080
+ ssh: "22"
3081
+ };
3082
+ function normalizeRemote(value) {
3083
+ const remote = value.trim().toLowerCase();
3084
+ if (/\s/.test(remote)) return null;
3085
+ const { scheme, host, port, path } = remoteForms.map((form) => form.exec(remote)).find(Boolean)?.groups ?? {};
3086
+ const segments = path?.replace(/\/+$/, "").replace(/\.git$/, "").split("/").filter(Boolean);
3087
+ if (!host || !segments?.length) return null;
3088
+ return `${host}${port && port !== defaultRemotePorts[scheme ?? ""] ? `:${port}` : ""}/${segments.join("/")}`;
3089
+ }
3090
+ const repositoryRemote = z.string().max(300).refine((value) => normalizeRemote(value) !== null, "Enter a git remote URL").overwrite((value) => normalizeRemote(value) ?? value);
3091
+ const projectRepositories = z.array(repositoryRemote).max(20).overwrite((remotes) => [...new Set(remotes)]);
2974
3092
  const reason = z.object({
2975
3093
  code: z.string(),
2976
3094
  message: z.string(),
@@ -2987,15 +3105,19 @@ const filterFieldNames = [
2987
3105
  "priority",
2988
3106
  "kind",
2989
3107
  "difficulty",
3108
+ "automation",
2990
3109
  "label",
2991
3110
  "assigneeId",
2992
3111
  "customField"
2993
3112
  ];
3113
+ const automationFilters = ["ready", "manual"];
3114
+ labelTable(automationFilters, (value) => t(`common.automationFilter.${value}`));
2994
3115
  const filterFields = {
2995
3116
  status: z.enum(states),
2996
3117
  priority: z.enum(priorities),
2997
3118
  kind: z.enum(kinds),
2998
3119
  difficulty: z.enum(difficulties),
3120
+ automation: z.enum(automationFilters),
2999
3121
  label: z.string().max(40),
3000
3122
  assigneeId: z.union([id, z.literal("none")]),
3001
3123
  customField: z.string().regex(/^[0-9a-f-]{36}:(?:none|true|[0-9a-f-]{36})$/)
@@ -3013,6 +3135,8 @@ const filterShape = {
3013
3135
  kindNot: filterValues(filterFields.kind),
3014
3136
  difficulty: filterValues(filterFields.difficulty),
3015
3137
  difficultyNot: filterValues(filterFields.difficulty),
3138
+ automation: filterValues(filterFields.automation),
3139
+ automationNot: filterValues(filterFields.automation),
3016
3140
  label: filterValues(filterFields.label),
3017
3141
  labelNot: filterValues(filterFields.label),
3018
3142
  assigneeId: filterValues(filterFields.assigneeId),
@@ -3082,6 +3206,7 @@ const ticketFilter = z.object({
3082
3206
  ]).default("priority"),
3083
3207
  order: z.enum(["asc", "desc"]).optional()
3084
3208
  }).strict().superRefine(rejectConflicts);
3209
+ const listSort = ticketFilter.shape.sort.unwrap().optional();
3085
3210
  labelTable(ticketFilter.shape.sort.unwrap().options, (sort) => t(`common.sort.${sort}`));
3086
3211
  const defaultOrder = {
3087
3212
  priority: "asc",
@@ -3190,6 +3315,7 @@ const projectSchema = z.object({
3190
3315
  key: z.string(),
3191
3316
  name: z.string(),
3192
3317
  description: z.string(),
3318
+ repositories: z.array(z.string()).default([]),
3193
3319
  version,
3194
3320
  archivedAt: timestamp.nullable().default(null),
3195
3321
  createdAt: timestamp,
@@ -3360,6 +3486,11 @@ const attachmentSchema = z.object({
3360
3486
  createdAt: timestamp
3361
3487
  });
3362
3488
  const stagedUploadSchema = attachmentSchema.omit({ ticketId: true }).extend({ expiresAt: timestamp });
3489
+ const uploadUrlSchema = z.object({
3490
+ uploadId: z.uuid(),
3491
+ url: z.url(),
3492
+ expiresAt: timestamp
3493
+ });
3363
3494
  const httpUrl = z.url().regex(/^https?:\/\//i, "Use an HTTP or HTTPS URL");
3364
3495
  const evidenceFields = z.object({
3365
3496
  kind: z.enum([
@@ -4125,21 +4256,25 @@ const page = (item) => z.object({
4125
4256
  items: z.array(item),
4126
4257
  total: z.number().int().nonnegative()
4127
4258
  });
4128
- const fileFields = {
4259
+ const fileMetadata = {
4129
4260
  name: text.max(255).refine((value) => {
4130
4261
  for (const character of value) if (character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127) return false;
4131
4262
  return true;
4132
4263
  }, "Use a filename without control characters"),
4133
- contentType: z.string().max(120).regex(/^[a-z0-9][a-z0-9.+-]*\/[a-z0-9][a-z0-9.+-]*$/i).default("application/octet-stream"),
4264
+ contentType: z.string().max(120).regex(/^[a-z0-9][a-z0-9.+-]*\/[a-z0-9][a-z0-9.+-]*$/i).default("application/octet-stream")
4265
+ };
4266
+ const fileFields = {
4267
+ ...fileMetadata,
4134
4268
  data: z.string().max(Math.ceil(attachmentLimit / 3) * 4)
4135
4269
  };
4136
- const op = (input, output, method, path, scope, description) => ({
4270
+ const op = (input, output, method, path, scope, description, options = {}) => ({
4137
4271
  input,
4138
4272
  output,
4139
4273
  method,
4140
4274
  path,
4141
4275
  scope,
4142
- description
4276
+ description,
4277
+ ...options
4143
4278
  });
4144
4279
  const operations = {
4145
4280
  list_workspaces: op(z.object({}), z.array(workspaceSchema), "GET", "/workspaces", "read", "List accessible workspaces and the current membership role."),
@@ -4329,8 +4464,9 @@ const operations = {
4329
4464
  publicReadEnabled: z.boolean().optional(),
4330
4465
  name: text.max(120),
4331
4466
  description: z.string().max(5e3),
4332
- key: projectKey.optional()
4333
- }).strict(), projectSchema, "PATCH", "/projects/{projectId}", "admin", "Update project details. A new `key` re-keys every ticket of the project; the previous prefix stays reserved for the project, and the project and every key issued under it keep resolving. `publicReadEnabled` shares or stops sharing the project's read-only public view (see the public operations)."),
4467
+ key: projectKey.optional(),
4468
+ repositories: projectRepositories.optional()
4469
+ }).strict(), projectSchema, "PATCH", "/projects/{projectId}", "admin", "Update project details. A new `key` re-keys every ticket of the project; the previous prefix stays reserved for the project, and the project and every key issued under it keep resolving. `publicReadEnabled` shares or stops sharing the project's read-only public view (see the public operations). `repositories` replaces the project's linked git remotes (at most 20), and any `projectId` then accepts one of them; within a workspace only one unarchived project can hold a remote."),
4334
4470
  move_project: op(projectInput.extend({
4335
4471
  ...mutation,
4336
4472
  expectedVersion: version,
@@ -4394,13 +4530,14 @@ const operations = {
4394
4530
  }).strict(), okSchema, "POST", "/projects/{projectId}/members", "admin", "Add or update an existing user's membership with a seeded role or a custom role of the project's workspace, or remove it with a null role. Needs `member.manage`; the role, and any role the person holds now, must grant nothing the caller lacks."),
4395
4531
  list_tickets: op(projectInput.extend({
4396
4532
  ...ticketFilter.shape,
4533
+ sort: listSort,
4397
4534
  ...pagination,
4398
4535
  relatedTo: id.optional(),
4399
4536
  stateId: z.uuid().optional(),
4400
4537
  scheduledFrom: timestamp.optional(),
4401
4538
  scheduledTo: timestamp.optional(),
4402
4539
  ...ticketView
4403
- }).superRefine(rejectConflicts), page(ticketRow), "GET", "/projects/{projectId}/tickets", "read", "Search tickets with server-side filters, stable ordering, and pagination. Each property filter takes one value or a repeated list (any of them); its `Not` twin excludes values. Double-quoted segments of `q` match as exact phrases. Pass `view: \"summary\"` when scanning results: rows then omit the description and acceptance criteria."),
4540
+ }).superRefine(rejectConflicts), page(ticketRow), "GET", "/projects/{projectId}/tickets", "read", "Search tickets with server-side filters, stable ordering, and pagination. Each property filter takes one value or a repeated list (any of them); its `Not` twin excludes values. `q` keeps only tickets whose key, title, description, acceptance criteria, labels, or scopes contain its text as written, or whose key or ID it names exactly; double-quoted segments are exact phrases that must each appear on word boundaries, so `\"IME\"` does not match `time` while unquoted `IME` does. With `q` and no `sort`, results order by relevance as in search_tickets; otherwise by `sort` (default `priority`). With `view: \"summary\"`, rows omit the description and acceptance criteria."),
4404
4541
  list_ticket_labels: op(projectInput.extend({ archived: ticketFilter.shape.archived }), z.array(z.object({
4405
4542
  name: z.string(),
4406
4543
  count: z.number().int().nonnegative()
@@ -4494,7 +4631,7 @@ const operations = {
4494
4631
  claim: claimSchema.nullable(),
4495
4632
  subscribed: z.boolean(),
4496
4633
  canReleaseClaim: z.boolean()
4497
- }), "GET", "/projects/{projectId}/tickets/{ticketId}", "read", "Read a ticket by ID or key, with readiness and ownership."),
4634
+ }), "GET", "/projects/{projectId}/tickets/{ticketId}", "read", "Read a ticket by ID or key, with readiness and ownership.", { mcp: "core" }),
4498
4635
  create_ticket: op(projectInput.extend({
4499
4636
  ...mutation,
4500
4637
  title: ticketFields.shape.title,
@@ -4516,14 +4653,14 @@ const operations = {
4516
4653
  archived: z.boolean().default(false),
4517
4654
  uploads: z.array(z.uuid()).max(50).default([]),
4518
4655
  customFields: customFieldValues.default({})
4519
- }).strict(), ticketSchema, "POST", "/projects/{projectId}/tickets", "write", "Create a ticket. `customFields` maps field IDs from list_custom_fields to values; omitted fields take their default, and a required field must end with a value. `uploads` lists your staged inline uploads in this project; they become its attachments in the same write, or nothing is created. Reuse requestId when retrying this write."),
4656
+ }).strict(), ticketSchema, "POST", "/projects/{projectId}/tickets", "write", "Create a ticket. `customFields` maps field IDs from list_custom_fields to values; omitted fields take their default, and a required field must end with a value. `uploads` lists your staged inline uploads in this project; they become its attachments in the same write, or nothing is created. Reuse requestId when retrying this write.", { mcp: "core" }),
4520
4657
  duplicate_ticket: op(ticketInput.extend(mutation).strict(), ticketSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/duplicate", "write", "Copy a ticket into a new To do ticket in the same project, linked to the original by a clones relationship. Copies requirements, properties, labels, scopes, and parent; resets agent readiness and never copies claims, comments, evidence, attachments, or children. Reuse requestId when retrying this write."),
4521
4658
  update_ticket: op(ticketInput.extend({
4522
4659
  ...mutation,
4523
4660
  expectedVersion: version,
4524
4661
  changes: ticketChanges,
4525
4662
  claimId: z.uuid().optional()
4526
- }).strict(), ticketSchema, "PATCH", "/projects/{projectId}/tickets/{ticketId}", "write", "Update a ticket with optimistic concurrency. Worker completion requires its active claim. `changes.customFields` sets only the named fields; null clears one."),
4663
+ }).strict(), ticketSchema, "PATCH", "/projects/{projectId}/tickets/{ticketId}", "write", "Update a ticket with optimistic concurrency. Worker completion requires its active claim. `changes.customFields` sets only the named fields; null clears one.", { mcp: "core" }),
4527
4664
  update_ticket_labels: op(ticketInput.extend({
4528
4665
  ...mutation,
4529
4666
  expectedVersion: version,
@@ -4553,7 +4690,7 @@ const operations = {
4553
4690
  resolve_ticket: op(z.object({ ticketId: id }).strict(), z.object({
4554
4691
  ticket: ticketSchema,
4555
4692
  project: projectRef
4556
- }), "GET", "/tickets/resolve", "read", "Find a ticket by ID, current key, or any earlier key from a prefix change or a move, across every accessible project. An unknown or inaccessible ticket reads as not found."),
4693
+ }), "GET", "/tickets/resolve", "read", "Find a ticket by ID, current key, or any earlier key from a prefix change or a move, across every accessible project. An unknown or inaccessible ticket reads as not found.", { mcp: "core" }),
4557
4694
  bulk_update_tickets: op(projectInput.extend({
4558
4695
  ...mutation,
4559
4696
  tickets: claimedTicketSelection,
@@ -4576,7 +4713,7 @@ const operations = {
4576
4713
  ticket: ticketRow,
4577
4714
  project: projectRef,
4578
4715
  snippet: z.string().optional()
4579
- })) }), "GET", "/tickets/search", "read", "Search unarchived tickets by key or text across every accessible project, optionally within one workspace. Results order by exact key match, then relevance, then recency. Double-quoted segments of `q` match as exact phrases. Pass `view: \"summary\"` when scanning results: each ticket is then a compact row and the result carries a `snippet` of the matching text."),
4716
+ })) }), "GET", "/tickets/search", "read", "Search unarchived tickets by key or text across every accessible project, optionally within one workspace. Results order by exact key match, then relevance, then recency. Double-quoted segments of `q` match as exact phrases on word boundaries, so `\"IME\"` does not match `time`. With `view: \"summary\"`, each ticket is a compact row and the result carries a `snippet` of the matching text.", { mcp: "core" }),
4580
4717
  search_workspace: op(z.object({
4581
4718
  q: z.string().trim().min(1).max(200),
4582
4719
  workspaceId: z.uuid().optional(),
@@ -4591,19 +4728,19 @@ const operations = {
4591
4728
  counts: z.record(z.enum(searchResultTypes), z.number().int().nonnegative()),
4592
4729
  engine: z.enum(["postgres", "index"]),
4593
4730
  indexing: z.boolean()
4594
- }), "GET", "/search", "read", "Search accessible tickets, projects, comments, and activity by text or ticket key, optionally within one workspace or one result type. Property filters restrict results to matching tickets. Results order by exact key match, then type, then ticket relevance, then recency. Double-quoted segments of `q` match ticket text as exact phrases. Pass `view: \"summary\"` when scanning results: ticket results then carry their summary row and each result a `snippet` of the matching text."),
4731
+ }), "GET", "/search", "read", "Search accessible tickets, projects, comments, and activity by text or ticket key, optionally within one workspace or one result type. Property filters restrict results to matching tickets. Results order by exact key match, then type, then ticket relevance, then recency. Double-quoted segments of `q` match ticket text as exact phrases on word boundaries. With `view: \"summary\"`, ticket results carry their summary row and each result a `snippet` of the matching text."),
4595
4732
  list_my_work: op(z.object({
4596
4733
  workspaceId: z.uuid().optional(),
4597
4734
  q: ticketFilter.shape.q,
4598
- sort: ticketFilter.shape.sort,
4735
+ sort: listSort,
4599
4736
  order: ticketFilter.shape.order,
4600
4737
  activity: z.coerce.number().int().min(0).max(50).default(0),
4601
4738
  ...pagination
4602
- }).strict(), page(ticketSchema).extend({ activity: z.array(eventSchema).default([]) }), "GET", "/my-work", "read", "List open, unarchived tickets assigned to the current identity across every accessible project, optionally within one workspace, with the most recent accessible activity when `activity` is set."),
4739
+ }).strict(), page(ticketSchema).extend({ activity: z.array(eventSchema).default([]) }), "GET", "/my-work", "read", "List open, unarchived tickets assigned to the current identity across every accessible project, optionally within one workspace, with the most recent accessible activity when `activity` is set. `q` and `sort` work as in list_tickets.", { mcp: "core" }),
4603
4740
  list_eligible_tickets: op(projectInput.extend(pagination), page(z.object({
4604
4741
  ticket: ticketSchema,
4605
4742
  readiness: readinessSchema
4606
- })), "GET", "/projects/{projectId}/eligibility", "read", "Inspect eligibility and explicit blocking reasons for open tickets."),
4743
+ })), "GET", "/projects/{projectId}/eligibility", "read", "Inspect eligibility and explicit blocking reasons for open tickets.", { mcp: "core" }),
4607
4744
  list_relations: op(ticketInput, z.array(relationSchema), "GET", "/projects/{projectId}/tickets/{ticketId}/relations", "read", "List incoming and outgoing ticket relationships with each side's key, title, and project. A ticket in a project the caller cannot read appears by ID and key alone, with `restricted: true`."),
4608
4745
  add_relation: op(ticketInput.extend({
4609
4746
  ...mutation,
@@ -4619,7 +4756,7 @@ const operations = {
4619
4756
  add_comment: op(ticketInput.extend({
4620
4757
  ...mutation,
4621
4758
  body: text.max(5e4)
4622
- }).strict(), commentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/comments", "write", "Add a comment with authenticated attribution. Mention a project member with `[@Name](mention:<user id>)` from list_members; members who can read the project are notified."),
4759
+ }).strict(), commentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/comments", "write", "Add a comment with authenticated attribution. Mention a project member with `[@Name](mention:<user id>)` from list_members; members who can read the project are notified.", { mcp: "core" }),
4623
4760
  update_comment: op(projectInput.extend({
4624
4761
  ...mutation,
4625
4762
  commentId: z.uuid(),
@@ -4635,16 +4772,21 @@ const operations = {
4635
4772
  upload_attachment: op(ticketInput.extend({
4636
4773
  ...mutation,
4637
4774
  ...fileFields
4638
- }).strict(), attachmentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/attachments", "write", "Upload up to 10 MB of base64-encoded bytes. The original filename is metadata, never a filesystem path."),
4775
+ }).strict(), attachmentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/attachments", "write", "Upload up to 10 MB of base64-encoded bytes. The original filename is metadata, never a filesystem path. An intake credential can attach up to 10 files to a quarantined ticket it created, within 1 GB across its quarantined tickets. For a file on disk, use create_upload_url instead of inlining it."),
4639
4776
  stage_upload: op(projectInput.extend({
4640
4777
  ...mutation,
4641
4778
  ...fileFields
4642
- }).strict(), stagedUploadSchema, "POST", "/projects/{projectId}/uploads", "write", "Stage up to 10 MB of base64-encoded bytes for a ticket that does not exist yet. Only you can read it, at its attachment content address, until create_ticket claims it; unclaimed uploads expire after 24 hours."),
4779
+ }).strict(), stagedUploadSchema, "POST", "/projects/{projectId}/uploads", "write", "Stage up to 10 MB of base64-encoded bytes for a ticket that does not exist yet. Only you can read it, at its attachment content address, until create_ticket claims it; unclaimed uploads expire after 24 hours. For a file on disk, use create_upload_url instead of inlining it."),
4780
+ create_upload_url: op(projectInput.extend({
4781
+ ...fileMetadata,
4782
+ ticketId: id.optional(),
4783
+ size: z.number().int().nonnegative().max(attachmentLimit)
4784
+ }).strict(), uploadUrlSchema, "POST", "/projects/{projectId}/upload-urls", "write", "Get a single-use URL for one file of up to 10 MB, so its bytes never pass through the tool call. PUT exactly `size` bytes to `url` within 15 minutes, for example `curl --upload-file <path> <url>`; the URL needs no other credential and reads nothing. With `ticketId` the file becomes that ticket's attachment; without it, it is a staged upload that create_ticket `uploads` claims by `uploadId`."),
4643
4785
  discard_upload: op(projectInput.extend({
4644
4786
  ...mutation,
4645
4787
  uploadId: z.uuid()
4646
4788
  }).strict(), okSchema, "DELETE", "/projects/{projectId}/uploads/{uploadId}", "write", "Delete one of your unclaimed staged uploads and its bytes."),
4647
- list_attachments: op(ticketInput, z.array(attachmentSchema), "GET", "/projects/{projectId}/tickets/{ticketId}/attachments", "read", "List authorized attachment metadata."),
4789
+ list_attachments: op(ticketInput, z.array(attachmentSchema), "GET", "/projects/{projectId}/tickets/{ticketId}/attachments", "read", "List authorized attachment metadata. An intake credential can list them on a quarantined ticket it created."),
4648
4790
  delete_attachment: op(projectInput.extend({
4649
4791
  ...mutation,
4650
4792
  attachmentId: z.uuid()
@@ -4654,7 +4796,7 @@ const operations = {
4654
4796
  ...mutation,
4655
4797
  ...evidenceFields.shape,
4656
4798
  claimId: z.uuid().optional()
4657
- }).strict(), evidenceSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/evidence", "write", "Attach evidence with its commit and provenance."),
4799
+ }).strict(), evidenceSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/evidence", "write", "Attach evidence with its commit and provenance.", { mcp: "core" }),
4658
4800
  list_time_entries: op(ticketInput.extend(pagination), page(timeEntrySchema), "GET", "/projects/{projectId}/tickets/{ticketId}/time-entries", "read", "List observed time entries, newest first. Running entries have null endAt and durationMs."),
4659
4801
  get_time_entry: op(ticketInput.extend({ timeEntryId: z.uuid() }), timeEntrySchema, "GET", "/projects/{projectId}/tickets/{ticketId}/time-entries/{timeEntryId}", "read", "Read one attributed time entry within its current ticket and project."),
4660
4802
  create_time_entry: op(ticketInput.extend({
@@ -4700,18 +4842,18 @@ const operations = {
4700
4842
  claim_ticket: op(ticketInput.extend({
4701
4843
  ...mutation,
4702
4844
  workerId: text.max(200),
4703
- expectedVersion: version,
4845
+ expectedVersion: version.optional(),
4704
4846
  leaseSeconds: claimLeaseSecondsSchema.optional()
4705
- }).strict(), claimSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/claim", "claim", "Atomically claim ready work. Expired claims require explicit recovery."),
4847
+ }).strict(), claimSchema.extend({ ticket: ticketSchema }), "POST", "/projects/{projectId}/tickets/{ticketId}/claim", "claim", "Atomically claim ready work and return the claim with the claimed ticket. expectedVersion is optional; readiness always applies. Expired claims require explicit recovery.", { mcp: "core" }),
4706
4848
  renew_claim: op(ticketInput.extend({
4707
4849
  ...mutation,
4708
4850
  claimId: z.uuid(),
4709
4851
  leaseSeconds: claimLeaseSecondsSchema.optional()
4710
- }).strict(), claimSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/claim/renew", "claim", "Renew the caller's unexpired claim."),
4852
+ }).strict(), claimSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/claim/renew", "claim", "Renew the caller's unexpired claim.", { mcp: "core" }),
4711
4853
  release_claim: op(ticketInput.extend({
4712
4854
  ...mutation,
4713
4855
  claimId: z.uuid()
4714
- }).strict(), okSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/claim/release", "claim", "Release the caller's claim."),
4856
+ }).strict(), okSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/claim/release", "claim", "Release the caller's claim.", { mcp: "core" }),
4715
4857
  recover_claim: op(ticketInput.extend({
4716
4858
  ...mutation,
4717
4859
  claimId: z.uuid().optional(),
@@ -4999,4 +5141,4 @@ function parseOutput(name, value) {
4999
5141
  return operations[name].output.parse(value);
5000
5142
  }
5001
5143
  //#endregion
5002
- export { permissionLabels as $, hasAdminRole as A, workflowOrder as At, memberSchema as B, searchSettingsSchema as Bt, errorSchema as C, streamErrorSchema as Ct, filterKey as D, ticketPredicates as Dt, eventSchema as E, ticketImportSchema as Et, isHexColor as F, instanceUpdateSchema as Ft, notificationReadInput as G, notificationIdsInput as H, isOperation as I, photoInputSchema as It, operationPermission as J, notificationsSchema as K, isPresetColor as L, photoResultSchema as Lt, importProviderDefinitions as M, adminInstanceSchema as Mt, importSecretFields as N, authenticationPolicySchema as Nt, filterList as O, ticketSchema as Ot, invitationStatuses as P, brokerSettingsSchema as Pt, parsePublicOutput as Q, isPublicOperation as R, s3SettingsSchema as Rt, difficulties as S, states as St, eventLabels as T, ticketFilter as Tt, notificationPreferencesInput as U, mentionScheme as V, notificationPreferencesSchema as W, parseCustomFieldFilter as X, operations as Y, parseOutput as Z, deletedAccountName as _, seededPermissions as _t, checkpointSchema as a, publicOperations as at, destinationEventKeys as b, stagedUploadLifetime as bt, credentialInput as c, repositoryProviderDefinitions as ct, customFieldSchema as d, resourceProvider as dt, permissionScope as et, customFieldValue as f, roleCategory as ft, defaultWorkflow as g, searchResultTypes as gt, defaultOrder as h, scopes as ht, channelRouteAllows as i, projectSchema as it, importLimits as j, workspaceSchema as jt, formatEvent as k, ticketSummarySchema as kt, credentialProjectsSchema as l, repositoryProviders as lt, defaultClaimMaxLeaseSeconds as m, roles as mt, attachmentLimit as n, priorities as nt, claimLeaseSecondsSchema as o, pushDeviceInput as ot, customFieldValueSchema as p, roleLabels as pt, okSchema as q, channelKinds as r, priorityLabels as rt, closedStates as s, remoteKinds as st, ApiError as t, permissions as tt, customFieldFilterTokens as u, repositorySecretFields as ut, deliverySecretFields as v, signInMethodLabels as vt, eventCategories as w, ticketExportFormat as wt, destinationKinds as x, stateLabels as xt, deliverySettingsSchema as y, snapshotSchema as yt, isSeededRole as z, searchAuthentication as zt };
5144
+ export { parseCustomFieldFilter as $, filterList as A, ticketImportSchema as At, isPublicOperation as B, instanceUpdateSchema as Bt, destinationKinds as C, stagedUploadLifetime as Ct, eventLabels as D, streamErrorSchema as Dt, eventCategories as E, states as Et, importSecretFields as F, workflowOrder as Ft, notificationIdsInput as G, searchSettingsSchema as Gt, memberSchema as H, photoResultSchema as Ht, invitationStatuses as I, workspaceSchema as It, notificationReadInput as J, notificationPreferencesInput as K, isHexColor as L, adminInstanceSchema as Lt, hasAdminRole as M, ticketSchema as Mt, importLimits as N, ticketSummarySchema as Nt, eventSchema as O, ticketExportFormat as Ot, importProviderDefinitions as P, uploadUrlLifetime as Pt, operations as Q, isOperation as R, authenticationPolicySchema as Rt, destinationEventKeys as S, snapshotSchema as St, errorSchema as T, stateLabels as Tt, mentionScheme as U, s3SettingsSchema as Ut, isSeededRole as V, photoInputSchema as Vt, normalizeRemote as W, searchAuthentication as Wt, okSchema as X, notificationsSchema as Y, operationPermission as Z, defaultOrder as _, roles as _t, channelRouteAllows as a, priorities as at, deliverySecretFields as b, seededPermissions as bt, claimSchema as c, publicOperations as ct, credentialProjectsSchema as d, repositoryProviderDefinitions as dt, parseOutput as et, customFieldFilterTokens as f, repositoryProviders as ft, defaultClaimMaxLeaseSeconds as g, roleLabels as gt, customFieldValueSchema as h, roleCategory as ht, channelKinds as i, permissions as it, formatEvent as j, ticketPredicates as jt, filterKey as k, ticketFilter as kt, closedStates as l, pushDeviceInput as lt, customFieldValue as m, resourceProvider as mt, attachmentLimit as n, permissionLabels as nt, checkpointSchema as o, priorityLabels as ot, customFieldSchema as p, repositorySecretFields as pt, notificationPreferencesSchema as q, attachmentSchema as r, permissionScope as rt, claimLeaseSecondsSchema as s, projectSchema as st, ApiError as t, parsePublicOutput as tt, credentialInput as u, remoteKinds as ut, defaultWorkflow as v, scopes as vt, difficulties as w, stagedUploadSchema as wt, deliverySettingsSchema as x, signInMethodLabels as xt, deletedAccountName as y, searchResultTypes as yt, isPresetColor as z, brokerSettingsSchema as zt };
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "tickets" ADD COLUMN "intake_credential_id" text;--> statement-breakpoint
2
+ CREATE INDEX "ticket_intake_credential" ON "tickets" USING btree ("intake_credential_id") WHERE "tickets"."intake_credential_id" IS NOT NULL;
@@ -0,0 +1,20 @@
1
+ CREATE TABLE "upload_urls" (
2
+ "id" uuid PRIMARY KEY NOT NULL,
3
+ "project_id" uuid NOT NULL,
4
+ "ticket_id" uuid,
5
+ "actor_id" text NOT NULL,
6
+ "credential" jsonb,
7
+ "name" text NOT NULL,
8
+ "content_type" text NOT NULL,
9
+ "size" integer NOT NULL,
10
+ "token_hash" text NOT NULL,
11
+ "expires_at" timestamp with time zone NOT NULL,
12
+ "used_at" timestamp with time zone,
13
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
14
+ CONSTRAINT "upload_urls_token_hash_unique" UNIQUE("token_hash")
15
+ );
16
+ --> statement-breakpoint
17
+ ALTER TABLE "upload_urls" ADD CONSTRAINT "upload_urls_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
18
+ ALTER TABLE "upload_urls" ADD CONSTRAINT "upload_urls_ticket_id_tickets_id_fk" FOREIGN KEY ("ticket_id") REFERENCES "public"."tickets"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
19
+ ALTER TABLE "upload_urls" ADD CONSTRAINT "upload_urls_actor_id_user_id_fk" FOREIGN KEY ("actor_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
20
+ CREATE INDEX "upload_urls_expires" ON "upload_urls" USING btree ("expires_at");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "projects" ADD COLUMN "repositories" text[] DEFAULT '{}' NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "mutation_receipts" ADD COLUMN "project_id" uuid;