@xemahq/kernel-contracts 0.28.0 → 0.30.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 (151) hide show
  1. package/dist/document-patch/index.d.ts +4 -0
  2. package/dist/document-patch/index.d.ts.map +1 -0
  3. package/dist/document-patch/index.js +20 -0
  4. package/dist/document-patch/index.js.map +1 -0
  5. package/dist/document-patch/lib/patch-anchor.d.ts +7 -0
  6. package/dist/document-patch/lib/patch-anchor.d.ts.map +1 -0
  7. package/dist/document-patch/lib/patch-anchor.js +14 -0
  8. package/dist/document-patch/lib/patch-anchor.js.map +1 -0
  9. package/dist/document-patch/lib/patch-enums.d.ts +11 -0
  10. package/dist/document-patch/lib/patch-enums.d.ts.map +1 -0
  11. package/dist/document-patch/lib/patch-enums.js +16 -0
  12. package/dist/document-patch/lib/patch-enums.js.map +1 -0
  13. package/dist/document-patch/lib/pending-patch.d.ts +22 -0
  14. package/dist/document-patch/lib/pending-patch.d.ts.map +1 -0
  15. package/dist/document-patch/lib/pending-patch.js +3 -0
  16. package/dist/document-patch/lib/pending-patch.js.map +1 -0
  17. package/dist/output/index.d.ts +7 -0
  18. package/dist/output/index.d.ts.map +1 -0
  19. package/dist/output/index.js +23 -0
  20. package/dist/output/index.js.map +1 -0
  21. package/dist/output/lib/output-deliverable-expectation.d.ts +9 -0
  22. package/dist/output/lib/output-deliverable-expectation.d.ts.map +1 -0
  23. package/dist/output/lib/output-deliverable-expectation.js +3 -0
  24. package/dist/output/lib/output-deliverable-expectation.js.map +1 -0
  25. package/dist/output/lib/output-item-dto.d.ts +25 -0
  26. package/dist/output/lib/output-item-dto.d.ts.map +1 -0
  27. package/dist/output/lib/output-item-dto.js +3 -0
  28. package/dist/output/lib/output-item-dto.js.map +1 -0
  29. package/dist/output/lib/output-kind.d.ts +14 -0
  30. package/dist/output/lib/output-kind.d.ts.map +1 -0
  31. package/dist/output/lib/output-kind.js +18 -0
  32. package/dist/output/lib/output-kind.js.map +1 -0
  33. package/dist/output/lib/output-render-hint.d.ts +11 -0
  34. package/dist/output/lib/output-render-hint.d.ts.map +1 -0
  35. package/dist/output/lib/output-render-hint.js +10 -0
  36. package/dist/output/lib/output-render-hint.js.map +1 -0
  37. package/dist/output/lib/output-version-dto.d.ts +10 -0
  38. package/dist/output/lib/output-version-dto.d.ts.map +1 -0
  39. package/dist/output/lib/output-version-dto.js +3 -0
  40. package/dist/output/lib/output-version-dto.js.map +1 -0
  41. package/dist/output/lib/payload-schemas/code-diff.d.ts +7 -0
  42. package/dist/output/lib/payload-schemas/code-diff.d.ts.map +1 -0
  43. package/dist/output/lib/payload-schemas/code-diff.js +11 -0
  44. package/dist/output/lib/payload-schemas/code-diff.js.map +1 -0
  45. package/dist/output/lib/payload-schemas/decision-record.d.ts +19 -0
  46. package/dist/output/lib/payload-schemas/decision-record.d.ts.map +1 -0
  47. package/dist/output/lib/payload-schemas/decision-record.js +39 -0
  48. package/dist/output/lib/payload-schemas/decision-record.js.map +1 -0
  49. package/dist/output/lib/payload-schemas/diagram.d.ts +12 -0
  50. package/dist/output/lib/payload-schemas/diagram.d.ts.map +1 -0
  51. package/dist/output/lib/payload-schemas/diagram.js +34 -0
  52. package/dist/output/lib/payload-schemas/diagram.js.map +1 -0
  53. package/dist/output/lib/payload-schemas/external-blob.d.ts +9 -0
  54. package/dist/output/lib/payload-schemas/external-blob.d.ts.map +1 -0
  55. package/dist/output/lib/payload-schemas/external-blob.js +15 -0
  56. package/dist/output/lib/payload-schemas/external-blob.js.map +1 -0
  57. package/dist/output/lib/payload-schemas/index.d.ts +17 -0
  58. package/dist/output/lib/payload-schemas/index.d.ts.map +1 -0
  59. package/dist/output/lib/payload-schemas/index.js +94 -0
  60. package/dist/output/lib/payload-schemas/index.js.map +1 -0
  61. package/dist/output/lib/payload-schemas/json-payload.d.ts +4 -0
  62. package/dist/output/lib/payload-schemas/json-payload.d.ts.map +1 -0
  63. package/dist/output/lib/payload-schemas/json-payload.js +9 -0
  64. package/dist/output/lib/payload-schemas/json-payload.js.map +1 -0
  65. package/dist/output/lib/payload-schemas/manifest.d.ts +37 -0
  66. package/dist/output/lib/payload-schemas/manifest.d.ts.map +1 -0
  67. package/dist/output/lib/payload-schemas/manifest.js +43 -0
  68. package/dist/output/lib/payload-schemas/manifest.js.map +1 -0
  69. package/dist/output/lib/payload-schemas/markdown-doc.d.ts +8 -0
  70. package/dist/output/lib/payload-schemas/markdown-doc.d.ts.map +1 -0
  71. package/dist/output/lib/payload-schemas/markdown-doc.js +12 -0
  72. package/dist/output/lib/payload-schemas/markdown-doc.js.map +1 -0
  73. package/dist/output/lib/payload-schemas/review-findings.d.ts +30 -0
  74. package/dist/output/lib/payload-schemas/review-findings.d.ts.map +1 -0
  75. package/dist/output/lib/payload-schemas/review-findings.js +39 -0
  76. package/dist/output/lib/payload-schemas/review-findings.js.map +1 -0
  77. package/dist/output/lib/payload-schemas/schema.d.ts +4 -0
  78. package/dist/output/lib/payload-schemas/schema.d.ts.map +1 -0
  79. package/dist/output/lib/payload-schemas/schema.js +10 -0
  80. package/dist/output/lib/payload-schemas/schema.js.map +1 -0
  81. package/dist/output/lib/payload-schemas/test-report.d.ts +33 -0
  82. package/dist/output/lib/payload-schemas/test-report.d.ts.map +1 -0
  83. package/dist/output/lib/payload-schemas/test-report.js +46 -0
  84. package/dist/output/lib/payload-schemas/test-report.js.map +1 -0
  85. package/dist/output-surface-inspect/index.d.ts +3 -0
  86. package/dist/output-surface-inspect/index.d.ts.map +1 -0
  87. package/dist/output-surface-inspect/index.js +19 -0
  88. package/dist/output-surface-inspect/index.js.map +1 -0
  89. package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts +226 -0
  90. package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts.map +1 -0
  91. package/dist/output-surface-inspect/lib/output-surface-inspect.js +85 -0
  92. package/dist/output-surface-inspect/lib/output-surface-inspect.js.map +1 -0
  93. package/dist/output-surface-inspect/lib/step-schema.d.ts +64 -0
  94. package/dist/output-surface-inspect/lib/step-schema.d.ts.map +1 -0
  95. package/dist/output-surface-inspect/lib/step-schema.js +73 -0
  96. package/dist/output-surface-inspect/lib/step-schema.js.map +1 -0
  97. package/dist/output-surface-inspect/runtime/index.d.ts +2 -0
  98. package/dist/output-surface-inspect/runtime/index.d.ts.map +1 -0
  99. package/dist/output-surface-inspect/runtime/index.js +18 -0
  100. package/dist/output-surface-inspect/runtime/index.js.map +1 -0
  101. package/dist/workspace-image/index.d.ts +5 -0
  102. package/dist/workspace-image/index.d.ts.map +1 -0
  103. package/dist/workspace-image/index.js +21 -0
  104. package/dist/workspace-image/index.js.map +1 -0
  105. package/dist/workspace-image/lib/enums.d.ts +17 -0
  106. package/dist/workspace-image/lib/enums.d.ts.map +1 -0
  107. package/dist/workspace-image/lib/enums.js +22 -0
  108. package/dist/workspace-image/lib/enums.js.map +1 -0
  109. package/dist/workspace-image/lib/hash.d.ts +3 -0
  110. package/dist/workspace-image/lib/hash.d.ts.map +1 -0
  111. package/dist/workspace-image/lib/hash.js +50 -0
  112. package/dist/workspace-image/lib/hash.js.map +1 -0
  113. package/dist/workspace-image/lib/schemas.d.ts +103 -0
  114. package/dist/workspace-image/lib/schemas.d.ts.map +1 -0
  115. package/dist/workspace-image/lib/schemas.js +53 -0
  116. package/dist/workspace-image/lib/schemas.js.map +1 -0
  117. package/dist/workspace-image/lib/types.d.ts +50 -0
  118. package/dist/workspace-image/lib/types.d.ts.map +1 -0
  119. package/dist/workspace-image/lib/types.js +3 -0
  120. package/dist/workspace-image/lib/types.js.map +1 -0
  121. package/package.json +1 -1
  122. package/src/document-patch/index.ts +25 -0
  123. package/src/document-patch/lib/patch-anchor.ts +22 -0
  124. package/src/document-patch/lib/patch-enums.ts +36 -0
  125. package/src/document-patch/lib/pending-patch.ts +31 -0
  126. package/src/output/index.ts +20 -0
  127. package/src/output/lib/output-deliverable-expectation.ts +25 -0
  128. package/src/output/lib/output-item-dto.ts +54 -0
  129. package/src/output/lib/output-kind.ts +44 -0
  130. package/src/output/lib/output-render-hint.ts +28 -0
  131. package/src/output/lib/output-version-dto.ts +21 -0
  132. package/src/output/lib/payload-schemas/code-diff.ts +20 -0
  133. package/src/output/lib/payload-schemas/decision-record.ts +71 -0
  134. package/src/output/lib/payload-schemas/diagram.ts +54 -0
  135. package/src/output/lib/payload-schemas/external-blob.ts +36 -0
  136. package/src/output/lib/payload-schemas/index.ts +133 -0
  137. package/src/output/lib/payload-schemas/json-payload.ts +19 -0
  138. package/src/output/lib/payload-schemas/manifest.ts +81 -0
  139. package/src/output/lib/payload-schemas/markdown-doc.ts +33 -0
  140. package/src/output/lib/payload-schemas/review-findings.ts +75 -0
  141. package/src/output/lib/payload-schemas/schema.ts +22 -0
  142. package/src/output/lib/payload-schemas/test-report.ts +69 -0
  143. package/src/output-surface-inspect/index.ts +4 -0
  144. package/src/output-surface-inspect/lib/output-surface-inspect.ts +427 -0
  145. package/src/output-surface-inspect/lib/step-schema.ts +107 -0
  146. package/src/output-surface-inspect/runtime/index.ts +7 -0
  147. package/src/workspace-image/index.ts +13 -0
  148. package/src/workspace-image/lib/enums.ts +38 -0
  149. package/src/workspace-image/lib/hash.ts +95 -0
  150. package/src/workspace-image/lib/schemas.ts +63 -0
  151. package/src/workspace-image/lib/types.ts +79 -0
