@xemahq/kernel-contracts 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/LICENSE +201 -0
  2. package/dist/agent-tool-inquiry/index.d.ts +2 -0
  3. package/dist/agent-tool-inquiry/index.d.ts.map +1 -0
  4. package/dist/agent-tool-inquiry/index.js +18 -0
  5. package/dist/agent-tool-inquiry/index.js.map +1 -0
  6. package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.d.ts +43 -0
  7. package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.d.ts.map +1 -0
  8. package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.js +32 -0
  9. package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.js.map +1 -0
  10. package/dist/agent-workspace/awp-spec.json +1 -1
  11. package/dist/app-runtime/index.d.ts +9 -0
  12. package/dist/app-runtime/index.d.ts.map +1 -0
  13. package/dist/app-runtime/index.js +25 -0
  14. package/dist/app-runtime/index.js.map +1 -0
  15. package/dist/app-runtime/lib/app-client.d.ts +11 -0
  16. package/dist/app-runtime/lib/app-client.d.ts.map +1 -0
  17. package/dist/app-runtime/lib/app-client.js +23 -0
  18. package/dist/app-runtime/lib/app-client.js.map +1 -0
  19. package/dist/app-runtime/lib/app-lockfile.d.ts +12 -0
  20. package/dist/app-runtime/lib/app-lockfile.d.ts.map +1 -0
  21. package/dist/app-runtime/lib/app-lockfile.js +17 -0
  22. package/dist/app-runtime/lib/app-lockfile.js.map +1 -0
  23. package/dist/app-runtime/lib/app.d.ts +26 -0
  24. package/dist/app-runtime/lib/app.d.ts.map +1 -0
  25. package/dist/app-runtime/lib/app.js +31 -0
  26. package/dist/app-runtime/lib/app.js.map +1 -0
  27. package/dist/app-runtime/lib/audience-policy.d.ts +31 -0
  28. package/dist/app-runtime/lib/audience-policy.d.ts.map +1 -0
  29. package/dist/app-runtime/lib/audience-policy.js +38 -0
  30. package/dist/app-runtime/lib/audience-policy.js.map +1 -0
  31. package/dist/app-runtime/lib/biome-install.d.ts +9 -0
  32. package/dist/app-runtime/lib/biome-install.d.ts.map +1 -0
  33. package/dist/app-runtime/lib/biome-install.js +13 -0
  34. package/dist/app-runtime/lib/biome-install.js.map +1 -0
  35. package/dist/app-runtime/lib/branding-config.d.ts +9 -0
  36. package/dist/app-runtime/lib/branding-config.d.ts.map +1 -0
  37. package/dist/app-runtime/lib/branding-config.js +24 -0
  38. package/dist/app-runtime/lib/branding-config.js.map +1 -0
  39. package/dist/app-runtime/lib/delegated-session.d.ts +15 -0
  40. package/dist/app-runtime/lib/delegated-session.d.ts.map +1 -0
  41. package/dist/app-runtime/lib/delegated-session.js +29 -0
  42. package/dist/app-runtime/lib/delegated-session.js.map +1 -0
  43. package/dist/app-runtime/lib/external-subject.d.ts +9 -0
  44. package/dist/app-runtime/lib/external-subject.d.ts.map +1 -0
  45. package/dist/app-runtime/lib/external-subject.js +19 -0
  46. package/dist/app-runtime/lib/external-subject.js.map +1 -0
  47. package/dist/connector/index.d.ts +9 -0
  48. package/dist/connector/index.d.ts.map +1 -0
  49. package/dist/connector/index.js +25 -0
  50. package/dist/connector/index.js.map +1 -0
  51. package/dist/connector/lib/adapter-kind.d.ts +8 -0
  52. package/dist/connector/lib/adapter-kind.d.ts.map +1 -0
  53. package/dist/connector/lib/adapter-kind.js +14 -0
  54. package/dist/connector/lib/adapter-kind.js.map +1 -0
  55. package/dist/connector/lib/capability-refs.d.ts +14 -0
  56. package/dist/connector/lib/capability-refs.d.ts.map +1 -0
  57. package/dist/connector/lib/capability-refs.js +15 -0
  58. package/dist/connector/lib/capability-refs.js.map +1 -0
  59. package/dist/connector/lib/capability.d.ts +18 -0
  60. package/dist/connector/lib/capability.d.ts.map +1 -0
  61. package/dist/connector/lib/capability.js +24 -0
  62. package/dist/connector/lib/capability.js.map +1 -0
  63. package/dist/connector/lib/credential-kind.d.ts +42 -0
  64. package/dist/connector/lib/credential-kind.d.ts.map +1 -0
  65. package/dist/connector/lib/credential-kind.js +26 -0
  66. package/dist/connector/lib/credential-kind.js.map +1 -0
  67. package/dist/connector/lib/envelope-schema.d.ts +6 -0
  68. package/dist/connector/lib/envelope-schema.d.ts.map +1 -0
  69. package/dist/connector/lib/envelope-schema.js +150 -0
  70. package/dist/connector/lib/envelope-schema.js.map +1 -0
  71. package/dist/connector/lib/filter-expr-schema.d.ts +4 -0
  72. package/dist/connector/lib/filter-expr-schema.d.ts.map +1 -0
  73. package/dist/connector/lib/filter-expr-schema.js +65 -0
  74. package/dist/connector/lib/filter-expr-schema.js.map +1 -0
  75. package/dist/connector/lib/filter-expr-validate.d.ts +10 -0
  76. package/dist/connector/lib/filter-expr-validate.d.ts.map +1 -0
  77. package/dist/connector/lib/filter-expr-validate.js +58 -0
  78. package/dist/connector/lib/filter-expr-validate.js.map +1 -0
  79. package/dist/connector/lib/filter-expr.d.ts +49 -0
  80. package/dist/connector/lib/filter-expr.d.ts.map +1 -0
  81. package/dist/connector/lib/filter-expr.js +135 -0
  82. package/dist/connector/lib/filter-expr.js.map +1 -0
  83. package/dist/connector/lib/onboarding-manifest.d.ts +45 -0
  84. package/dist/connector/lib/onboarding-manifest.d.ts.map +1 -0
  85. package/dist/connector/lib/onboarding-manifest.js +30 -0
  86. package/dist/connector/lib/onboarding-manifest.js.map +1 -0
  87. package/dist/document-render/index.d.ts +7 -0
  88. package/dist/document-render/index.d.ts.map +1 -0
  89. package/dist/document-render/index.js +23 -0
  90. package/dist/document-render/index.js.map +1 -0
  91. package/dist/document-render/lib/measure-layout.d.ts +44 -0
  92. package/dist/document-render/lib/measure-layout.d.ts.map +1 -0
  93. package/dist/document-render/lib/measure-layout.js +16 -0
  94. package/dist/document-render/lib/measure-layout.js.map +1 -0
  95. package/dist/document-render/lib/render-enums.d.ts +18 -0
  96. package/dist/document-render/lib/render-enums.d.ts.map +1 -0
  97. package/dist/document-render/lib/render-enums.js +24 -0
  98. package/dist/document-render/lib/render-enums.js.map +1 -0
  99. package/dist/document-render/lib/render-record.d.ts +22 -0
  100. package/dist/document-render/lib/render-record.d.ts.map +1 -0
  101. package/dist/document-render/lib/render-record.js +3 -0
  102. package/dist/document-render/lib/render-record.js.map +1 -0
  103. package/dist/document-render/lib/render-request.d.ts +24 -0
  104. package/dist/document-render/lib/render-request.d.ts.map +1 -0
  105. package/dist/document-render/lib/render-request.js +12 -0
  106. package/dist/document-render/lib/render-request.js.map +1 -0
  107. package/dist/document-render/lib/render-source.d.ts +43 -0
  108. package/dist/document-render/lib/render-source.d.ts.map +1 -0
  109. package/dist/document-render/lib/render-source.js +31 -0
  110. package/dist/document-render/lib/render-source.js.map +1 -0
  111. package/dist/document-render/lib/xema-prompt.d.ts +11 -0
  112. package/dist/document-render/lib/xema-prompt.d.ts.map +1 -0
  113. package/dist/document-render/lib/xema-prompt.js +46 -0
  114. package/dist/document-render/lib/xema-prompt.js.map +1 -0
  115. package/dist/inquiry/index.d.ts +7 -0
  116. package/dist/inquiry/index.d.ts.map +1 -0
  117. package/dist/inquiry/index.js +23 -0
  118. package/dist/inquiry/index.js.map +1 -0
  119. package/dist/inquiry/lib/enums.d.ts +36 -0
  120. package/dist/inquiry/lib/enums.d.ts.map +1 -0
  121. package/dist/inquiry/lib/enums.js +45 -0
  122. package/dist/inquiry/lib/enums.js.map +1 -0
  123. package/dist/inquiry/lib/inquiry.d.ts +332 -0
  124. package/dist/inquiry/lib/inquiry.d.ts.map +1 -0
  125. package/dist/inquiry/lib/inquiry.js +102 -0
  126. package/dist/inquiry/lib/inquiry.js.map +1 -0
  127. package/dist/inquiry/lib/kind-registry.d.ts +14 -0
  128. package/dist/inquiry/lib/kind-registry.d.ts.map +1 -0
  129. package/dist/inquiry/lib/kind-registry.js +24 -0
  130. package/dist/inquiry/lib/kind-registry.js.map +1 -0
  131. package/dist/inquiry/lib/policy.d.ts +19 -0
  132. package/dist/inquiry/lib/policy.d.ts.map +1 -0
  133. package/dist/inquiry/lib/policy.js +21 -0
  134. package/dist/inquiry/lib/policy.js.map +1 -0
  135. package/dist/inquiry/lib/recipient.d.ts +111 -0
  136. package/dist/inquiry/lib/recipient.d.ts.map +1 -0
  137. package/dist/inquiry/lib/recipient.js +64 -0
  138. package/dist/inquiry/lib/recipient.js.map +1 -0
  139. package/dist/inquiry/lib/workflow-verdict-evaluator.d.ts +15 -0
  140. package/dist/inquiry/lib/workflow-verdict-evaluator.d.ts.map +1 -0
  141. package/dist/inquiry/lib/workflow-verdict-evaluator.js +145 -0
  142. package/dist/inquiry/lib/workflow-verdict-evaluator.js.map +1 -0
  143. package/dist/org-database/index.d.ts +5 -0
  144. package/dist/org-database/index.d.ts.map +1 -0
  145. package/dist/org-database/index.js +21 -0
  146. package/dist/org-database/index.js.map +1 -0
  147. package/dist/org-database/lib/db-result-event.d.ts +24 -0
  148. package/dist/org-database/lib/db-result-event.d.ts.map +1 -0
  149. package/dist/org-database/lib/db-result-event.js +3 -0
  150. package/dist/org-database/lib/db-result-event.js.map +1 -0
  151. package/dist/org-database/lib/driver.d.ts +43 -0
  152. package/dist/org-database/lib/driver.d.ts.map +1 -0
  153. package/dist/org-database/lib/driver.js +3 -0
  154. package/dist/org-database/lib/driver.js.map +1 -0
  155. package/dist/org-database/lib/enums.d.ts +41 -0
  156. package/dist/org-database/lib/enums.d.ts.map +1 -0
  157. package/dist/org-database/lib/enums.js +51 -0
  158. package/dist/org-database/lib/enums.js.map +1 -0
  159. package/dist/org-database/lib/migration-runner.d.ts +15 -0
  160. package/dist/org-database/lib/migration-runner.d.ts.map +1 -0
  161. package/dist/org-database/lib/migration-runner.js +3 -0
  162. package/dist/org-database/lib/migration-runner.js.map +1 -0
  163. package/dist/project-kit/index.d.ts +2 -0
  164. package/dist/project-kit/index.d.ts.map +1 -0
  165. package/dist/project-kit/index.js +18 -0
  166. package/dist/project-kit/index.js.map +1 -0
  167. package/dist/project-kit/lib/project-kit.d.ts +63 -0
  168. package/dist/project-kit/lib/project-kit.d.ts.map +1 -0
  169. package/dist/project-kit/lib/project-kit.js +32 -0
  170. package/dist/project-kit/lib/project-kit.js.map +1 -0
  171. package/dist/provisioning/index.d.ts +2 -0
  172. package/dist/provisioning/index.d.ts.map +1 -0
  173. package/dist/provisioning/index.js +18 -0
  174. package/dist/provisioning/index.js.map +1 -0
  175. package/dist/provisioning/lib/provisioning.d.ts +256 -0
  176. package/dist/provisioning/lib/provisioning.d.ts.map +1 -0
  177. package/dist/provisioning/lib/provisioning.js +221 -0
  178. package/dist/provisioning/lib/provisioning.js.map +1 -0
  179. package/dist/worker-runtime/index.d.ts +6 -0
  180. package/dist/worker-runtime/index.d.ts.map +1 -0
  181. package/dist/worker-runtime/index.js +22 -0
  182. package/dist/worker-runtime/index.js.map +1 -0
  183. package/dist/worker-runtime/lib/capabilities.d.ts +22 -0
  184. package/dist/worker-runtime/lib/capabilities.d.ts.map +1 -0
  185. package/dist/worker-runtime/lib/capabilities.js +3 -0
  186. package/dist/worker-runtime/lib/capabilities.js.map +1 -0
  187. package/dist/worker-runtime/lib/enums.d.ts +10 -0
  188. package/dist/worker-runtime/lib/enums.d.ts.map +1 -0
  189. package/dist/worker-runtime/lib/enums.js +15 -0
  190. package/dist/worker-runtime/lib/enums.js.map +1 -0
  191. package/dist/worker-runtime/lib/messages.d.ts +33 -0
  192. package/dist/worker-runtime/lib/messages.d.ts.map +1 -0
  193. package/dist/worker-runtime/lib/messages.js +3 -0
  194. package/dist/worker-runtime/lib/messages.js.map +1 -0
  195. package/dist/worker-runtime/lib/runtime.d.ts +35 -0
  196. package/dist/worker-runtime/lib/runtime.d.ts.map +1 -0
  197. package/dist/worker-runtime/lib/runtime.js +3 -0
  198. package/dist/worker-runtime/lib/runtime.js.map +1 -0
  199. package/dist/worker-runtime/lib/schemas.d.ts +87 -0
  200. package/dist/worker-runtime/lib/schemas.d.ts.map +1 -0
  201. package/dist/worker-runtime/lib/schemas.js +57 -0
  202. package/dist/worker-runtime/lib/schemas.js.map +1 -0
  203. package/dist/workspace-storage/index.d.ts +4 -0
  204. package/dist/workspace-storage/index.d.ts.map +1 -0
  205. package/dist/workspace-storage/index.js +20 -0
  206. package/dist/workspace-storage/index.js.map +1 -0
  207. package/dist/workspace-storage/lib/enums.d.ts +34 -0
  208. package/dist/workspace-storage/lib/enums.d.ts.map +1 -0
  209. package/dist/workspace-storage/lib/enums.js +42 -0
  210. package/dist/workspace-storage/lib/enums.js.map +1 -0
  211. package/dist/workspace-storage/lib/schemas.d.ts +56 -0
  212. package/dist/workspace-storage/lib/schemas.d.ts.map +1 -0
  213. package/dist/workspace-storage/lib/schemas.js +59 -0
  214. package/dist/workspace-storage/lib/schemas.js.map +1 -0
  215. package/dist/workspace-storage/lib/types.d.ts +71 -0
  216. package/dist/workspace-storage/lib/types.d.ts.map +1 -0
  217. package/dist/workspace-storage/lib/types.js +3 -0
  218. package/dist/workspace-storage/lib/types.js.map +1 -0
  219. package/package.json +22 -153
  220. package/src/agent-composition/lib/composition-workspace.ts +1 -1
  221. package/src/agent-tool-inquiry/index.ts +16 -0
  222. package/src/agent-tool-inquiry/lib/agent-tool-inquiry.ts +82 -0
  223. package/src/agent-workspace/lib/workspace-spec.ts +1 -1
  224. package/src/app-runtime/index.ts +8 -0
  225. package/src/app-runtime/lib/app-client.ts +44 -0
  226. package/src/app-runtime/lib/app-lockfile.ts +54 -0
  227. package/src/app-runtime/lib/app.ts +84 -0
  228. package/src/app-runtime/lib/audience-policy.ts +87 -0
  229. package/src/app-runtime/lib/biome-install.ts +29 -0
  230. package/src/app-runtime/lib/branding-config.ts +54 -0
  231. package/src/app-runtime/lib/delegated-session.ts +69 -0
  232. package/src/app-runtime/lib/external-subject.ts +34 -0
  233. package/src/connector/index.ts +8 -0
  234. package/src/connector/lib/adapter-kind.ts +37 -0
  235. package/src/connector/lib/capability-refs.ts +29 -0
  236. package/src/connector/lib/capability.ts +38 -0
  237. package/src/connector/lib/credential-kind.ts +120 -0
  238. package/src/connector/lib/envelope-schema.ts +256 -0
  239. package/src/connector/lib/filter-expr-schema.ts +75 -0
  240. package/src/connector/lib/filter-expr-validate.ts +91 -0
  241. package/src/connector/lib/filter-expr.ts +208 -0
  242. package/src/connector/lib/onboarding-manifest.ts +167 -0
  243. package/src/document-render/index.ts +25 -0
  244. package/src/document-render/lib/measure-layout.ts +61 -0
  245. package/src/document-render/lib/render-enums.ts +49 -0
  246. package/src/document-render/lib/render-record.ts +38 -0
  247. package/src/document-render/lib/render-request.ts +16 -0
  248. package/src/document-render/lib/render-source.ts +44 -0
  249. package/src/document-render/lib/xema-prompt.ts +100 -0
  250. package/src/inquiry/index.ts +23 -0
  251. package/src/inquiry/lib/enums.ts +103 -0
  252. package/src/inquiry/lib/inquiry.ts +182 -0
  253. package/src/inquiry/lib/kind-registry.ts +57 -0
  254. package/src/inquiry/lib/policy.ts +27 -0
  255. package/src/inquiry/lib/recipient.ts +188 -0
  256. package/src/inquiry/lib/workflow-verdict-evaluator.ts +220 -0
  257. package/src/org-database/index.ts +4 -0
  258. package/src/org-database/lib/db-result-event.ts +59 -0
  259. package/src/org-database/lib/driver.ts +47 -0
  260. package/src/org-database/lib/enums.ts +51 -0
  261. package/src/org-database/lib/migration-runner.ts +17 -0
  262. package/src/project-kit/index.ts +17 -0
  263. package/src/project-kit/lib/project-kit.ts +227 -0
  264. package/src/provisioning/index.ts +17 -0
  265. package/src/provisioning/lib/provisioning.ts +499 -0
  266. package/src/worker-runtime/index.ts +14 -0
  267. package/src/worker-runtime/lib/capabilities.ts +58 -0
  268. package/src/worker-runtime/lib/enums.ts +33 -0
  269. package/src/worker-runtime/lib/messages.ts +49 -0
  270. package/src/worker-runtime/lib/runtime.ts +109 -0
  271. package/src/worker-runtime/lib/schemas.ts +72 -0
  272. package/src/workflow/lib/activity-outputs.ts +1 -1
  273. package/src/workflow/lib/compiled-run.ts +1 -1
  274. package/src/workflow/lib/compiled-workspace-manifest.ts +1 -1
  275. package/src/workflow/lib/model-ref.ts +1 -1
  276. package/src/workflow/lib/workspace-manifest-enums.ts +1 -1
  277. package/src/workspace-storage/index.ts +12 -0
  278. package/src/workspace-storage/lib/enums.ts +78 -0
  279. package/src/workspace-storage/lib/schemas.ts +75 -0
  280. package/src/workspace-storage/lib/types.ts +145 -0
