@opengeni/contracts 0.50.0 → 1.0.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 (369) hide show
  1. package/dist/agent-authored-durable-text.d.ts +70 -0
  2. package/dist/agent-config.d.ts +869 -0
  3. package/dist/agent-instruction-changes.d.ts +110 -0
  4. package/dist/agent-learning.d.ts +243 -0
  5. package/dist/agent-topology.d.ts +292 -0
  6. package/dist/allowance-refusal.d.ts +9 -0
  7. package/dist/allowance-refusal.js +50 -0
  8. package/dist/allowance-refusal.js.map +1 -0
  9. package/dist/analytics-consent-report.d.ts +19 -0
  10. package/dist/analytics-consent-report.js +10 -0
  11. package/dist/analytics-consent-report.js.map +1 -0
  12. package/dist/api-key-presets.d.ts +19 -0
  13. package/dist/artifact-catalog.d.ts +161 -0
  14. package/dist/artifacts.d.ts +135 -11
  15. package/dist/atlassian-native-retirement.d.ts +16 -0
  16. package/dist/atlassian-native-retirement.js +30 -0
  17. package/dist/atlassian-native-retirement.js.map +1 -0
  18. package/dist/atlassian.d.ts +2 -0
  19. package/dist/atlassian.js +26 -12
  20. package/dist/browser-storage.d.ts +5 -0
  21. package/dist/browser-storage.js +9 -0
  22. package/dist/browser-storage.js.map +1 -0
  23. package/dist/bundled-skills.d.ts +40 -0
  24. package/dist/chunk-2ACYHZFB.js +292 -0
  25. package/dist/chunk-2ACYHZFB.js.map +1 -0
  26. package/dist/chunk-2VORLN2R.js +353 -0
  27. package/dist/chunk-2VORLN2R.js.map +1 -0
  28. package/dist/{chunk-Y3MLSLB4.js → chunk-3SIZGL3O.js} +42 -30
  29. package/dist/chunk-3SIZGL3O.js.map +1 -0
  30. package/dist/chunk-46KLD2UH.js +186 -0
  31. package/dist/chunk-46KLD2UH.js.map +1 -0
  32. package/dist/chunk-4JGHSSB7.js +11 -0
  33. package/dist/chunk-4JGHSSB7.js.map +1 -0
  34. package/dist/{chunk-M5ZGRVIQ.js → chunk-5IXYF6XN.js} +14 -5
  35. package/dist/chunk-5IXYF6XN.js.map +1 -0
  36. package/dist/chunk-BCS7WHCK.js +139 -0
  37. package/dist/chunk-BCS7WHCK.js.map +1 -0
  38. package/dist/chunk-EK7NDGFR.js +128 -0
  39. package/dist/chunk-EK7NDGFR.js.map +1 -0
  40. package/dist/{chunk-5UDNP7AO.js → chunk-FZ6BXQHL.js} +78 -38
  41. package/dist/chunk-FZ6BXQHL.js.map +1 -0
  42. package/dist/{chunk-CM6BMECR.js → chunk-GRG7PHWQ.js} +2 -1
  43. package/dist/chunk-GRG7PHWQ.js.map +1 -0
  44. package/dist/chunk-KHHZTBP7.js +11 -0
  45. package/dist/chunk-KHHZTBP7.js.map +1 -0
  46. package/dist/chunk-KR2V42UZ.js +187 -0
  47. package/dist/chunk-KR2V42UZ.js.map +1 -0
  48. package/dist/chunk-MZLBPKFE.js +168 -0
  49. package/dist/chunk-MZLBPKFE.js.map +1 -0
  50. package/dist/{chunk-LW7OH6CS.js → chunk-NRMCVHAU.js} +6 -5
  51. package/dist/chunk-NRMCVHAU.js.map +1 -0
  52. package/dist/{chunk-TZ6YEYN4.js → chunk-NVJMJWLL.js} +3 -1
  53. package/dist/chunk-NVJMJWLL.js.map +1 -0
  54. package/dist/chunk-O77VSFYZ.js +70 -0
  55. package/dist/chunk-O77VSFYZ.js.map +1 -0
  56. package/dist/chunk-PX3VCKAU.js +29 -0
  57. package/dist/chunk-PX3VCKAU.js.map +1 -0
  58. package/dist/chunk-QR5D2IQC.js +61 -0
  59. package/dist/chunk-QR5D2IQC.js.map +1 -0
  60. package/dist/chunk-RJ76DRPO.js +117 -0
  61. package/dist/chunk-RJ76DRPO.js.map +1 -0
  62. package/dist/chunk-RKX3NQYS.js +28 -0
  63. package/dist/chunk-RKX3NQYS.js.map +1 -0
  64. package/dist/{chunk-JBCIY7QD.js → chunk-SIOU2K4U.js} +45 -22
  65. package/dist/chunk-SIOU2K4U.js.map +1 -0
  66. package/dist/chunk-TSCDAGET.js +75 -0
  67. package/dist/chunk-TSCDAGET.js.map +1 -0
  68. package/dist/{chunk-LSB7GRLG.js → chunk-TXTQIYCV.js} +15 -11
  69. package/dist/chunk-TXTQIYCV.js.map +1 -0
  70. package/dist/chunk-X7ETVO4P.js +26544 -0
  71. package/dist/chunk-X7ETVO4P.js.map +1 -0
  72. package/dist/{chunk-CADSX6UN.js → chunk-Y3KNXVTD.js} +2 -2
  73. package/dist/chunk-YBW5JSA3.js +251 -0
  74. package/dist/chunk-YBW5JSA3.js.map +1 -0
  75. package/dist/chunk-YRXAWWCU.js +45 -0
  76. package/dist/chunk-YRXAWWCU.js.map +1 -0
  77. package/dist/claude-provider-account-authority.d.ts +18 -0
  78. package/dist/claude-subscription-oauth.d.ts +42 -0
  79. package/dist/claude-subscription-usage.d.ts +159 -0
  80. package/dist/client-error-report.d.ts +109 -0
  81. package/dist/client-error-report.js +87 -0
  82. package/dist/client-error-report.js.map +1 -0
  83. package/dist/code-search.d.ts +52 -0
  84. package/dist/code-search.js +40 -0
  85. package/dist/code-search.js.map +1 -0
  86. package/dist/company-brain-governed-writes.d.ts +475 -0
  87. package/dist/company-brain.d.ts +336 -0
  88. package/dist/company-profile.d.ts +566 -0
  89. package/dist/connect.d.ts +325 -0
  90. package/dist/connect.js +191 -0
  91. package/dist/connect.js.map +1 -0
  92. package/dist/connection-account-label.d.ts +2 -0
  93. package/dist/connection-account-label.js +35 -0
  94. package/dist/connection-account-label.js.map +1 -0
  95. package/dist/connection-authority.d.ts +193 -0
  96. package/dist/connection-authority.js +50 -0
  97. package/dist/connection-authority.js.map +1 -0
  98. package/dist/connector-attachments.d.ts +95 -0
  99. package/dist/connector-attachments.js +51 -0
  100. package/dist/connector-attachments.js.map +1 -0
  101. package/dist/connector-tool-permissions.d.ts +73 -0
  102. package/dist/direct-model-provider.d.ts +36 -0
  103. package/dist/editable-artifact-codec-registry.d.ts +16 -7
  104. package/dist/editable-artifact-codec-registry.js +18 -8
  105. package/dist/editable-artifact-committed-transaction.d.ts +2 -2
  106. package/dist/editable-artifact-committed-transaction.js +2 -2
  107. package/dist/editable-artifact-live.d.ts +11 -12
  108. package/dist/editable-artifact-live.js +110 -45
  109. package/dist/editable-artifact-live.js.map +1 -1
  110. package/dist/editable-artifact-serialized-commit.d.ts +2 -1
  111. package/dist/editable-artifact-serialized-commit.js +8 -7
  112. package/dist/editable-artifact-versions.d.ts +20 -5
  113. package/dist/editable-artifact-versions.js +23 -5
  114. package/dist/editable-artifacts.d.ts +2 -0
  115. package/dist/editable-artifacts.js +47 -35
  116. package/dist/external-identities.d.ts +784 -0
  117. package/dist/external-identities.js +44 -0
  118. package/dist/external-identities.js.map +1 -0
  119. package/dist/feedback.d.ts +51 -0
  120. package/dist/github-repository-contracts.d.ts +36 -0
  121. package/dist/github-repository-contracts.js +59 -0
  122. package/dist/github-repository-contracts.js.map +1 -0
  123. package/dist/github-repository.d.ts +14 -0
  124. package/dist/github-repository.js +36 -0
  125. package/dist/github-repository.js.map +1 -0
  126. package/dist/google-drive.d.ts +90 -1
  127. package/dist/google-drive.js +90 -16
  128. package/dist/google-drive.js.map +1 -1
  129. package/dist/governed-learning-activation.d.ts +154 -0
  130. package/dist/governed-learning-evaluator.d.ts +152 -0
  131. package/dist/host-mcp-bindings.d.ts +326 -0
  132. package/dist/host-mcp-bindings.js +252 -0
  133. package/dist/host-mcp-bindings.js.map +1 -0
  134. package/dist/image-generation.d.ts +1 -0
  135. package/dist/index.d.ts +32396 -11386
  136. package/dist/index.js +2198 -164
  137. package/dist/insights-usage.d.ts +877 -0
  138. package/dist/insights-usage.js +509 -0
  139. package/dist/insights-usage.js.map +1 -0
  140. package/dist/interaction.d.ts +344 -0
  141. package/dist/knowledge-entries.d.ts +982 -0
  142. package/dist/knowledge-preparation.d.ts +237 -0
  143. package/dist/knowledge.d.ts +197 -0
  144. package/dist/managed-auth-session-sets.d.ts +241 -0
  145. package/dist/managed-auth-session-sets.js +191 -0
  146. package/dist/managed-auth-session-sets.js.map +1 -0
  147. package/dist/managed-sign-in-methods.d.ts +56 -0
  148. package/dist/managed-sign-in-methods.js +46 -0
  149. package/dist/managed-sign-in-methods.js.map +1 -0
  150. package/dist/mcp-catalog-limits.d.ts +2 -0
  151. package/dist/mcp-endpoint.d.ts +7 -0
  152. package/dist/mcp-endpoint.js +9 -0
  153. package/dist/mcp-endpoint.js.map +1 -0
  154. package/dist/mcp-oauth.d.ts +71 -0
  155. package/dist/modal-native-proof-v2.d.ts +587 -0
  156. package/dist/modal-native-proof-v2.js +37 -0
  157. package/dist/modal-native-proof-v2.js.map +1 -0
  158. package/dist/model-availability.d.ts +15 -0
  159. package/dist/model-connection-access.d.ts +24 -0
  160. package/dist/model-context-inspector.d.ts +329 -0
  161. package/dist/model-display.d.ts +38 -0
  162. package/dist/model-display.js +134 -0
  163. package/dist/model-display.js.map +1 -0
  164. package/dist/model-picker-order.d.ts +25 -0
  165. package/dist/model-picker-order.js +42 -0
  166. package/dist/model-picker-order.js.map +1 -0
  167. package/dist/organization-access.d.ts +231 -0
  168. package/dist/organization-access.js +34 -0
  169. package/dist/organization-access.js.map +1 -0
  170. package/dist/organization-integration-policy.d.ts +27 -0
  171. package/dist/organization-membership-lifecycle.d.ts +1022 -0
  172. package/dist/organization-model-usage.d.ts +146 -0
  173. package/dist/organization-model-usage.js +67 -0
  174. package/dist/organization-model-usage.js.map +1 -0
  175. package/dist/organization-recovery.d.ts +337 -0
  176. package/dist/organization-recovery.js +37 -0
  177. package/dist/organization-recovery.js.map +1 -0
  178. package/dist/organization-usage.d.ts +138 -0
  179. package/dist/permissions.d.ts +54 -0
  180. package/dist/personal-github.d.ts +320 -0
  181. package/dist/personal-github.js +222 -0
  182. package/dist/personal-github.js.map +1 -0
  183. package/dist/plugin-discovery.d.ts +35 -0
  184. package/dist/plugin-discovery.js +7 -0
  185. package/dist/plugin-discovery.js.map +1 -0
  186. package/dist/preference-registry.d.ts +44 -1
  187. package/dist/product-analytics.d.ts +113 -0
  188. package/dist/product-lifecycle-facts.d.ts +73 -0
  189. package/dist/remember.d.ts +350 -0
  190. package/dist/retained-output.d.ts +8 -0
  191. package/dist/sandbox-file-artifacts.d.ts +57 -0
  192. package/dist/sandbox-provider-command.d.ts +113 -0
  193. package/dist/sandbox-recovery.d.ts +146 -0
  194. package/dist/sandbox-snapshots.d.ts +39 -0
  195. package/dist/session-final-reply.d.ts +6 -0
  196. package/dist/session-final-reply.js +9 -0
  197. package/dist/session-final-reply.js.map +1 -0
  198. package/dist/session-goal-reports.d.ts +21 -0
  199. package/dist/session-history-import.d.ts +947 -0
  200. package/dist/session-list-entries.d.ts +4 -0
  201. package/dist/session-list-entries.js +51 -0
  202. package/dist/session-list-entries.js.map +1 -0
  203. package/dist/session-mcp-projections.d.ts +215 -0
  204. package/dist/session-message-search.d.ts +68 -0
  205. package/dist/session-titles.d.ts +68 -0
  206. package/dist/session-titles.js +25 -0
  207. package/dist/session-titles.js.map +1 -0
  208. package/dist/session-topology-primitives.d.ts +22 -0
  209. package/dist/signup-attribution.d.ts +39 -0
  210. package/dist/site-request-headers.test.d.ts +1 -0
  211. package/dist/site-session-http.d.ts +11 -0
  212. package/dist/site-session-http.js +11 -0
  213. package/dist/site-session-http.js.map +1 -0
  214. package/dist/skill-catalog-context.d.ts +7 -0
  215. package/dist/skill-files.d.ts +12 -0
  216. package/dist/skill-metadata.d.ts +9 -0
  217. package/dist/skill-use.d.ts +61 -0
  218. package/dist/skills.d.ts +185 -0
  219. package/dist/slack-bot-scopes.d.ts +46 -21
  220. package/dist/slack-bot-scopes.js +14 -3
  221. package/dist/slack-rest-mcp.d.ts +31 -0
  222. package/dist/slack-rest-mcp.js +19 -0
  223. package/dist/slack-rest-mcp.js.map +1 -0
  224. package/dist/spreadsheet-artifact-commands.d.ts +2 -3
  225. package/dist/spreadsheet-artifact-commands.js +4 -2
  226. package/dist/spreadsheet-artifact-query.js +3 -2
  227. package/dist/subscription-account-pools.d.ts +292 -0
  228. package/dist/task-notes.d.ts +42 -1
  229. package/dist/tool-catalog.d.ts +286 -0
  230. package/dist/tool-result-spill.d.ts +16 -0
  231. package/dist/usage-allowances.d.ts +285 -0
  232. package/dist/usage-allowances.js +49 -0
  233. package/dist/usage-allowances.js.map +1 -0
  234. package/dist/video-generation.d.ts +3 -0
  235. package/dist/video-generation.js +1 -1
  236. package/dist/work-claims.d.ts +411 -0
  237. package/dist/workspace-instruction-policies.d.ts +94 -0
  238. package/dist/workspace-integration-wire.d.ts +36 -0
  239. package/dist/workspace-integration-wire.js +23 -0
  240. package/dist/workspace-integration-wire.js.map +1 -0
  241. package/dist/workspace-integrations.d.ts +948 -0
  242. package/dist/workspace-learning-administration.d.ts +289 -0
  243. package/dist/workspace-learning-policy.d.ts +1 -1
  244. package/dist/workspace-state.d.ts +85 -416
  245. package/dist/xai-provider-account-authority.d.ts +3 -0
  246. package/dist/xai-provider-account-authority.js +1 -1
  247. package/package.json +134 -1
  248. package/src/agent-authored-durable-text.ts +116 -0
  249. package/src/agent-config.ts +1527 -0
  250. package/src/agent-instruction-changes.ts +98 -0
  251. package/src/agent-learning.ts +161 -0
  252. package/src/agent-topology.ts +69 -0
  253. package/src/allowance-refusal.ts +81 -0
  254. package/src/analytics-consent-report.ts +20 -0
  255. package/src/api-key-presets.ts +25 -0
  256. package/src/artifact-catalog.ts +60 -0
  257. package/src/artifacts.ts +146 -18
  258. package/src/atlassian-native-retirement.ts +33 -0
  259. package/src/browser-storage.ts +10 -0
  260. package/src/bundled-skills.ts +73 -0
  261. package/src/claude-provider-account-authority.ts +12 -0
  262. package/src/claude-subscription-oauth.ts +62 -0
  263. package/src/claude-subscription-usage.ts +59 -0
  264. package/src/client-error-report.ts +184 -0
  265. package/src/code-search.ts +105 -0
  266. package/src/company-brain-governed-writes.ts +356 -0
  267. package/src/company-brain.ts +201 -0
  268. package/src/company-profile.ts +167 -1
  269. package/src/connect.ts +202 -0
  270. package/src/connection-account-label.ts +46 -0
  271. package/src/connection-authority.ts +213 -0
  272. package/src/connector-attachments.ts +327 -0
  273. package/src/connector-tool-permissions.ts +60 -0
  274. package/src/direct-model-provider.ts +98 -0
  275. package/src/editable-artifact-codec-registry.ts +55 -17
  276. package/src/editable-artifact-committed-transaction.ts +44 -31
  277. package/src/editable-artifact-live.ts +123 -57
  278. package/src/editable-artifact-serialized-commit.ts +2 -1
  279. package/src/editable-artifact-versions.ts +26 -5
  280. package/src/editable-artifacts.ts +2 -0
  281. package/src/external-identities.ts +285 -0
  282. package/src/feedback.ts +39 -0
  283. package/src/github-repository-contracts.ts +85 -0
  284. package/src/github-repository.ts +59 -0
  285. package/src/google-drive.ts +76 -4
  286. package/src/governed-learning-activation.ts +191 -0
  287. package/src/governed-learning-evaluator.ts +176 -0
  288. package/src/host-mcp-bindings.ts +298 -0
  289. package/src/image-generation.ts +8 -2
  290. package/src/index.ts +7093 -1466
  291. package/src/insights-usage.ts +679 -0
  292. package/src/interaction.ts +220 -5
  293. package/src/knowledge-entries.ts +375 -0
  294. package/src/knowledge-preparation.ts +50 -0
  295. package/src/knowledge.ts +134 -6
  296. package/src/managed-auth-session-sets.ts +253 -0
  297. package/src/managed-sign-in-methods.ts +37 -0
  298. package/src/mcp-catalog-limits.ts +2 -0
  299. package/src/mcp-endpoint.ts +30 -0
  300. package/src/mcp-oauth.ts +66 -0
  301. package/src/modal-native-proof-v2.ts +398 -0
  302. package/src/model-availability.ts +22 -0
  303. package/src/model-connection-access.ts +17 -0
  304. package/src/model-context-inspector.ts +139 -0
  305. package/src/model-display.ts +195 -0
  306. package/src/model-picker-order.ts +97 -0
  307. package/src/organization-access.ts +176 -0
  308. package/src/organization-integration-policy.ts +54 -0
  309. package/src/organization-membership-lifecycle.ts +559 -0
  310. package/src/organization-model-usage.ts +72 -0
  311. package/src/organization-recovery.ts +186 -0
  312. package/src/organization-usage.ts +79 -0
  313. package/src/permissions.ts +58 -0
  314. package/src/personal-github.ts +267 -0
  315. package/src/plugin-discovery.ts +33 -0
  316. package/src/preference-registry.ts +20 -1
  317. package/src/product-analytics.ts +253 -0
  318. package/src/product-lifecycle-facts.ts +121 -0
  319. package/src/remember.ts +243 -0
  320. package/src/retained-output.ts +20 -3
  321. package/src/sandbox-file-artifacts.ts +73 -0
  322. package/src/sandbox-provider-command.ts +82 -0
  323. package/src/sandbox-recovery.ts +116 -0
  324. package/src/sandbox-snapshots.ts +142 -0
  325. package/src/session-final-reply.ts +16 -0
  326. package/src/session-goal-reports.ts +55 -0
  327. package/src/session-history-import.ts +159 -0
  328. package/src/session-list-entries.ts +91 -0
  329. package/src/session-mcp-projections.ts +273 -0
  330. package/src/session-message-search.ts +54 -0
  331. package/src/session-titles.ts +467 -0
  332. package/src/session-topology-primitives.ts +21 -0
  333. package/src/signup-attribution.ts +81 -0
  334. package/src/site-request-headers.test.ts +28 -0
  335. package/src/site-session-http.ts +63 -0
  336. package/src/skill-catalog-context.ts +50 -0
  337. package/src/skill-files.ts +52 -0
  338. package/src/skill-metadata.ts +40 -0
  339. package/src/skill-use.ts +77 -0
  340. package/src/skills.ts +136 -0
  341. package/src/slack-bot-scopes.ts +106 -42
  342. package/src/slack-rest-mcp.ts +194 -0
  343. package/src/spreadsheet-artifact-commands.ts +12 -13
  344. package/src/subscription-account-pools.ts +44 -0
  345. package/src/task-notes.ts +14 -1
  346. package/src/tool-catalog.ts +155 -0
  347. package/src/tool-result-spill.ts +35 -0
  348. package/src/usage-allowances.ts +187 -0
  349. package/src/work-claims.ts +266 -0
  350. package/src/workspace-instruction-policies.ts +31 -0
  351. package/src/workspace-integration-wire.ts +99 -0
  352. package/src/workspace-integrations.ts +640 -0
  353. package/src/workspace-learning-administration.ts +88 -0
  354. package/src/workspace-learning-policy.ts +4 -3
  355. package/src/workspace-state.ts +16 -126
  356. package/src/xai-provider-account-authority.ts +1 -0
  357. package/dist/chunk-5UDNP7AO.js.map +0 -1
  358. package/dist/chunk-BVGIYW7D.js +0 -11
  359. package/dist/chunk-BVGIYW7D.js.map +0 -1
  360. package/dist/chunk-CM6BMECR.js.map +0 -1
  361. package/dist/chunk-JBCIY7QD.js.map +0 -1
  362. package/dist/chunk-LSB7GRLG.js.map +0 -1
  363. package/dist/chunk-LW7OH6CS.js.map +0 -1
  364. package/dist/chunk-M5ZGRVIQ.js.map +0 -1
  365. package/dist/chunk-Q6A7XT2N.js +0 -16734
  366. package/dist/chunk-Q6A7XT2N.js.map +0 -1
  367. package/dist/chunk-TZ6YEYN4.js.map +0 -1
  368. package/dist/chunk-Y3MLSLB4.js.map +0 -1
  369. /package/dist/{chunk-CADSX6UN.js.map → chunk-Y3KNXVTD.js.map} +0 -0