@@ -0,0 +1,95 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ── Workspace image — deterministic content hash ──
3
+ //
4
+ // Given a `WorkspaceImageManifest` plus the resolved base-image digest,
5
+ // produce a stable sha256 used as the variant's content identity. Two
6
+ // inputs that differ only in JSON formatting MUST hash to the same value;
7
+ // two inputs that differ semantically MUST NOT collide.
8
+ //
9
+ // Strategy:
10
+ // 1. Canonicalize: recursively sort object keys; arrays keep their
11
+ // authored order (order is semantically meaningful — `apt install`
12
+ // ordering can change layer caching and image size).
13
+ // 2. JSON.stringify the canonical form (no whitespace, stable key order).
14
+ // 3. sha256 over the concatenation `canonicalManifest + '\n' + digest`.
15
+ // ═══════════════════════════════════════════════════════════════════════════
16
+
17
+ import { createHash } from 'node:crypto';
18
+
19
+ import type { WorkspaceImageManifest } from './types';
20
+
21
+ type CanonicalJson =
22
+ | null
23
+ | boolean
24
+ | number
25
+ | string
26
+ | readonly CanonicalJson[]
27
+ | { readonly [key: string]: CanonicalJson };
28
+
29
+ /**
30
+ * Recursively produce a canonical, order-stable JSON-compatible value:
31
+ *
32
+ * - Objects: keys sorted lexicographically. `undefined` values dropped
33
+ * (mirrors `JSON.stringify`'s default and avoids two inputs differing
34
+ * only by an explicit `undefined` hashing differently).
35
+ * - Arrays: order is preserved (semantically meaningful in image layers).
36
+ * - Primitives & null: pass through.
37
+ *
38
+ * Throws on values JSON cannot represent (functions, symbols, bigint,
39
+ * circular refs) — fail-fast per the project's constitution.
40
+ */
41
+ function canonicalize(value: unknown, seen: WeakSet<object> = new WeakSet()): CanonicalJson {
42
+ if (value === null) return null;
43
+ const t = typeof value;
44
+ if (t === 'string' || t === 'boolean') {
45
+ return value as CanonicalJson;
46
+ }
47
+ if (t === 'number') {
48
+ if (!Number.isFinite(value as number)) {
49
+ throw new Error('canonicalize: non-finite number is not JSON-representable');
50
+ }
51
+ return value as number;
52
+ }
53
+ if (t === 'undefined') {
54
+ // Will be dropped by the object pass; encountering it at the root or
55
+ // inside an array indicates a programmer error.
56
+ throw new Error('canonicalize: undefined is not JSON-representable');
57
+ }
58
+ if (t === 'bigint' || t === 'function' || t === 'symbol') {
59
+ throw new Error(`canonicalize: ${t} is not JSON-representable`);
60
+ }
61
+ if (Array.isArray(value)) {
62
+ if (seen.has(value)) throw new Error('canonicalize: circular reference');
63
+ seen.add(value);
64
+ return value.map((entry) => canonicalize(entry, seen));
65
+ }
66
+ // Plain object.
67
+ if (seen.has(value as object)) throw new Error('canonicalize: circular reference');
68
+ seen.add(value as object);
69
+ const entries = Object.entries(value as Record<string, unknown>)
70
+ .filter(([, v]) => v !== undefined)
71
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
72
+ const out: Record<string, CanonicalJson> = {};
73
+ for (const [k, v] of entries) {
74
+ out[k] = canonicalize(v, seen);
75
+ }
76
+ return out;
77
+ }
78
+
79
+ /**
80
+ * Compute the canonical content hash of a workspace image variant. The
81
+ * `baseImageDigest` MUST be the resolved digest of the base image at
82
+ * bake-time (not a mutable tag) — otherwise a tag drift would silently
83
+ * invalidate the hash.
84
+ */
85
+ export function computeContentHash(
86
+ manifest: WorkspaceImageManifest,
87
+ baseImageDigest: string,
88
+ ): string {
89
+ if (!baseImageDigest || typeof baseImageDigest !== 'string') {
90
+ throw new Error('computeContentHash: baseImageDigest is required');
91
+ }
92
+ const canonical = canonicalize(manifest);
93
+ const serialized = JSON.stringify(canonical);
94
+ return createHash('sha256').update(`${serialized}\n${baseImageDigest}`).digest('hex');
95
+ }
@@ -0,0 +1,63 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ── Workspace image — zod schemas ──
3
+ //
4
+ // Runtime validators mirroring the enums and DTOs. Used by the bake
5
+ // service when persisting authored manifests and by the frontend when
6
+ // editing them in the Studio.
7
+ // ═══════════════════════════════════════════════════════════════════════════
8
+
9
+ import { z } from 'zod';
10
+ import { workerRuntimeKindSchema } from '../../worker-runtime';
11
+
12
+ import { ImageLayerKind, VariantStatus } from './enums';
13
+
14
+ export const imageLayerKindSchema = z.nativeEnum(ImageLayerKind);
15
+ export const variantStatusSchema = z.nativeEnum(VariantStatus);
16
+
17
+ const packagesArray = z.array(z.string().min(1));
18
+
19
+ export const imageLayerSchema = z.discriminatedUnion('kind', [
20
+ z.object({ kind: z.literal(ImageLayerKind.Apt), packages: packagesArray }),
21
+ z.object({ kind: z.literal(ImageLayerKind.Dnf), packages: packagesArray }),
22
+ z.object({ kind: z.literal(ImageLayerKind.Apk), packages: packagesArray }),
23
+ z.object({
24
+ kind: z.literal(ImageLayerKind.Pip),
25
+ packages: packagesArray,
26
+ pythonVersion: z.string().min(1).optional(),
27
+ }),
28
+ z.object({ kind: z.literal(ImageLayerKind.NpmGlobal), packages: packagesArray }),
29
+ z.object({
30
+ kind: z.literal(ImageLayerKind.Env),
31
+ vars: z.record(z.string().min(1), z.string()),
32
+ }),
33
+ z.object({
34
+ kind: z.literal(ImageLayerKind.File),
35
+ path: z.string().min(1),
36
+ contentBase64: z.string().min(1),
37
+ mode: z.number().int().nonnegative().optional(),
38
+ }),
39
+ ]);
40
+
41
+ export const workspaceImageManifestSchema = z.object({
42
+ layers: z.array(imageLayerSchema),
43
+ workdir: z.string().min(1).optional(),
44
+ });
45
+
46
+ export const workspaceImageVariantSchema = z.object({
47
+ id: z.string().min(1),
48
+ orgId: z.string().min(1),
49
+ slug: z.string().min(1),
50
+ description: z.string(),
51
+ runtimeKind: workerRuntimeKindSchema,
52
+ baseImage: z.string().min(1),
53
+ manifest: workspaceImageManifestSchema,
54
+ contentHash: z.string().min(1),
55
+ registryRef: z.string().min(1).optional(),
56
+ status: variantStatusSchema,
57
+ isOrgDefault: z.boolean(),
58
+ autoRebake: z.boolean(),
59
+ regions: z.array(z.string().min(1)),
60
+ buildLog: z.string().optional(),
61
+ builtAt: z.string().min(1).optional(),
62
+ createdAt: z.string().min(1),
63
+ });
@@ -0,0 +1,79 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ── Workspace image — manifest & variant types ──
3
+ //
4
+ // Strict types for per-org workspace image variants. The kernel never sees
5
+ // a Dockerfile — variants are declared as a closed list of layer recipes
6
+ // that the bake service translates into Buildah/BuildKit operations.
7
+ // ═══════════════════════════════════════════════════════════════════════════
8
+
9
+ import type { WorkerRuntimeKind } from '../../worker-runtime';
10
+
11
+ import type { ImageLayerKind, VariantStatus } from './enums';
12
+
13
+ /**
14
+ * A single layer in a `WorkspaceImageManifest`. Closed discriminated
15
+ * union keyed by `kind`. Each kind has a strict payload — the bake
16
+ * service exhaustively `switch`es on `kind`.
17
+ *
18
+ * No `entrypoint` / `cmd` kind by design: the worker-runtime owns process
19
+ * lifecycle, not the org-authored image.
20
+ */
21
+ export type ImageLayer =
22
+ | { readonly kind: ImageLayerKind.Apt; readonly packages: readonly string[] }
23
+ | { readonly kind: ImageLayerKind.Dnf; readonly packages: readonly string[] }
24
+ | { readonly kind: ImageLayerKind.Apk; readonly packages: readonly string[] }
25
+ | {
26
+ readonly kind: ImageLayerKind.Pip;
27
+ readonly packages: readonly string[];
28
+ readonly pythonVersion?: string;
29
+ }
30
+ | { readonly kind: ImageLayerKind.NpmGlobal; readonly packages: readonly string[] }
31
+ | { readonly kind: ImageLayerKind.Env; readonly vars: Readonly<Record<string, string>> }
32
+ | {
33
+ readonly kind: ImageLayerKind.File;
34
+ readonly path: string;
35
+ readonly contentBase64: string;
36
+ readonly mode?: number;
37
+ };
38
+
39
+ /**
40
+ * A bake recipe. The manifest is the AUTHORATIVE input to the bake
41
+ * service; everything else on `WorkspaceImageVariant` is derived metadata.
42
+ *
43
+ * `workdir` is the working directory inside the resulting image; it
44
+ * defaults to the runtime's choice when omitted. No `entrypoint` field —
45
+ * the runtime owns process lifecycle.
46
+ */
47
+ export interface WorkspaceImageManifest {
48
+ readonly layers: readonly ImageLayer[];
49
+ readonly workdir?: string;
50
+ }
51
+
52
+ /**
53
+ * Cross-service DTO for a baked variant. Mirrors the Prisma row in the
54
+ * workspace-image / bake service.
55
+ */
56
+ export interface WorkspaceImageVariant {
57
+ readonly id: string;
58
+ readonly orgId: string;
59
+ readonly slug: string;
60
+ readonly description: string;
61
+ readonly runtimeKind: WorkerRuntimeKind;
62
+ /** Base image (registry/name:tag or digest) the manifest extends. */
63
+ readonly baseImage: string;
64
+ readonly manifest: WorkspaceImageManifest;
65
+ /** sha256 of `(manifest, baseImageDigest)` — see `computeContentHash`. */
66
+ readonly contentHash: string;
67
+ /** Pushed registry reference once `status = Ready`. */
68
+ readonly registryRef?: string;
69
+ readonly status: VariantStatus;
70
+ readonly isOrgDefault: boolean;
71
+ readonly autoRebake: boolean;
72
+ /** Regions in which this variant has been replicated. */
73
+ readonly regions: readonly string[];
74
+ /** Tail of the bake log; absent for `draft`. */
75
+ readonly buildLog?: string;
76
+ /** ISO-8601 timestamp; absent until first successful bake. */
77
+ readonly builtAt?: string;
78
+ readonly createdAt: string;
79
+ }