@@ -0,0 +1,54 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Accepts:
5
+ * - 3- or 6-digit hex (e.g. `#0a0`, `#0a0a0a`)
6
+ * - 8-digit hex with alpha (e.g. `#0a0a0aff`)
7
+ * - `rgb(r, g, b)` / `rgba(r, g, b, a)` (whitespace-flexible)
8
+ *
9
+ * Kept deliberately tight: the App branding contract should never silently
10
+ * absorb a free-form string. Anything else (CSS custom properties, named
11
+ * colors, `hsl(...)`, etc.) belongs in `cssTokens` where the host CSS
12
+ * pipeline interprets it.
13
+ */
14
+ const PRIMARY_COLOR_REGEX =
15
+ /^(?:#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(?:,\s*(?:0|1|0?\.\d+)\s*)?\))$/;
16
+
17
+ /**
18
+ * `BrandingConfig` — per-App visual branding (plan §5.1). Used by the
19
+ * public ingress (`app-runtime-api`) and any embed snippet to theme the
20
+ * audience-facing UI. The shape is intentionally minimal:
21
+ *
22
+ * - `displayName` is REQUIRED — every audience-facing surface needs a
23
+ * human-readable label; no silent fallback to the App slug.
24
+ * - `primaryColor` is validated against a strict hex / rgb(a) grammar.
25
+ * - `cssTokens` is the escape hatch for richer theming — keys map to CSS
26
+ * custom-property names (without the leading `--`); the host CSS
27
+ * pipeline interprets the values.
28
+ */
29
+ export interface BrandingConfig {
30
+ displayName: string;
31
+ logoUrl?: string;
32
+ primaryColor?: string;
33
+ cssTokens?: Record<string, string>;
34
+ }
35
+
36
+ export const BrandingConfigSchema = z.object({
37
+ displayName: z.string().min(1, {
38
+ message: 'BrandingConfig.displayName must be a non-empty string.',
39
+ }),
40
+ logoUrl: z
41
+ .string()
42
+ .url({
43
+ message: 'BrandingConfig.logoUrl must be a valid URL.',
44
+ })
45
+ .optional(),
46
+ primaryColor: z
47
+ .string()
48
+ .regex(PRIMARY_COLOR_REGEX, {
49
+ message:
50
+ 'BrandingConfig.primaryColor must be a hex (`#rgb`, `#rrggbb`, `#rrggbbaa`) or `rgb()` / `rgba()` value. Use `cssTokens` for richer theming.',
51
+ })
52
+ .optional(),
53
+ cssTokens: z.record(z.string().min(1), z.string().min(1)).optional(),
54
+ }) as z.ZodType<BrandingConfig>;
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ import {
3
+ CapabilityRefSchema,
4
+ type CapabilityRef,
5
+ } from '../../capability';
6
+ import {
7
+ ExecutionEnvironmentRefSchema,
8
+ type ExecutionEnvironmentRef,
9
+ } from '../../execution-environment';
10
+
11
+ /**
12
+ * Claims carried by a delegated session token minted by `app-runtime-api`
13
+ * for an `ExternalSubject` audience (plan §5.2):
14
+ *
15
+ * ```
16
+ * sub = external-user:<externalId> (or anon:<random>)
17
+ * act = app:<appClientId>
18
+ * org = <orgId>
19
+ * project = <projectId>
20
+ * session = <sessionId>
21
+ * environment = <environmentId> (typically environment:public-session)
22
+ * capabilities = [<allowed capability refs>]
23
+ * exp = short
24
+ * ```
25
+ *
26
+ * `exp` is a Unix-epoch second count (RFC 7519 `exp` claim shape) — the
27
+ * value MUST be a positive integer. Token minting is short-lived by design;
28
+ * downstream services MUST NOT extend it silently.
29
+ *
30
+ * `capabilities` is the closed, fully-resolved set the gateway will honor
31
+ * for the lifetime of this token — refs not in this list are denied at the
32
+ * gateway with no fallback (per the capability-protocol fail-fast rule).
33
+ */
34
+ export interface DelegatedSessionClaims {
35
+ sub: string;
36
+ act: string;
37
+ org: string;
38
+ project: string;
39
+ session: string;
40
+ environment: ExecutionEnvironmentRef;
41
+ capabilities: CapabilityRef[];
42
+ exp: number;
43
+ }
44
+
45
+ export const DelegatedSessionClaimsSchema = z.object({
46
+ sub: z.string().min(1, {
47
+ message:
48
+ 'DelegatedSessionClaims.sub must be a non-empty subject identifier (e.g. `external-user:<id>` or `anon:<random>`).',
49
+ }),
50
+ act: z.string().min(1, {
51
+ message:
52
+ 'DelegatedSessionClaims.act must be a non-empty actor identifier (e.g. `app:<appClientId>`).',
53
+ }),
54
+ org: z.string().min(1, {
55
+ message: 'DelegatedSessionClaims.org must be a non-empty orgId.',
56
+ }),
57
+ project: z.string().min(1, {
58
+ message: 'DelegatedSessionClaims.project must be a non-empty projectId.',
59
+ }),
60
+ session: z.string().min(1, {
61
+ message: 'DelegatedSessionClaims.session must be a non-empty sessionId.',
62
+ }),
63
+ environment: ExecutionEnvironmentRefSchema,
64
+ capabilities: z.array(CapabilityRefSchema),
65
+ exp: z.number().int().positive({
66
+ message:
67
+ 'DelegatedSessionClaims.exp must be a positive Unix-epoch second count (RFC 7519 `exp`).',
68
+ }),
69
+ }) as z.ZodType<DelegatedSessionClaims>;
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * `ExternalSubject` — an app-scoped, non-Xema identity (plan §5.2). Created
5
+ * when an `AudiencePolicy` of kind `ExternalSubject` mints a delegated
6
+ * session for an upstream user (OIDC / magic-link / anon). External
7
+ * subjects do NOT become Xema users — they are stored and referenced only
8
+ * by their `externalId` under the owning `appClientId`.
9
+ *
10
+ * `createdAt` is a strict ISO-8601 datetime string at the wire boundary —
11
+ * no implicit timezone, no Unix-epoch fallback.
12
+ */
13
+ export interface ExternalSubject {
14
+ externalId: string;
15
+ appClientId: string;
16
+ createdAt: string;
17
+ metadata?: Record<string, unknown>;
18
+ }
19
+
20
+ export const ExternalSubjectSchema = z.object({
21
+ externalId: z.string().min(1, {
22
+ message: 'ExternalSubject.externalId must be a non-empty string.',
23
+ }),
24
+ appClientId: z.string().min(1, {
25
+ message: 'ExternalSubject.appClientId must be a non-empty string.',
26
+ }),
27
+ createdAt: z
28
+ .string()
29
+ .datetime({
30
+ message:
31
+ 'ExternalSubject.createdAt must be a strict ISO-8601 datetime string.',
32
+ }),
33
+ metadata: z.record(z.string(), z.unknown()).optional(),
34
+ }) as z.ZodType<ExternalSubject>;
@@ -0,0 +1,8 @@
1
+ export * from './lib/adapter-kind';
2
+ export * from './lib/capability';
3
+ export * from './lib/credential-kind';
4
+ export * from './lib/onboarding-manifest';
5
+ export * from './lib/envelope-schema';
6
+ export * from './lib/filter-expr';
7
+ export * from './lib/filter-expr-schema';
8
+ export * from './lib/filter-expr-validate';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Built-in adapter kinds.
3
+ *
4
+ * An `AdapterKind` is a *category* of external system. Each kind ships a
5
+ * canonical envelope schema in its owning domain service (SCM →
6
+ * connector-gateway-api, TRACKER → backlog-api, DOCUMENTATION →
7
+ * knowledge-base-api). Providers (github, gitlab, jira, …) plug into
8
+ * a kind by mapping their raw events onto that canonical envelope.
9
+ *
10
+ * The set is *built-in-closed but biome-extensible*: biomes may
11
+ * contribute additional kinds via the future `AdapterContribution`
12
+ * registry (Phase 7). The closed enum below names only the kinds the
13
+ * platform ships out-of-the-box. Anything outside this list MUST be
14
+ * either a built-in plus a biome contribution, or routed through an
15
+ * opaque `AdapterKindRef` string captured below.
16
+ */
17
+ export enum BuiltInAdapterKind {
18
+ Scm = 'scm',
19
+ Tracker = 'tracker',
20
+ Documentation = 'documentation',
21
+ }
22
+
23
+ /**
24
+ * Wire-typed reference to an adapter kind. Built-in kinds use their
25
+ * `BuiltInAdapterKind` slug; biome-contributed kinds use whatever slug
26
+ * the contributing biome registered (validated at boot by
27
+ * integration-adapters-api).
28
+ *
29
+ * Stored as a plain string so the persistence layer (Prisma) does not
30
+ * have to evolve when a biome introduces a new kind. The runtime
31
+ * registry is the authority on which slugs are currently known.
32
+ */
33
+ export type AdapterKindRef = string;
34
+
35
+ export function isBuiltInAdapterKind(ref: AdapterKindRef): ref is BuiltInAdapterKind {
36
+ return (Object.values(BuiltInAdapterKind) as string[]).includes(ref);
37
+ }
@@ -0,0 +1,29 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ── Connector capability refs ──
3
+ //
4
+ // Typed string constants for the connector capabilities exposed by the
5
+ // capability gateway. Values are CapabilityRefs (see `@xemahq/capability-
6
+ // contracts`); they version like syscalls (`@1`, `@2`, ...) and the runtime
7
+ // MUST refuse to dispatch a major version it has not registered.
8
+ //
9
+ // Source of truth: plan §17.2-B item 2. This file is the registry seed; the
10
+ // `connector-gateway-api` capability dispatcher MAY consume it directly for
11
+ // `name`-side validation.
12
+ // ═══════════════════════════════════════════════════════════════════════════
13
+
14
+ import type { CapabilityRef } from '../../capability';
15
+
16
+ export const CONNECTOR_CAPABILITY_REFS = Object.freeze({
17
+ ScmCreatePullRequest: 'connector:scm.create-pull-request@1' as CapabilityRef,
18
+ ScmMerge: 'connector:scm.merge@1' as CapabilityRef,
19
+ TrackerIssueCreate: 'connector:tracker.issue.create@1' as CapabilityRef,
20
+ TrackerIssueTransition:
21
+ 'connector:tracker.issue.transition@1' as CapabilityRef,
22
+ DocsPublishPage: 'connector:docs.publish-page@1' as CapabilityRef,
23
+ DocsPageRead: 'connector:docs.page.read@1' as CapabilityRef,
24
+ ChatSendMessage: 'connector:chat.send-message@1' as CapabilityRef,
25
+ LlmInvoke: 'connector:llm.invoke@1' as CapabilityRef,
26
+ McpToolInvoke: 'connector:mcp.tool.invoke@1' as CapabilityRef,
27
+ } as const);
28
+
29
+ export type ConnectorCapabilityRefName = keyof typeof CONNECTOR_CAPABILITY_REFS;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Capability slugs a biome can request against an integration. The set
3
+ * is *closed and built-in for v1*. Biome-contributed AdapterKinds may
4
+ * register additional capability slugs at boot (validated against the
5
+ * `^[a-z]+(\.[a-z][a-z0-9-]*)+$` shape).
6
+ *
7
+ * Slugs are `<domain>.<verb>[-qualifier]`. The first segment maps to the
8
+ * AdapterKind family the capability applies to; the rest names the
9
+ * action. Closed enum values exist for the v1 built-in kinds so consent
10
+ * UX and ESLint rules can switch on them exhaustively.
11
+ */
12
+ export enum BuiltInCapability {
13
+ ScmReadRepo = 'scm.read-repo',
14
+ ScmReadBranch = 'scm.read-branch',
15
+ ScmReadCommit = 'scm.read-commit',
16
+ ScmReadFile = 'scm.read-file',
17
+ ScmWritePrComment = 'scm.write-pr-comment',
18
+ ScmWriteCommitStatus = 'scm.write-commit-status',
19
+ TrackerReadIssue = 'tracker.read-issue',
20
+ TrackerWriteIssue = 'tracker.write-issue',
21
+ TrackerWriteComment = 'tracker.write-comment',
22
+ TrackerTransitionStatus = 'tracker.transition-status',
23
+ DocumentationReadPage = 'documentation.read-page',
24
+ DocumentationWritePage = 'documentation.write-page',
25
+ }
26
+
27
+ /**
28
+ * Capability slug at the wire boundary — a string for forward
29
+ * compatibility with biome-contributed AdapterKinds. Validate against
30
+ * the shape regex at manifest-parse time.
31
+ */
32
+ export type CapabilitySlug = string;
33
+
34
+ export const CAPABILITY_SLUG_PATTERN = /^[a-z]+(\.[a-z][a-z0-9-]*)+$/;
35
+
36
+ export function isValidCapabilitySlug(slug: string): slug is CapabilitySlug {
37
+ return CAPABILITY_SLUG_PATTERN.test(slug);
38
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Closed enum of credential strategies the platform knows how to mint,
3
+ * cache, refresh and revoke. Biomes contributing new providers (Phase
4
+ * 7) MUST declare one of these — they never ship custom mint code.
5
+ *
6
+ * Adding a kind here is a one-line schema change plus a matching
7
+ * strategy implementation under
8
+ * `apps/integration-adapters-api/src/credentials/strategies/<kind>/`.
9
+ */
10
+ export enum CredentialKind {
11
+ /** GitHub App / GitLab App style installation token (per-installation, 1h). */
12
+ AppInstall = 'app_install',
13
+ /** 3-legged OAuth user-delegated token with refresh-token rotation. */
14
+ OAuthUser = 'oauth_user',
15
+ /** 2-legged OAuth client-credentials grant. */
16
+ OAuthClient = 'oauth_client',
17
+ /** Long-lived personal access token. */
18
+ Pat = 'pat',
19
+ /** Generic API key. */
20
+ ApiKey = 'api_key',
21
+ /** Long-lived bot token (Slack / Discord style). */
22
+ BotToken = 'bot_token',
23
+ /** HTTP Basic auth credential. */
24
+ Basic = 'basic',
25
+ /** Provider-scoped restricted key (Stripe restricted keys, etc.). */
26
+ RestrictedKey = 'restricted_key',
27
+ /** AWS STS AssumeRoleWithWebIdentity using a workload-identity token. */
28
+ IamRole = 'iam_role',
29
+ /**
30
+ * No outbound credential — provider sends signed webhooks only. The
31
+ * resolver returns no token; only the webhook verifier is registered.
32
+ */
33
+ SignatureOnly = 'signature_only',
34
+ /**
35
+ * SMTP wallet (one or more per org). Stored as a typed config blob —
36
+ * `host`, `port`, `username`, `password`, `tlsMode`, optional
37
+ * `fromAddress` and `fromName`. Resolved as `tokenType='header'` with
38
+ * the full config carried in `providerHints` so the SMTP send
39
+ * activity can hand it straight to nodemailer without re-decrypting.
40
+ */
41
+ SmtpAuth = 'smtp_auth',
42
+ /**
43
+ * IMAP wallet (one or more per org). Same shape as SmtpAuth minus
44
+ * the sender fields. Resolver carries `host`, `port`, `username`,
45
+ * `password`, `tlsMode` in `providerHints` for imapflow.
46
+ */
47
+ ImapAuth = 'imap_auth',
48
+ }
49
+
50
+ /**
51
+ * Closed TLS-mode enum shared by SMTP + IMAP wallets. `auto` lets the
52
+ * client library pick the right mode for the configured port:
53
+ * - 465 / 993 → implicit TLS
54
+ * - 587 / 143 → STARTTLS (negotiated)
55
+ * - 25 (SMTP) → plain (warns; not recommended)
56
+ * `tls` / `starttls` / `plain` are the explicit overrides.
57
+ */
58
+ export enum EmailTlsMode {
59
+ Auto = 'auto',
60
+ Tls = 'tls',
61
+ Starttls = 'starttls',
62
+ Plain = 'plain',
63
+ }
64
+
65
+ /**
66
+ * Wire shape of the SMTP / IMAP wallet payload as carried in
67
+ * `MintedToken.providerHints`. The values are always plain strings on
68
+ * the wire — `port` is stringified so the platform-common decoder can
69
+ * round-trip through any envelope without losing the type. The send /
70
+ * fetch activities re-parse `port` to a number at use site.
71
+ *
72
+ * Sensitive fields (`password`) are returned by the resolver only;
73
+ * cache the minted token, not the wallet config, and never log it.
74
+ */
75
+ export interface EmailWalletHints {
76
+ host: string;
77
+ port: string;
78
+ username: string;
79
+ password: string;
80
+ tlsMode: EmailTlsMode;
81
+ /** SMTP only — default sender address for the wallet. */
82
+ fromAddress?: string;
83
+ /** SMTP only — default sender name. */
84
+ fromName?: string;
85
+ }
86
+
87
+ /**
88
+ * A minted, ready-to-use token returned by `POST /credentials/resolve`.
89
+ * Provider-neutral by construction — `providerHints` carries any
90
+ * per-provider routing data (regional endpoint, app id, …) opaquely.
91
+ */
92
+ export type MintedTokenType =
93
+ | 'bearer'
94
+ | 'basic'
95
+ | 'aws-sigv4'
96
+ | 'header'
97
+ /**
98
+ * Webhook-verifier-only: `accessToken` carries the HMAC shared
99
+ * secret. Callers MUST NOT send this anywhere outbound; the only
100
+ * intended use is local signature verification on inbound webhooks.
101
+ */
102
+ | 'signature-only';
103
+
104
+ export interface MintedToken {
105
+ tokenType: MintedTokenType;
106
+ accessToken: string;
107
+ expiresAt: string | null;
108
+ expiresInSec: number | null;
109
+ providerHints: Readonly<Record<string, string>>;
110
+ }
111
+
112
+ /**
113
+ * Reference to a concrete resource the credential mint is being asked
114
+ * to scope to. `type` identifies which `ResourceLister` produced it
115
+ * (e.g. `'repo'`, `'project'`, `'channel'`); `id` is provider-opaque.
116
+ */
117
+ export interface ResourceRef {
118
+ type: string;
119
+ id: string;
120
+ }
@@ -0,0 +1,256 @@
1
+ import { BuiltInAdapterKind, type AdapterKindRef } from './adapter-kind';
2
+
3
+ /**
4
+ * Canonical envelope path schemas — per built-in `(AdapterKind, EntityKind)`.
5
+ *
6
+ * The dispatcher receives a canonical webhook envelope shaped by the
7
+ * domain service that owns the AdapterKind (connector-gateway-api,
8
+ * backlog-api, knowledge-base-api). At biome-manifest validation
9
+ * time we want to fail fast on `FilterExpr` predicates that reference
10
+ * `$envelope.someFieldThatDoesNotExist`, instead of silently
11
+ * evaluating to `false` at dispatch.
12
+ *
13
+ * The map is keyed by `(adapterKind, entityKind)`. When a webhook
14
+ * filter declares its target `entityKind` (Phase 7 manifest field),
15
+ * the cross-validator narrows path checking to that entry. Filters
16
+ * that omit `entityKind` fall back to the `UNION_ENTITY_KIND` entry,
17
+ * which collects every path across the adapter's entity kinds — over-
18
+ * permissive but still catches the common typo class.
19
+ *
20
+ * Updates: when a domain service adds/renames a payload field, the
21
+ * matching entry below MUST be updated in the same PR. `crossValidate-
22
+ * IntegrationContract` walks every biome's filter predicates against
23
+ * this map at biome-host boot, so stale entries surface as cross-
24
+ * validation failures with named paths.
25
+ */
26
+
27
+ /**
28
+ * Wildcard entityKind used when a `FilterExpr` predicate doesn't
29
+ * declare which entity kind it targets. Matches the union across all
30
+ * entity kinds the adapter owns.
31
+ */
32
+ export const UNION_ENTITY_KIND = '*';
33
+
34
+ /** Inherited base envelope fields (defined on `IntegrationWebhookEnvelopeDto`). */
35
+ const BASE_ENVELOPE_PATHS = [
36
+ 'provider',
37
+ 'adapterKey',
38
+ 'event',
39
+ 'entityKind',
40
+ 'deliveryId',
41
+ 'occurredAt',
42
+ 'correlationId',
43
+ 'externalId',
44
+ 'externalSpaceKey',
45
+ ] as const;
46
+
47
+ // ── SCM per-entityKind payload paths ──
48
+
49
+ const SCM_PUSH_PATHS = [
50
+ 'payload.repositoryCloneUrl',
51
+ 'payload.repositoryFullName',
52
+ 'payload.authorExternalId',
53
+ 'payload.ref',
54
+ 'payload.branch',
55
+ 'payload.beforeSha',
56
+ 'payload.afterSha',
57
+ 'payload.commitCount',
58
+ 'payload.commits',
59
+ 'payload.commits.sha',
60
+ 'payload.commits.message',
61
+ 'payload.commits.authorExternalId',
62
+ 'payload.commits.committedAt',
63
+ ] as const;
64
+
65
+ const SCM_CHANGE_REQUEST_PATHS = [
66
+ 'payload.repositoryCloneUrl',
67
+ 'payload.repositoryFullName',
68
+ 'payload.authorExternalId',
69
+ 'payload.title',
70
+ 'payload.description',
71
+ 'payload.state',
72
+ 'payload.sourceBranch',
73
+ 'payload.targetBranch',
74
+ 'payload.headSha',
75
+ 'payload.mergeCommitSha',
76
+ ] as const;
77
+
78
+ const SCM_ISSUE_PATHS = [
79
+ 'payload.repositoryCloneUrl',
80
+ 'payload.repositoryFullName',
81
+ 'payload.authorExternalId',
82
+ 'payload.title',
83
+ 'payload.description',
84
+ 'payload.state',
85
+ 'payload.labels',
86
+ ] as const;
87
+
88
+ const SCM_REPOSITORY_PATHS = [
89
+ 'payload.repositoryCloneUrl',
90
+ 'payload.repositoryFullName',
91
+ 'payload.action',
92
+ 'payload.visibility',
93
+ 'payload.previousVisibility',
94
+ 'payload.previousRepositoryCloneUrl',
95
+ 'payload.previousRepositoryFullName',
96
+ ] as const;
97
+
98
+ const SCM_INSTALLATION_PATHS = [
99
+ 'payload.installationId',
100
+ 'payload.action',
101
+ 'payload.accountLogin',
102
+ 'payload.affectedRepositoryFullNames',
103
+ ] as const;
104
+
105
+ // ── Tracker per-entityKind payload paths ──
106
+
107
+ const TRACKER_ITEM_PATHS = [
108
+ 'payload.title',
109
+ 'payload.description',
110
+ 'payload.type',
111
+ 'payload.status',
112
+ 'payload.priority',
113
+ 'payload.tags',
114
+ 'payload.ownerDomain',
115
+ ] as const;
116
+
117
+ const TRACKER_COMMENT_PATHS = [
118
+ 'payload.itemExternalId',
119
+ 'payload.content',
120
+ 'payload.authorId',
121
+ 'payload.authorType',
122
+ ] as const;
123
+
124
+ // ── Documentation per-entityKind payload paths ──
125
+
126
+ const DOC_PAGE_PATHS = [
127
+ 'payload.slug',
128
+ 'payload.title',
129
+ 'payload.content',
130
+ 'payload.contentType',
131
+ 'payload.externalParentId',
132
+ ] as const;
133
+
134
+ const DOC_SPACE_PATHS = [
135
+ 'payload.slug',
136
+ 'payload.title',
137
+ 'payload.description',
138
+ ] as const;
139
+
140
+ /**
141
+ * Per-`(adapterKind, entityKind)` allowed `$envelope.*` paths. The
142
+ * `'*'` entityKind entry is the union across every kind for that
143
+ * adapter — used when a filter omits `entityKind` (today's default).
144
+ */
145
+ const ENVELOPE_PATHS_BY_KIND_BY_ENTITY = new Map<
146
+ AdapterKindRef,
147
+ Map<string, ReadonlySet<string>>
148
+ >();
149
+
150
+ registerEnvelopeSchema(BuiltInAdapterKind.Scm, {
151
+ push: SCM_PUSH_PATHS,
152
+ change_request: SCM_CHANGE_REQUEST_PATHS,
153
+ issue: SCM_ISSUE_PATHS,
154
+ repository: SCM_REPOSITORY_PATHS,
155
+ installation: SCM_INSTALLATION_PATHS,
156
+ });
157
+
158
+ registerEnvelopeSchema(BuiltInAdapterKind.Tracker, {
159
+ item: TRACKER_ITEM_PATHS,
160
+ comment: TRACKER_COMMENT_PATHS,
161
+ });
162
+
163
+ registerEnvelopeSchema(BuiltInAdapterKind.Documentation, {
164
+ page: DOC_PAGE_PATHS,
165
+ space: DOC_SPACE_PATHS,
166
+ });
167
+
168
+ /**
169
+ * Register the per-entityKind permitted `$envelope.*` paths for a
170
+ * biome-contributed AdapterKind (Phase 7). Built-in kinds are pre-
171
+ * registered above. Re-registering an existing kind REPLACES its
172
+ * entry set — `integration-adapters-api`'s registry is the authority,
173
+ * so biome upgrades surface here.
174
+ *
175
+ * Each entry in `perEntityKind` lists the payload paths (without the
176
+ * `$envelope.` prefix, without the base envelope fields — those are
177
+ * implicitly included). The `'*'` union entry is derived automatically.
178
+ */
179
+ export function registerEnvelopeSchema(
180
+ adapterKind: AdapterKindRef,
181
+ perEntityKind: Readonly<Record<string, readonly string[]>>,
182
+ ): void {
183
+ const perEntity = new Map<string, ReadonlySet<string>>();
184
+ const unionSet = new Set<string>(BASE_ENVELOPE_PATHS);
185
+ for (const [entityKind, paths] of Object.entries(perEntityKind)) {
186
+ const withBase = new Set<string>([...BASE_ENVELOPE_PATHS, ...paths]);
187
+ perEntity.set(entityKind, withBase);
188
+ for (const path of paths) unionSet.add(path);
189
+ }
190
+ perEntity.set(UNION_ENTITY_KIND, unionSet);
191
+ ENVELOPE_PATHS_BY_KIND_BY_ENTITY.set(adapterKind, perEntity);
192
+ }
193
+
194
+ /**
195
+ * Returns the set of permitted `$envelope.*` paths for the given
196
+ * `(adapterKind, entityKind)`. `entityKind === undefined` means
197
+ * "union across every entity kind under this adapter".
198
+ *
199
+ * `undefined` return: the adapter kind isn't registered (biome-
200
+ * contributed kind whose adapter hasn't loaded yet) — callers should
201
+ * skip validation rather than fail.
202
+ */
203
+ export function getEnvelopeSchema(
204
+ adapterKind: AdapterKindRef,
205
+ entityKind?: string,
206
+ ): ReadonlySet<string> | undefined {
207
+ const perEntity = ENVELOPE_PATHS_BY_KIND_BY_ENTITY.get(adapterKind);
208
+ if (!perEntity) return undefined;
209
+ return perEntity.get(entityKind ?? UNION_ENTITY_KIND);
210
+ }
211
+
212
+ /**
213
+ * True iff `path` is a permitted reference under `$envelope.*` for
214
+ * the given `(adapterKind, entityKind)`. Numeric path segments
215
+ * (array indices) are normalized before lookup —
216
+ * `payload.commits.0.sha` matches `payload.commits.sha`.
217
+ *
218
+ * When `entityKind` is omitted, validates against the union across
219
+ * every entity kind for the adapter.
220
+ *
221
+ * Returns `true` when the adapter kind is unregistered OR when an
222
+ * `entityKind` is passed but the registered schema doesn't know it —
223
+ * biome-contributed kinds without a loaded schema don't break
224
+ * validation (the cross-validator surfaces the missing-schema case
225
+ * separately).
226
+ */
227
+ export function isAllowedEnvelopePath(
228
+ adapterKind: AdapterKindRef,
229
+ path: string,
230
+ entityKind?: string,
231
+ ): boolean {
232
+ const schema = getEnvelopeSchema(adapterKind, entityKind);
233
+ if (!schema) {
234
+ // Either the adapter kind isn't registered, or the registered
235
+ // schema doesn't recognize the entityKind. Either way, fall back
236
+ // to the union (if any) so an unknown entityKind doesn't bomb.
237
+ if (entityKind !== undefined) {
238
+ const unionFallback = getEnvelopeSchema(adapterKind);
239
+ if (unionFallback) return unionFallback.has(normalizeEnvelopePath(path));
240
+ }
241
+ return true;
242
+ }
243
+ return schema.has(normalizeEnvelopePath(path));
244
+ }
245
+
246
+ /**
247
+ * Strip numeric-index segments from a dot-delimited path so the
248
+ * schema lookup sees the structural shape. `commits.0.sha` →
249
+ * `commits.sha`.
250
+ */
251
+ function normalizeEnvelopePath(path: string): string {
252
+ return path
253
+ .split('.')
254
+ .filter((segment) => !/^\d+$/.test(segment))
255
+ .join('.');
256
+ }