@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,75 @@
1
+ import { z } from 'zod';
2
+
3
+ import type { FilterExpr } from './filter-expr';
4
+
5
+ /**
6
+ * Zod schema for the closed `FilterExpr` grammar. Used by biome-host-sdk
7
+ * at manifest parse time and by the workflow-engine when persisting the
8
+ * compiled filter bundle on `WorkflowDefinition`. Recursive shape is
9
+ * spelled with `z.lazy` so the leaf operators reference the union itself.
10
+ */
11
+ const PathRefSchema = z
12
+ .object({
13
+ source: z.enum(['$selector', '$envelope']),
14
+ path: z.string().min(1),
15
+ })
16
+ .strict();
17
+
18
+ const LiteralRefSchema = z
19
+ .object({
20
+ kind: z.literal('lit'),
21
+ value: z.union([z.string(), z.number(), z.boolean(), z.null()]),
22
+ })
23
+ .strict();
24
+
25
+ const ValueRefSchema = z.union([PathRefSchema, LiteralRefSchema]);
26
+
27
+ export const FilterExprSchema: z.ZodType<FilterExpr> = z.lazy(() =>
28
+ z.union([
29
+ z
30
+ .object({
31
+ op: z.literal('and'),
32
+ items: z.array(FilterExprSchema).min(1),
33
+ })
34
+ .strict(),
35
+ z
36
+ .object({
37
+ op: z.literal('or'),
38
+ items: z.array(FilterExprSchema).min(1),
39
+ })
40
+ .strict(),
41
+ z
42
+ .object({
43
+ op: z.literal('not'),
44
+ item: FilterExprSchema,
45
+ })
46
+ .strict(),
47
+ z
48
+ .object({
49
+ op: z.literal('eq'),
50
+ left: ValueRefSchema,
51
+ right: ValueRefSchema,
52
+ })
53
+ .strict(),
54
+ z
55
+ .object({
56
+ op: z.literal('in'),
57
+ left: ValueRefSchema,
58
+ right: PathRefSchema,
59
+ })
60
+ .strict(),
61
+ z
62
+ .object({
63
+ op: z.literal('matches'),
64
+ left: ValueRefSchema,
65
+ pattern: z.string().min(1).max(256),
66
+ })
67
+ .strict(),
68
+ z
69
+ .object({
70
+ op: z.literal('exists'),
71
+ left: PathRefSchema,
72
+ })
73
+ .strict(),
74
+ ]),
75
+ );
@@ -0,0 +1,91 @@
1
+ import type { AdapterKindRef } from './adapter-kind';
2
+ import { isAllowedEnvelopePath } from './envelope-schema';
3
+ import { type FilterExpr, type PathRef } from './filter-expr';
4
+
5
+ /**
6
+ * Walk a `FilterExpr` AST and return every `PathRef` it references.
7
+ * Pure traversal; no schema lookup. Callers pair the output with
8
+ * `isAllowedEnvelopePath` (per AdapterKind) to validate references
9
+ * statically — at biome-manifest cross-validation time, not at
10
+ * dispatch.
11
+ */
12
+ export function collectFilterExprPathRefs(expr: FilterExpr): PathRef[] {
13
+ const out: PathRef[] = [];
14
+ walk(expr, out);
15
+ return out;
16
+ }
17
+
18
+ function walk(expr: FilterExpr, out: PathRef[]): void {
19
+ switch (expr.op) {
20
+ case 'and':
21
+ case 'or':
22
+ for (const item of expr.items) walk(item, out);
23
+ return;
24
+ case 'not':
25
+ walk(expr.item, out);
26
+ return;
27
+ case 'eq':
28
+ pushIfPathRef(expr.left, out);
29
+ pushIfPathRef(expr.right, out);
30
+ return;
31
+ case 'in':
32
+ pushIfPathRef(expr.left, out);
33
+ out.push(expr.right);
34
+ return;
35
+ case 'matches':
36
+ pushIfPathRef(expr.left, out);
37
+ return;
38
+ case 'exists':
39
+ out.push(expr.left);
40
+ return;
41
+ }
42
+ }
43
+
44
+ function pushIfPathRef(ref: { source?: string; path?: string; kind?: string }, out: PathRef[]): void {
45
+ if (ref.kind === 'lit') return;
46
+ out.push(ref as PathRef);
47
+ }
48
+
49
+ export interface FilterExprPathIssue {
50
+ readonly path: string;
51
+ readonly source: '$envelope' | '$selector';
52
+ readonly reason: string;
53
+ }
54
+
55
+ /**
56
+ * Statically validate that every `$envelope.*` path the predicate
57
+ * references is permitted by the canonical envelope schema for
58
+ * `(adapterKind, entityKind)`. `$selector` paths are NOT validated
59
+ * here — selectors are opaque-by-design (Phase 3 lock-in): their
60
+ * shape is governed by the biome's install JSON Schema, not by a
61
+ * kernel-level path map.
62
+ *
63
+ * `entityKind` narrows the check to a single entity kind's payload
64
+ * shape (e.g. `push` rejects `payload.title` even though the union
65
+ * schema for SCM accepts it). Pass `undefined` to validate against
66
+ * the union across every entity kind under the adapter — the
67
+ * compatible behaviour for manifests authored before the manifest
68
+ * gained `webhookFilters[].entityKind`.
69
+ *
70
+ * Returns the list of offending references, empty on success. Callers
71
+ * fail fast on a non-empty list (biome-host boot, manifest publish).
72
+ */
73
+ export function validateFilterExprPaths(
74
+ expr: FilterExpr,
75
+ adapterKind: AdapterKindRef,
76
+ entityKind?: string,
77
+ ): FilterExprPathIssue[] {
78
+ const issues: FilterExprPathIssue[] = [];
79
+ const scopeLabel = entityKind ? `${adapterKind}/${entityKind}` : adapterKind;
80
+ for (const ref of collectFilterExprPathRefs(expr)) {
81
+ if (ref.source !== '$envelope') continue;
82
+ if (!isAllowedEnvelopePath(adapterKind, ref.path, entityKind)) {
83
+ issues.push({
84
+ path: ref.path,
85
+ source: ref.source,
86
+ reason: `not a known $envelope path for adapterKind="${scopeLabel}"`,
87
+ });
88
+ }
89
+ }
90
+ return issues;
91
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Closed-grammar filter expression for biome webhook routing.
3
+ *
4
+ * Biomes declare predicates in their manifest as a structured AST.
5
+ * The dispatcher evaluates them against `(selector, envelope)` pairs
6
+ * at webhook dispatch time. The grammar is intentionally tiny: no
7
+ * function calls, no arithmetic, no user-provided code — only what is
8
+ * needed to express "envelope.branch in selector.branches.values" and
9
+ * its kin. Adding an operator is a one-line union extension here plus
10
+ * a matching evaluator branch.
11
+ */
12
+
13
+ /**
14
+ * Path reference rooted at one of two well-known scopes:
15
+ * - `$selector` resolves against the `BiomeInstallationResource.selector`
16
+ * JSON the user submitted at install time (validated by the biome's
17
+ * install JSON Schema).
18
+ * - `$envelope` resolves against the canonical webhook envelope's
19
+ * payload (typed per AdapterKind by the owning domain service).
20
+ *
21
+ * `path` is dot-delimited; numeric segments index into arrays.
22
+ * Unknown segments resolve to `undefined`, which `eq`/`in`/`matches`
23
+ * treat as a non-match (never an error). `exists` is the explicit way
24
+ * to test for presence.
25
+ */
26
+ export interface PathRef {
27
+ readonly source: '$selector' | '$envelope';
28
+ readonly path: string;
29
+ }
30
+
31
+ export interface LiteralRef {
32
+ readonly kind: 'lit';
33
+ readonly value: string | number | boolean | null;
34
+ }
35
+
36
+ export type ValueRef = PathRef | LiteralRef;
37
+
38
+ export type FilterExpr =
39
+ | { readonly op: 'and'; readonly items: readonly FilterExpr[] }
40
+ | { readonly op: 'or'; readonly items: readonly FilterExpr[] }
41
+ | { readonly op: 'not'; readonly item: FilterExpr }
42
+ | { readonly op: 'eq'; readonly left: ValueRef; readonly right: ValueRef }
43
+ | { readonly op: 'in'; readonly left: ValueRef; readonly right: PathRef }
44
+ | { readonly op: 'matches'; readonly left: ValueRef; readonly pattern: string }
45
+ | { readonly op: 'exists'; readonly left: PathRef };
46
+
47
+ export type FilterExprOp = FilterExpr['op'];
48
+
49
+ export const FILTER_EXPR_OPS: readonly FilterExprOp[] = [
50
+ 'and',
51
+ 'or',
52
+ 'not',
53
+ 'eq',
54
+ 'in',
55
+ 'matches',
56
+ 'exists',
57
+ ];
58
+
59
+ export class FilterExprEvaluationError extends Error {
60
+ constructor(message: string) {
61
+ super(message);
62
+ this.name = 'FilterExprEvaluationError';
63
+ }
64
+ }
65
+
66
+ export class FilterExprParseError extends Error {
67
+ constructor(message: string) {
68
+ super(message);
69
+ this.name = 'FilterExprParseError';
70
+ }
71
+ }
72
+
73
+ interface EvaluateContext {
74
+ readonly selector: unknown;
75
+ readonly envelope: unknown;
76
+ }
77
+
78
+ /**
79
+ * Pure evaluator. No I/O, no exceptions on missing fields — only
80
+ * structural / type errors throw `FilterExprEvaluationError`. Callers
81
+ * that want fail-fast on unknown paths should pair this with
82
+ * `validateFilterExpr` at compile time against the AdapterKind schema.
83
+ */
84
+ export function evaluateFilterExpr(expr: FilterExpr, ctx: EvaluateContext): boolean {
85
+ switch (expr.op) {
86
+ case 'and':
87
+ for (const item of expr.items) {
88
+ if (!evaluateFilterExpr(item, ctx)) return false;
89
+ }
90
+ return true;
91
+
92
+ case 'or':
93
+ for (const item of expr.items) {
94
+ if (evaluateFilterExpr(item, ctx)) return true;
95
+ }
96
+ return false;
97
+
98
+ case 'not':
99
+ return !evaluateFilterExpr(expr.item, ctx);
100
+
101
+ case 'eq': {
102
+ const left = resolveValue(expr.left, ctx);
103
+ const right = resolveValue(expr.right, ctx);
104
+ return scalarEqual(left, right);
105
+ }
106
+
107
+ case 'in': {
108
+ const left = resolveValue(expr.left, ctx);
109
+ const right = resolveValue(expr.right, ctx);
110
+ if (right === undefined || right === null) return false;
111
+ if (!Array.isArray(right)) {
112
+ throw new FilterExprEvaluationError(
113
+ `'in' right-hand side at ${expr.right.source}.${expr.right.path} must resolve to an array`,
114
+ );
115
+ }
116
+ return right.some((entry) => scalarEqual(left, entry));
117
+ }
118
+
119
+ case 'matches': {
120
+ const left = resolveValue(expr.left, ctx);
121
+ if (typeof left !== 'string') return false;
122
+ const re = compileRegex(expr.pattern);
123
+ return re.test(left);
124
+ }
125
+
126
+ case 'exists': {
127
+ const value = resolveValue(expr.left, ctx);
128
+ return value !== undefined;
129
+ }
130
+
131
+ default: {
132
+ const _exhaustive: never = expr;
133
+ throw new FilterExprEvaluationError(
134
+ `Unknown FilterExpr op: ${(_exhaustive as { op: string }).op}`,
135
+ );
136
+ }
137
+ }
138
+ }
139
+
140
+ function resolveValue(ref: ValueRef, ctx: EvaluateContext): unknown {
141
+ if (isLiteralRef(ref)) {
142
+ return ref.value;
143
+ }
144
+ const root = ref.source === '$selector' ? ctx.selector : ctx.envelope;
145
+ return resolvePath(root, ref.path);
146
+ }
147
+
148
+ function isLiteralRef(ref: ValueRef): ref is LiteralRef {
149
+ return (ref as LiteralRef).kind === 'lit';
150
+ }
151
+
152
+ function resolvePath(root: unknown, path: string): unknown {
153
+ if (root === undefined || root === null) return undefined;
154
+ if (path === '' || path === '.') return root;
155
+ const segments = path.split('.');
156
+ let current: unknown = root;
157
+ for (const segment of segments) {
158
+ if (current === undefined || current === null) return undefined;
159
+ if (Array.isArray(current)) {
160
+ const index = Number(segment);
161
+ if (!Number.isInteger(index) || index < 0) return undefined;
162
+ current = current[index];
163
+ continue;
164
+ }
165
+ if (typeof current !== 'object') return undefined;
166
+ current = (current as Record<string, unknown>)[segment];
167
+ }
168
+ return current;
169
+ }
170
+
171
+ function scalarEqual(a: unknown, b: unknown): boolean {
172
+ if (a === b) return true;
173
+ // Treat the JSON null and undefined as distinct, but accept loose
174
+ // string/number equality only when both are primitives of the same
175
+ // type. No implicit coercion across types — too footgun-prone.
176
+ return false;
177
+ }
178
+
179
+ /**
180
+ * Compile and cache the user-supplied regex. Anchored is up to the
181
+ * author. We disallow lookbehind (Safari/JSC compatibility) and put a
182
+ * hard ceiling on pattern length to prevent ReDoS-prone input. This
183
+ * is *not* a full safe-regex engine — adopt RE2 if/when we need that.
184
+ */
185
+ const REGEX_CACHE = new Map<string, RegExp>();
186
+ const REGEX_MAX_LEN = 256;
187
+
188
+ function compileRegex(pattern: string): RegExp {
189
+ const cached = REGEX_CACHE.get(pattern);
190
+ if (cached) return cached;
191
+ if (pattern.length > REGEX_MAX_LEN) {
192
+ throw new FilterExprEvaluationError(
193
+ `regex pattern exceeds ${REGEX_MAX_LEN} characters`,
194
+ );
195
+ }
196
+ if (/\(\?<[!=]/.test(pattern)) {
197
+ throw new FilterExprEvaluationError('regex lookbehind is not supported');
198
+ }
199
+ try {
200
+ const re = new RegExp(pattern);
201
+ REGEX_CACHE.set(pattern, re);
202
+ return re;
203
+ } catch (cause) {
204
+ throw new FilterExprEvaluationError(
205
+ `invalid regex pattern: ${(cause as Error).message}`,
206
+ );
207
+ }
208
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * ─────────────────────────────────────────────────────────────────────────
3
+ * Provider onboarding manifest — install-wizard UX contract
4
+ *
5
+ * Each `IntegrationProviderModule` declares an `onboarding` manifest so the
6
+ * frontend can render the "Connect <provider>" surface generically from the
7
+ * registry instead of carrying a hardcoded provider catalogue.
8
+ *
9
+ * These types are **runtime contract enums** — they describe the UI shape
10
+ * a provider exposes, they are never persisted. There is therefore no
11
+ * Prisma mirror to keep in sync (parity-script `ConnectorKind` /
12
+ * `AdapterKey` parity is unrelated — those enums are stored on
13
+ * `OrgIntegrationCredential` / `IntegrationAdapter` rows; these aren't).
14
+ *
15
+ * Owned here (kernel `integration-contracts`) because every consumer of
16
+ * the integration domain — the platform service, the install-wizard
17
+ * frontend, the future biome-host-sdk validator — needs the same
18
+ * vocabulary. Keeping it next to `CredentialKind` keeps the integration
19
+ * contract surface in one place.
20
+ * ─────────────────────────────────────────────────────────────────────────
21
+ */
22
+
23
+ /**
24
+ * Closed set of credential-field input types the install wizard renders.
25
+ * Maps 1:1 onto HTML input affordances; extending requires both a backend
26
+ * declaration AND a frontend renderer update.
27
+ */
28
+ export enum CredentialFieldType {
29
+ TEXT = 'TEXT',
30
+ PASSWORD = 'PASSWORD',
31
+ EMAIL = 'EMAIL',
32
+ URL = 'URL',
33
+ JSON_BLOB = 'JSON_BLOB',
34
+ }
35
+
36
+ /**
37
+ * Closed set of normalization transforms applied to a credential field's
38
+ * value before submission. Pure deterministic string→string ops only —
39
+ * no field-specific business logic; that lives in the credential
40
+ * strategy.
41
+ */
42
+ export enum CredentialFieldTransform {
43
+ NONE = 'NONE',
44
+ UPPERCASE = 'UPPERCASE',
45
+ LOWERCASE = 'LOWERCASE',
46
+ TRIM = 'TRIM',
47
+ }
48
+
49
+ /**
50
+ * Closed set describing how a provider is connected:
51
+ * - `CREDENTIALS` — the wizard collects a credential blob (fields or
52
+ * free-form JSON) and posts it to the org-integration bootstrap.
53
+ * - `APP_INSTALL` — the wizard launches an external installation flow
54
+ * (GitHub App, GitLab App, Atlassian Connect, …). The `launchUrl`
55
+ * itself is per-org and is returned by the existing bootstrap
56
+ * endpoint — the manifest only declares the button copy.
57
+ */
58
+ export enum IntegrationOnboardingKind {
59
+ CREDENTIALS = 'CREDENTIALS',
60
+ APP_INSTALL = 'APP_INSTALL',
61
+ }
62
+
63
+ /**
64
+ * Closed set of project-binding adapter kinds a provider may attach to
65
+ * at the project level. Mirrors `BuiltInAdapterKind` but uses uppercase
66
+ * wire values so the install-wizard and project Bind dialog can render
67
+ * stable, frontend-friendly enum literals without re-deriving casing.
68
+ *
69
+ * This is a **runtime contract enum** — same parity stance as
70
+ * `CredentialFieldType` / `IntegrationOnboardingKind`: it shapes UI
71
+ * surfaces only and is never persisted, so there is no Prisma mirror to
72
+ * keep in sync. Persisted adapter-kind data continues to use
73
+ * `BuiltInAdapterKind` (`scm` / `tracker` / `documentation`) on the
74
+ * `IntegrationAdapter` row.
75
+ *
76
+ * A single provider may declare ZERO or MORE of these. For example
77
+ * Atlassian binds to both `DOCUMENTATION` (Confluence) and `TRACKER`
78
+ * (Jira); Slack (messaging-only today) declares the empty set.
79
+ */
80
+ export enum ProjectBindingAdapterKey {
81
+ DOCUMENTATION = 'DOCUMENTATION',
82
+ TRACKER = 'TRACKER',
83
+ SCM = 'SCM',
84
+ }
85
+
86
+ /**
87
+ * Declaration of a single credential field the install wizard should
88
+ * render. The `key` is a dot-path applied to the credential blob the
89
+ * frontend POSTs; strategies on the backend read the same path.
90
+ */
91
+ export interface CredentialFieldSpec {
92
+ /** Dot-path key the wizard puts the value under in the credential blob. */
93
+ readonly key: string;
94
+ /** Human-readable label for the input. */
95
+ readonly label: string;
96
+ /** Input affordance the wizard renders. */
97
+ readonly type: CredentialFieldType;
98
+ /** When true, the wizard refuses submission unless the field is filled. */
99
+ readonly required: boolean;
100
+ /** Optional placeholder copy. */
101
+ readonly placeholder?: string;
102
+ /** Optional secondary hint shown beneath the input. */
103
+ readonly hint?: string;
104
+ /** Normalization transform applied to the value before submission. */
105
+ readonly transform: CredentialFieldTransform;
106
+ }
107
+
108
+ /**
109
+ * Provider-declared onboarding metadata returned by
110
+ * `GET /adapters/providers`. The frontend renders the install surface
111
+ * from this object alone — no PROVIDER_INFO map.
112
+ *
113
+ * The shape is a tagged union over `kind`:
114
+ * - `CREDENTIALS` providers carry `fields` / `hint` / `jsonPlaceholder`;
115
+ * - `APP_INSTALL` providers carry `launchLabel` / `launchHint`.
116
+ * Per-org `launchUrl`s are NOT on the manifest — they stay on the
117
+ * org-integration bootstrap endpoint because they encode org-scoped
118
+ * state.
119
+ */
120
+ export interface ProviderOnboardingManifest {
121
+ /** Provider slug (same as `IntegrationProviderModule.provider`). */
122
+ readonly provider: string;
123
+ /** Human-readable provider name (e.g. `GitHub`, `Atlassian Cloud`). */
124
+ readonly displayName: string;
125
+ /** One-sentence description shown beneath the provider name. */
126
+ readonly description: string;
127
+ /**
128
+ * Lucide-react icon name (e.g. `Globe`, `BookOpen`). The frontend maps
129
+ * the name to a concrete component; the backend never imports icon
130
+ * code.
131
+ */
132
+ readonly iconName: string;
133
+ /** Discriminator. */
134
+ readonly kind: IntegrationOnboardingKind;
135
+
136
+ /**
137
+ * Closed set of project-binding adapter kinds this provider supports
138
+ * at the project level. The project Bind dialog uses this list to
139
+ * decide which binding rows to offer for the provider — e.g.
140
+ * Atlassian → `[DOCUMENTATION, TRACKER]`, GitHub → `[SCM]`,
141
+ * messaging-only providers → `[]`.
142
+ *
143
+ * Empty array = the provider has no project-level bindings today
144
+ * (still connectable at the org level, but the project Bind dialog
145
+ * hides it). Authoring it as an explicit `[]` instead of `undefined`
146
+ * keeps the contract closed — every provider declares its surface.
147
+ */
148
+ readonly supportedProjectBindingAdapterKinds: readonly ProjectBindingAdapterKey[];
149
+
150
+ // ── CREDENTIALS-only ──
151
+ /** Field-by-field credential form spec. Required when `kind = CREDENTIALS`. */
152
+ readonly fields?: readonly CredentialFieldSpec[];
153
+ /** Hint shown above the credential form. */
154
+ readonly hint?: string;
155
+ /**
156
+ * Pretty-printed JSON placeholder for providers that accept a raw JSON
157
+ * credential blob (when no `fields` are declared the frontend falls
158
+ * back to a JSON textarea using this template).
159
+ */
160
+ readonly jsonPlaceholder?: string;
161
+
162
+ // ── APP_INSTALL-only ──
163
+ /** Copy for the launch button (e.g. `Install GitHub App`). */
164
+ readonly launchLabel?: string;
165
+ /** Hint shown next to / under the launch button. */
166
+ readonly launchHint?: string;
167
+ }
@@ -0,0 +1,25 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // @xemahq/document-render-contracts — Kernel layer
3
+ //
4
+ // Wire contracts for the generic Xema-wide document render service
5
+ // (`biomes/document-rendering/api/document-render-api`). Used by every caller that wants a
6
+ // renderable artifact (PDF, DOCX) from a source the service knows how to
7
+ // fetch — KB pages, brainstorming exports, workflow deliverables, or
8
+ // inline HTML.
9
+ //
10
+ // The service is deliberately format/source-agnostic at this contract
11
+ // surface: source adapters fan out at the service edge, and the queue
12
+ // (backed by Temporal workflows + a Playwright worker pool) is shared.
13
+ // Adding a new source kind or format is a closed-enum extension here +
14
+ // an adapter behind the service — no caller change required.
15
+ //
16
+ // Pure types + Zod. Zero runtime adapter knowledge.
17
+ // ═══════════════════════════════════════════════════════════════════════════
18
+
19
+ export * from './lib/render-enums';
20
+ export * from './lib/render-source';
21
+ export * from './lib/render-request';
22
+ export * from './lib/render-record';
23
+ export * from './lib/measure-layout';
24
+ export * from './lib/xema-prompt';
25
+
@@ -0,0 +1,61 @@
1
+ import { z } from 'zod';
2
+
3
+ import { RenderSourceSchema } from './render-source';
4
+
5
+ /**
6
+ * "Measure mode" of the render service: run the same Paged.js pipeline
7
+ * but skip PDF generation and return layout metrics instead. Sub-second
8
+ * latency on a warm browser context, so the document agent can call
9
+ * `xema/document.page_metrics` / `outline` / `simulate_insert` cheaply
10
+ * during composition.
11
+ *
12
+ * `inserts` lets the agent ask "what would the layout look like if I put
13
+ * THIS HTML at THIS section?" without actually mutating the document.
14
+ */
15
+ export const MeasureLayoutRequestSchema = z.object({
16
+ source: RenderSourceSchema,
17
+ inserts: z
18
+ .array(
19
+ z.object({
20
+ /** Section path the agent received from a prior outline call. */
21
+ atSectionPath: z.string().min(1),
22
+ /** HTML fragment (rich docs) or markdown fragment (markdown docs). */
23
+ fragment: z.string().min(1).max(500_000),
24
+ }),
25
+ )
26
+ .max(20)
27
+ .optional(),
28
+ });
29
+ export type MeasureLayoutRequestDto = z.infer<typeof MeasureLayoutRequestSchema>;
30
+
31
+ /**
32
+ * Aggregate layout metrics for the rendered document. `density` is a
33
+ * 0–100 percent estimate of how full the current page is, so the agent
34
+ * can pace content without guessing.
35
+ */
36
+ export interface PageLayoutMetricsDto {
37
+ readonly pageCount: number;
38
+ readonly currentPageIndex: number;
39
+ readonly currentPageRemainingMm: number;
40
+ readonly totalContentHeightMm: number;
41
+ readonly densityPercent: number;
42
+ }
43
+
44
+ /**
45
+ * One row of the rendered outline. `sectionPath` is the canonical
46
+ * agent-addressable handle (the agent passes it back to
47
+ * `simulate_insert`).
48
+ */
49
+ export interface DocumentOutlineEntryDto {
50
+ readonly pageIndex: number;
51
+ readonly sectionPath: string;
52
+ readonly headingText: string;
53
+ readonly headingLevel: number;
54
+ readonly yMm: number;
55
+ readonly heightMm: number;
56
+ }
57
+
58
+ export interface MeasureLayoutResponseDto {
59
+ readonly metrics: PageLayoutMetricsDto;
60
+ readonly outline: ReadonlyArray<DocumentOutlineEntryDto>;
61
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Closed enums for the render service wire. Real TS enums (not
3
+ * string-literal unions) so OpenAPI/Orval emit stable enum schemas — see
4
+ * `docs/API_STANDARDS.md` and `.claude/rules/backend.md`.
5
+ */
6
+
7
+ /**
8
+ * Output file format.
9
+ *
10
+ * - PDF — high-fidelity Paged.js → Chromium → page.pdf() pipeline.
11
+ * Pixel-faithful to the on-screen preview.
12
+ * - DOCX — best-effort Pandoc pipeline. UI surfaces this as
13
+ * "structured export — formatting may differ" because DOCX
14
+ * has no CSS box model.
15
+ */
16
+ export enum RenderFormat {
17
+ PDF = 'PDF',
18
+ DOCX = 'DOCX',
19
+ }
20
+
21
+ /**
22
+ * Lifecycle status for a single render record.
23
+ *
24
+ * - QUEUED — accepted, awaiting a worker.
25
+ * - RUNNING — a worker is actively rendering.
26
+ * - READY — output uploaded, `downloadUrl` populated (terminal).
27
+ * - FAILED — render or upload failed; `failureReason` populated
28
+ * (terminal).
29
+ * - CANCELLED — caller cancelled before completion (terminal).
30
+ */
31
+ export enum RenderStatus {
32
+ QUEUED = 'QUEUED',
33
+ RUNNING = 'RUNNING',
34
+ READY = 'READY',
35
+ FAILED = 'FAILED',
36
+ CANCELLED = 'CANCELLED',
37
+ }
38
+
39
+ /**
40
+ * What kind of thing the source-resolution layer should fetch.
41
+ * Adding a new kind is a closed extension + a new adapter inside the
42
+ * render service.
43
+ */
44
+ export enum RenderSourceKind {
45
+ PAGE = 'PAGE',
46
+ DESIGN_SYSTEM_BUILDER_EXPORT = 'DESIGN_SYSTEM_BUILDER_EXPORT',
47
+ WORKFLOW_DELIVERABLE = 'WORKFLOW_DELIVERABLE',
48
+ INLINE_HTML = 'INLINE_HTML',
49
+ }