@@ -0,0 +1,327 @@
1
+ import { z } from "zod";
2
+
3
+ export const CONNECTOR_ATTACHMENT_TRANSFER_VERSION = 1 as const;
4
+ export const CONNECTOR_ATTACHMENT_RECEIPT_VERSION = 1 as const;
5
+ export const CONNECTOR_ATTACHMENT_TRANSFER_META_KEY =
6
+ "opengeni/connector-attachment-transfers" as const;
7
+ export const CONNECTOR_ATTACHMENT_RECEIPT_META_KEY =
8
+ "opengeni/connector-attachment-receipts" as const;
9
+ export const CONNECTOR_ATTACHMENT_MAX_COUNT = 16;
10
+ // Must remain byte-for-byte aligned with Channel A's exact workspace importer.
11
+ export const CONNECTOR_ATTACHMENT_MAX_BYTES = 5_000_000_000;
12
+ export const CONNECTOR_ATTACHMENT_FILENAME_MAX_UTF8_BYTES = 255;
13
+ export const CONNECTOR_ATTACHMENT_MEDIA_TYPE_MAX_UTF8_BYTES = 256;
14
+ export const CONNECTOR_ATTACHMENT_PROVIDER_MAX_UTF8_BYTES = 128;
15
+ export const CONNECTOR_ATTACHMENT_PROVIDER_ID_MAX_UTF8_BYTES = 512;
16
+ export const CONNECTOR_ATTACHMENT_SOURCE_URL_MAX_UTF8_BYTES = 8 * 1024;
17
+ export const CONNECTOR_ATTACHMENT_SANDBOX_PATH_MAX_UTF8_BYTES = 2 * 1024;
18
+
19
+ const PROVIDER_PATTERN = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u;
20
+ const SHA256_PATTERN = /^[0-9a-f]{64}$/u;
21
+ const MEDIA_TYPE_PATTERN =
22
+ /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+(?:\s*;\s*[a-z0-9!#$&^_.+-]+=(?:[a-z0-9!#$&^_.+-]+|"[^"\r\n]*"))*$/iu;
23
+ const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
24
+ const HTTP_URL_REFERENCE_PATTERN = /(?:https?:)?\/\/[^\s]/iu;
25
+ const PORTABLE_FILENAME_FORBIDDEN_PATTERN = /[<>:"|?*]/u;
26
+ const PORTABLE_FILENAME_RESERVED_PATTERN = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu;
27
+ const textEncoder = new TextEncoder();
28
+
29
+ function utf8Bytes(value: string): number {
30
+ return textEncoder.encode(value).byteLength;
31
+ }
32
+
33
+ function boundedString(maxUtf8Bytes: number) {
34
+ return z.string().refine((value) => utf8Bytes(value) <= maxUtf8Bytes, {
35
+ message: `must be at most ${maxUtf8Bytes} UTF-8 bytes`,
36
+ });
37
+ }
38
+
39
+ function isHttpUrl(value: string): boolean {
40
+ try {
41
+ const parsed = new URL(value);
42
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ function containsHttpUrlReference(value: string): boolean {
49
+ return HTTP_URL_REFERENCE_PATTERN.test(value);
50
+ }
51
+
52
+ function isPrivateUrlCredentialQueryName(value: string): boolean {
53
+ const normalized = value.toLowerCase().replace(/[^a-z0-9]/gu, "");
54
+ return (
55
+ normalized === "sig" ||
56
+ normalized === "auth" ||
57
+ normalized.endsWith("signature") ||
58
+ normalized.endsWith("token") ||
59
+ normalized.endsWith("credential") ||
60
+ normalized.endsWith("secret") ||
61
+ normalized.endsWith("password") ||
62
+ normalized.endsWith("passcode") ||
63
+ normalized.endsWith("authorization") ||
64
+ normalized.endsWith("apikey") ||
65
+ normalized.endsWith("accesskey") ||
66
+ normalized.endsWith("securitytoken") ||
67
+ normalized.endsWith("sas") ||
68
+ normalized === "googleaccessid"
69
+ );
70
+ }
71
+
72
+ function privateUrlCredentialValues(value: string): string[] {
73
+ let parsed: URL;
74
+ try {
75
+ parsed = new URL(value);
76
+ } catch {
77
+ return [];
78
+ }
79
+ const credentials = new Set<string>();
80
+ for (const [name, credential] of parsed.searchParams) {
81
+ if (credential && isPrivateUrlCredentialQueryName(name)) credentials.add(credential);
82
+ }
83
+ for (const pair of parsed.search.slice(1).split("&")) {
84
+ if (!pair) continue;
85
+ const separator = pair.indexOf("=");
86
+ const rawName = separator === -1 ? pair : pair.slice(0, separator);
87
+ const rawCredential = separator === -1 ? "" : pair.slice(separator + 1);
88
+ let decodedName: string;
89
+ try {
90
+ decodedName = decodeURIComponent(rawName.replace(/\+/gu, " "));
91
+ } catch {
92
+ continue;
93
+ }
94
+ if (rawCredential && isPrivateUrlCredentialQueryName(decodedName)) {
95
+ credentials.add(rawCredential);
96
+ }
97
+ }
98
+ return [...credentials];
99
+ }
100
+
101
+ function publicMetadataContainsCredential(publicValue: string, credential: string): boolean {
102
+ return publicValue.includes(credential);
103
+ }
104
+
105
+ export const ConnectorAttachmentProviderIdentity = z
106
+ .object({
107
+ provider: boundedString(CONNECTOR_ATTACHMENT_PROVIDER_MAX_UTF8_BYTES).regex(PROVIDER_PATTERN),
108
+ kind: z.literal("attachment"),
109
+ value: boundedString(CONNECTOR_ATTACHMENT_PROVIDER_ID_MAX_UTF8_BYTES)
110
+ .min(1)
111
+ .refine((value) => !CONTROL_CHARACTER_PATTERN.test(value), {
112
+ message: "must not contain control characters",
113
+ })
114
+ .refine((value) => !isHttpUrl(value) && !containsHttpUrlReference(value), {
115
+ message: "must be an opaque provider attachment identity, not a URL",
116
+ }),
117
+ })
118
+ .strict();
119
+ export type ConnectorAttachmentProviderIdentity = z.infer<
120
+ typeof ConnectorAttachmentProviderIdentity
121
+ >;
122
+
123
+ export const ConnectorAttachmentFileName = boundedString(
124
+ CONNECTOR_ATTACHMENT_FILENAME_MAX_UTF8_BYTES,
125
+ )
126
+ .min(1)
127
+ .refine(
128
+ (value) =>
129
+ value !== "." &&
130
+ value !== ".." &&
131
+ value === value.trim() &&
132
+ !value.includes("/") &&
133
+ !value.includes("\\") &&
134
+ !CONTROL_CHARACTER_PATTERN.test(value) &&
135
+ !PORTABLE_FILENAME_FORBIDDEN_PATTERN.test(value) &&
136
+ !/[ .]$/u.test(value) &&
137
+ !PORTABLE_FILENAME_RESERVED_PATTERN.test(value),
138
+ { message: "must be a safe leaf filename" },
139
+ );
140
+
141
+ export const ConnectorAttachmentMediaType = boundedString(
142
+ CONNECTOR_ATTACHMENT_MEDIA_TYPE_MAX_UTF8_BYTES,
143
+ )
144
+ .regex(MEDIA_TYPE_PATTERN)
145
+ .refine((value) => !containsHttpUrlReference(value), {
146
+ message: "must not contain an HTTP URL reference",
147
+ });
148
+
149
+ export const ConnectorAttachmentSha256 = z.string().regex(SHA256_PATTERN);
150
+
151
+ export const ConnectorAttachmentPrivateSource = z
152
+ .object({
153
+ url: boundedString(CONNECTOR_ATTACHMENT_SOURCE_URL_MAX_UTF8_BYTES).superRefine(
154
+ (value, context) => {
155
+ let parsed: URL;
156
+ try {
157
+ parsed = new URL(value);
158
+ } catch {
159
+ context.addIssue({
160
+ code: "custom",
161
+ message: "must be an absolute URL",
162
+ });
163
+ return;
164
+ }
165
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
166
+ context.addIssue({ code: "custom", message: "must use http or https" });
167
+ }
168
+ if (parsed.username || parsed.password) {
169
+ context.addIssue({
170
+ code: "custom",
171
+ message: "must not contain URL userinfo",
172
+ });
173
+ }
174
+ if (parsed.hash) {
175
+ context.addIssue({
176
+ code: "custom",
177
+ message: "must not contain a URL fragment",
178
+ });
179
+ }
180
+ },
181
+ ),
182
+ expiresAt: z.iso.datetime({ offset: true }),
183
+ })
184
+ .strict();
185
+ export type ConnectorAttachmentPrivateSource = z.infer<typeof ConnectorAttachmentPrivateSource>;
186
+
187
+ export const ConnectorAttachmentTransfer = z
188
+ .object({
189
+ providerAttachmentId: ConnectorAttachmentProviderIdentity,
190
+ fileName: ConnectorAttachmentFileName,
191
+ mediaType: ConnectorAttachmentMediaType,
192
+ byteSize: z.number().int().min(0).max(CONNECTOR_ATTACHMENT_MAX_BYTES),
193
+ contentSha256: ConnectorAttachmentSha256,
194
+ source: ConnectorAttachmentPrivateSource,
195
+ })
196
+ .strict()
197
+ .superRefine((attachment, context) => {
198
+ const publicValues = [
199
+ attachment.providerAttachmentId.value,
200
+ attachment.fileName,
201
+ attachment.mediaType,
202
+ ];
203
+ for (const credential of privateUrlCredentialValues(attachment.source.url)) {
204
+ if (publicValues.some((value) => publicMetadataContainsCredential(value, credential))) {
205
+ context.addIssue({
206
+ code: "custom",
207
+ message: "private source credentials must not appear in public attachment metadata",
208
+ });
209
+ return;
210
+ }
211
+ }
212
+ });
213
+ export type ConnectorAttachmentTransfer = z.infer<typeof ConnectorAttachmentTransfer>;
214
+
215
+ export const ConnectorAttachmentTransferEnvelope = z
216
+ .object({
217
+ version: z.literal(CONNECTOR_ATTACHMENT_TRANSFER_VERSION),
218
+ attachments: z.array(ConnectorAttachmentTransfer).min(1).max(CONNECTOR_ATTACHMENT_MAX_COUNT),
219
+ })
220
+ .strict()
221
+ .superRefine((envelope, context) => {
222
+ const identities = new Set<string>();
223
+ for (const [index, attachment] of envelope.attachments.entries()) {
224
+ const identity = `${attachment.providerAttachmentId.provider}\0${attachment.providerAttachmentId.value}`;
225
+ if (identities.has(identity)) {
226
+ context.addIssue({
227
+ code: "custom",
228
+ message: "provider attachment identities must be unique",
229
+ path: ["attachments", index, "providerAttachmentId"],
230
+ });
231
+ }
232
+ identities.add(identity);
233
+ }
234
+ });
235
+ export type ConnectorAttachmentTransferEnvelope = z.infer<
236
+ typeof ConnectorAttachmentTransferEnvelope
237
+ >;
238
+
239
+ export const ConnectorAttachmentSandboxPath = boundedString(
240
+ CONNECTOR_ATTACHMENT_SANDBOX_PATH_MAX_UTF8_BYTES,
241
+ )
242
+ .min(1)
243
+ .refine(
244
+ (value) => {
245
+ if (
246
+ value !== value.trim() ||
247
+ value.startsWith("/") ||
248
+ /^[A-Za-z]:[\\/]/u.test(value) ||
249
+ value.includes("\\") ||
250
+ CONTROL_CHARACTER_PATTERN.test(value)
251
+ ) {
252
+ return false;
253
+ }
254
+ const segments = value.split("/");
255
+ if (
256
+ segments.length !== 5 ||
257
+ segments[0] !== ".opengeni" ||
258
+ segments[1] !== "connector-attachments" ||
259
+ !PROVIDER_PATTERN.test(segments[2] ?? "") ||
260
+ !/^[0-9a-f]{32}$/u.test(segments[3] ?? "") ||
261
+ !ConnectorAttachmentFileName.safeParse(segments[4]).success
262
+ ) {
263
+ return false;
264
+ }
265
+ return segments.every(
266
+ (segment) =>
267
+ segment.length > 0 &&
268
+ segment !== "." &&
269
+ segment !== ".." &&
270
+ !PORTABLE_FILENAME_FORBIDDEN_PATTERN.test(segment) &&
271
+ !/[ .]$/u.test(segment) &&
272
+ !PORTABLE_FILENAME_RESERVED_PATTERN.test(segment),
273
+ );
274
+ },
275
+ { message: "must be a confined connector attachment sandbox path" },
276
+ );
277
+
278
+ export const ConnectorAttachmentReceipt = z
279
+ .object({
280
+ providerAttachmentId: ConnectorAttachmentProviderIdentity,
281
+ fileName: ConnectorAttachmentFileName,
282
+ mediaType: ConnectorAttachmentMediaType,
283
+ byteSize: z.number().int().min(0).max(CONNECTOR_ATTACHMENT_MAX_BYTES),
284
+ contentSha256: ConnectorAttachmentSha256,
285
+ sandboxPath: ConnectorAttachmentSandboxPath,
286
+ })
287
+ .strict()
288
+ .superRefine((receipt, context) => {
289
+ const segments = receipt.sandboxPath.split("/");
290
+ if (segments[2] !== receipt.providerAttachmentId.provider) {
291
+ context.addIssue({
292
+ code: "custom",
293
+ message: "sandbox path provider must match the provider attachment identity",
294
+ path: ["sandboxPath"],
295
+ });
296
+ }
297
+ if (segments[4] !== receipt.fileName) {
298
+ context.addIssue({
299
+ code: "custom",
300
+ message: "sandbox path filename must match the attachment filename",
301
+ path: ["sandboxPath"],
302
+ });
303
+ }
304
+ });
305
+ export type ConnectorAttachmentReceipt = z.infer<typeof ConnectorAttachmentReceipt>;
306
+
307
+ export const ConnectorAttachmentReceiptEnvelope = z
308
+ .object({
309
+ version: z.literal(CONNECTOR_ATTACHMENT_RECEIPT_VERSION),
310
+ attachments: z.array(ConnectorAttachmentReceipt).min(1).max(CONNECTOR_ATTACHMENT_MAX_COUNT),
311
+ })
312
+ .strict();
313
+ export type ConnectorAttachmentReceiptEnvelope = z.infer<typeof ConnectorAttachmentReceiptEnvelope>;
314
+
315
+ export function parseConnectorAttachmentTransferEnvelope(
316
+ value: unknown,
317
+ options: { nowMs?: number } = {},
318
+ ): ConnectorAttachmentTransferEnvelope {
319
+ const envelope = ConnectorAttachmentTransferEnvelope.parse(value);
320
+ const nowMs = options.nowMs ?? Date.now();
321
+ for (const attachment of envelope.attachments) {
322
+ if (Date.parse(attachment.source.expiresAt) <= nowMs) {
323
+ throw new Error("connector attachment source is expired");
324
+ }
325
+ }
326
+ return envelope;
327
+ }
@@ -0,0 +1,60 @@
1
+ import { z } from "zod";
2
+ import { MCP_MAX_CATALOG_TOOL_ENTRIES } from "./mcp-catalog-limits";
3
+
4
+ export const ConnectorToolPermission = z.enum(["allow", "ask", "block"]);
5
+ export type ConnectorToolPermission = z.infer<typeof ConnectorToolPermission>;
6
+
7
+ export const ConnectorToolPermissionEntry = z.object({
8
+ name: z.string().min(1).max(512),
9
+ title: z.string().optional(),
10
+ description: z.string().optional(),
11
+ group: z.enum(["read", "write", "other"]),
12
+ permission: ConnectorToolPermission,
13
+ inherited: z.boolean(),
14
+ approvalRequired: z.boolean(),
15
+ });
16
+ export type ConnectorToolPermissionEntry = z.infer<typeof ConnectorToolPermissionEntry>;
17
+
18
+ export const ConnectorToolPermissionsResponse = z.object({
19
+ connectionId: z.string(),
20
+ serverId: z.string(),
21
+ defaultPermission: ConnectorToolPermission.nullable(),
22
+ tools: z.array(ConnectorToolPermissionEntry),
23
+ discoveryError: z.string().nullable(),
24
+ canManage: z.boolean(),
25
+ });
26
+ export type ConnectorToolPermissionsResponse = z.infer<typeof ConnectorToolPermissionsResponse>;
27
+
28
+ // Group changes name the currently displayed tools explicitly. MCP annotations
29
+ // organize the UI only; they never grant future tools permission automatically.
30
+ export const UpdateConnectorToolPermissionsRequest = z.discriminatedUnion("target", [
31
+ z
32
+ .object({
33
+ connectionId: z.string().min(1).max(512),
34
+ target: z.literal("default"),
35
+ permission: ConnectorToolPermission,
36
+ })
37
+ .strict(),
38
+ z
39
+ .object({
40
+ connectionId: z.string().min(1).max(512),
41
+ target: z.literal("tools"),
42
+ toolNames: z
43
+ .array(
44
+ z
45
+ .string()
46
+ .min(1)
47
+ .max(512)
48
+ .refine((name) => name !== "*" && name === name.trim(), {
49
+ message: "Tool names must be exact and cannot use the connector-default wildcard.",
50
+ }),
51
+ )
52
+ .min(1)
53
+ .max(MCP_MAX_CATALOG_TOOL_ENTRIES),
54
+ permission: ConnectorToolPermission,
55
+ })
56
+ .strict(),
57
+ ]);
58
+ export type UpdateConnectorToolPermissionsRequest = z.infer<
59
+ typeof UpdateConnectorToolPermissionsRequest
60
+ >;
@@ -0,0 +1,98 @@
1
+ import { z } from "zod";
2
+
3
+ export const DirectModelProvider = z.enum(["openai", "azure_openai"]);
4
+ export type DirectModelProvider = z.infer<typeof DirectModelProvider>;
5
+
6
+ /** Pin customer credentials to official provider origins, never arbitrary URLs. */
7
+ export const AzureOpenAIEndpoint = z
8
+ .string()
9
+ .trim()
10
+ .url()
11
+ .superRefine((value, ctx) => {
12
+ let url: URL;
13
+ try {
14
+ url = new URL(value);
15
+ } catch {
16
+ // The preceding URL validator supplies the normal validation issue.
17
+ return;
18
+ }
19
+ if (
20
+ url.protocol !== "https:" ||
21
+ url.username ||
22
+ url.password ||
23
+ url.port ||
24
+ !/^[a-z0-9-]+\.openai\.azure\.com$/i.test(url.hostname) ||
25
+ !["", "/", "/openai/v1", "/openai/v1/"].includes(url.pathname) ||
26
+ url.search ||
27
+ url.hash
28
+ ) {
29
+ ctx.addIssue({ code: "custom", message: "Enter your Azure OpenAI HTTPS resource endpoint" });
30
+ }
31
+ })
32
+ .transform((value) => new URL(value).origin + "/openai/v1");
33
+
34
+ export const DirectModelProviderMetadata = z
35
+ .object({
36
+ provider: DirectModelProvider,
37
+ model: z
38
+ .string()
39
+ .trim()
40
+ .min(1)
41
+ .max(128)
42
+ .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/),
43
+ endpoint: AzureOpenAIEndpoint.optional(),
44
+ })
45
+ .strict()
46
+ .superRefine((value, ctx) => {
47
+ if (value.provider === "azure_openai" && !value.endpoint) {
48
+ ctx.addIssue({
49
+ code: "custom",
50
+ path: ["endpoint"],
51
+ message: "Azure OpenAI needs an endpoint",
52
+ });
53
+ }
54
+ if (value.provider === "openai" && value.endpoint) {
55
+ ctx.addIssue({
56
+ code: "custom",
57
+ path: ["endpoint"],
58
+ message: "OpenAI uses its official API endpoint",
59
+ });
60
+ }
61
+ });
62
+ export type DirectModelProviderMetadata = z.infer<typeof DirectModelProviderMetadata>;
63
+
64
+ export function directModelConnectionSpec(connection: {
65
+ id: string;
66
+ version: number;
67
+ subjectId: string | null;
68
+ kind: string;
69
+ status: string;
70
+ providerDomain: string;
71
+ metadata: Record<string, unknown>;
72
+ }) {
73
+ if (
74
+ connection.subjectId !== null ||
75
+ connection.kind !== "api_key" ||
76
+ connection.status !== "active"
77
+ )
78
+ return null;
79
+ const parsed = DirectModelProviderMetadata.safeParse(connection.metadata.directModelProvider);
80
+ if (!parsed.success || connection.metadata.credentialRole !== `direct_${parsed.data.provider}`)
81
+ return null;
82
+ const config = parsed.data;
83
+ const baseUrl = config.provider === "openai" ? "https://api.openai.com/v1" : config.endpoint!;
84
+ if (connection.providerDomain.toLowerCase() !== new URL(baseUrl).hostname) return null;
85
+ const providerId = `workspace-${config.provider === "openai" ? "openai" : "azure-openai"}-${connection.id}`;
86
+ return {
87
+ ...config,
88
+ baseUrl,
89
+ providerId,
90
+ modelId: `${providerId}/${connection.version}/${config.model}`,
91
+ connectionId: connection.id,
92
+ version: connection.version,
93
+ };
94
+ }
95
+
96
+ export function isDirectModelId(modelId: string): boolean {
97
+ return /^workspace-(?:openai|azure-openai)-[0-9a-f-]{36}\//.test(modelId);
98
+ }
@@ -54,13 +54,24 @@ import {
54
54
  encodeSpreadsheetArtifactKernelQuery,
55
55
  } from "./spreadsheet-artifact-query";
56
56
  import {
57
- EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,
58
- EDITABLE_ARTIFACT_SNAPSHOT_VERSION,
57
+ DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,
58
+ DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,
59
+ EDITABLE_ARTIFACT_LIVE_WIRE_VERSION,
60
+ EDITABLE_ARTIFACT_SERIALIZED_COMMIT_VERSION,
61
+ PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,
62
+ PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,
63
+ COMMITTED_TRANSACTION_PROTOCOL_VERSION,
64
+ SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
65
+ SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
59
66
  } from "./editable-artifact-versions";
60
67
 
61
68
  export {
62
- EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,
63
- EDITABLE_ARTIFACT_SNAPSHOT_VERSION,
69
+ DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,
70
+ DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,
71
+ PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,
72
+ PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,
73
+ SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
74
+ SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
64
75
  } from "./editable-artifact-versions";
65
76
 
66
77
  export type EditableArtifactModality = "spreadsheet" | "document" | "presentation";
@@ -68,13 +79,22 @@ export type EditableArtifactConcurrencySemantics =
68
79
  | "causal-crdt-v1"
69
80
  | "authoritative-serialized-stale-base-v1";
70
81
 
82
+ export type CurrentEditableArtifactCompatibility = Readonly<{
83
+ modality: EditableArtifactModality;
84
+ liveProtocolVersion: number;
85
+ modelSchemaVersion: number;
86
+ snapshotVersion: number;
87
+ commandProtocolVersion: number;
88
+ committedTransactionProtocolVersion: number;
89
+ }>;
90
+
71
91
  export type EditableArtifactCodecDescriptor = Readonly<{
72
92
  modality: EditableArtifactModality;
73
- modelSchemaVersion: typeof EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION;
74
- snapshotVersion: typeof EDITABLE_ARTIFACT_SNAPSHOT_VERSION;
93
+ modelSchemaVersion: 1 | 2;
94
+ snapshotVersion: 1 | 2;
75
95
  command: Readonly<{
76
- magic: "OGASC001" | "OGADC001" | "OGAPC001";
77
- version: 1;
96
+ magic: "OGASC002" | "OGADC001" | "OGAPC001";
97
+ version: 1 | 2;
78
98
  maximumBytes: number;
79
99
  maximumCommands: number;
80
100
  encode: (value: unknown) => Uint8Array;
@@ -97,17 +117,17 @@ export type EditableArtifactCodecDescriptor = Readonly<{
97
117
  }>;
98
118
  concurrency: Readonly<{
99
119
  semantics: EditableArtifactConcurrencySemantics;
100
- collaborationEnvelope: "OGACO001" | null;
120
+ collaborationEnvelope: "OGACO002" | null;
101
121
  staleBaseMustBeRejected: boolean;
102
122
  }>;
103
123
  }>;
104
124
 
105
125
  const spreadsheet = Object.freeze({
106
126
  modality: "spreadsheet",
107
- modelSchemaVersion: 1,
108
- snapshotVersion: 1,
127
+ modelSchemaVersion: SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
128
+ snapshotVersion: SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
109
129
  command: Object.freeze({
110
- magic: "OGASC001",
130
+ magic: "OGASC002",
111
131
  version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
112
132
  maximumBytes: SPREADSHEET_ARTIFACT_COMMAND_MAX_BYTES,
113
133
  maximumCommands: SPREADSHEET_ARTIFACT_COMMAND_MAX_COMMANDS,
@@ -140,15 +160,15 @@ const spreadsheet = Object.freeze({
140
160
  }),
141
161
  concurrency: Object.freeze({
142
162
  semantics: "causal-crdt-v1",
143
- collaborationEnvelope: "OGACO001",
163
+ collaborationEnvelope: "OGACO002",
144
164
  staleBaseMustBeRejected: false,
145
165
  }),
146
166
  }) satisfies EditableArtifactCodecDescriptor;
147
167
 
148
168
  const document = Object.freeze({
149
169
  modality: "document",
150
- modelSchemaVersion: 1,
151
- snapshotVersion: 1,
170
+ modelSchemaVersion: DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,
171
+ snapshotVersion: DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,
152
172
  command: Object.freeze({
153
173
  magic: "OGADC001",
154
174
  version: DOCUMENT_ARTIFACT_COMMAND_VERSION,
@@ -188,8 +208,8 @@ const document = Object.freeze({
188
208
 
189
209
  const presentation = Object.freeze({
190
210
  modality: "presentation",
191
- modelSchemaVersion: 1,
192
- snapshotVersion: 1,
211
+ modelSchemaVersion: PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,
212
+ snapshotVersion: PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,
193
213
  command: Object.freeze({
194
214
  magic: "OGAPC001",
195
215
  version: PRESENTATION_ARTIFACT_COMMAND_VERSION,
@@ -233,6 +253,24 @@ export const EDITABLE_ARTIFACT_CODEC_REGISTRY: Readonly<
233
253
  Record<EditableArtifactModality, EditableArtifactCodecDescriptor>
234
254
  > = Object.freeze({ spreadsheet, document, presentation });
235
255
 
256
+ /** One exact current compatibility tuple per durable modality. */
257
+ export function currentEditableArtifactCompatibility(
258
+ modality: EditableArtifactModality,
259
+ ): CurrentEditableArtifactCompatibility {
260
+ const descriptor = EDITABLE_ARTIFACT_CODEC_REGISTRY[modality];
261
+ return Object.freeze({
262
+ modality,
263
+ liveProtocolVersion: EDITABLE_ARTIFACT_LIVE_WIRE_VERSION,
264
+ modelSchemaVersion: descriptor.modelSchemaVersion,
265
+ snapshotVersion: descriptor.snapshotVersion,
266
+ commandProtocolVersion: descriptor.command.version,
267
+ committedTransactionProtocolVersion:
268
+ modality === "spreadsheet"
269
+ ? COMMITTED_TRANSACTION_PROTOCOL_VERSION
270
+ : EDITABLE_ARTIFACT_SERIALIZED_COMMIT_VERSION,
271
+ });
272
+ }
273
+
236
274
  /**
237
275
  * Selects solely from the durable artifact modality plus persisted versions.
238
276
  * Modality intentionally never enters OGATX001: the durable artifact row is