@sprig-and-prose/sprig-edge 0.1.1 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @sprig-and-prose/sprig-edge
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **sprig-scenes (minor):** Export `PRIMITIVE_KINDS`, `ARTIFACT_TYPES`, and `ARTIFACT_TYPES_SET` from manifest as single source of truth. Add compile-time validation for primitive constraints (min/max/of) and array minItems/maxItems in `validateSceneManifest`. JSDoc: include `dataset` in artifactType.
8
+
9
+ **sprig-edge (minor):** Attestation now enforces optional fields, primitive constraints (min, max, of), and nested actor-shaped fields when manifest is available. Legend printed once at end for multiple scenes. Export `ValidationKind` and `ValidateRecordOptions`.
10
+
11
+ **sprig (patch):** Friendlier scene compile error prefix: "Scene compile failed" instead of "Scene compilation error".
12
+
13
+ **create-scene-tutorial (patch):** Generated scene file uses kebab-case filename: `demo-scene.scene.prose` instead of `DemoScene.scene.prose`.
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @sprig-and-prose/sprig-scenes@0.2.0
19
+
3
20
  ## 0.1.1
4
21
 
5
22
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/attestation/generate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,qBAAqB,CAAC;AAwBnE,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB1F"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/attestation/generate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,qBAAqB,CAAC;AAiDnE,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB1F"}
@@ -3,6 +3,28 @@ import { dirname, join } from "node:path";
3
3
  import { loadManifest } from "../manifest/reader.js";
4
4
  import { loadDatasetFiles } from "./file-loader.js";
5
5
  import { validateRecord } from "./validate-record.js";
6
+ /**
7
+ * Get the Kind used for record validation. Supports both legacy manifest (actorDef.kind)
8
+ * and new manifest (actorDef.type === "shape" with actorDef.fields).
9
+ * Passes through optional flags and field types (including primitive constraints).
10
+ */
11
+ function getActorKind(actorDef) {
12
+ if (actorDef.kind != null && typeof actorDef.kind === "object") {
13
+ return actorDef.kind;
14
+ }
15
+ const def = actorDef;
16
+ if (def.type === "shape" && def.fields && typeof def.fields === "object") {
17
+ const object = {};
18
+ for (const [name, field] of Object.entries(def.fields)) {
19
+ if (field?.type == null)
20
+ continue;
21
+ object[name] =
22
+ field.optional === true ? { kind: field.type, optional: true } : field.type;
23
+ }
24
+ return { object };
25
+ }
26
+ return undefined;
27
+ }
6
28
  export async function handleAttest(config, sceneFilter) {
7
29
  const scenesToProcess = sceneFilter
8
30
  ? config.scenes.filter((s) => s.scene === sceneFilter)
@@ -41,7 +63,8 @@ async function attestScene(sceneConfig) {
41
63
  // Only process dataset expectations
42
64
  if (expectation.artifactType !== "dataset")
43
65
  continue;
44
- const attestation = await attestDataset(sceneConfig, expectation, actorName, actorDef.kind);
66
+ const actorKind = getActorKind(actorDef);
67
+ const attestation = await attestDataset(sceneConfig, expectation, actorName, actorKind, manifest);
45
68
  attestations.push(attestation);
46
69
  }
47
70
  if (attestations.length > 0) {
@@ -53,7 +76,13 @@ async function attestScene(sceneConfig) {
53
76
  // Print summary
54
77
  printAttestationSummary(manifest.sceneName, attestationFile);
55
78
  }
56
- async function attestDataset(sceneConfig, expectation, actorName, actorKind) {
79
+ async function attestDataset(sceneConfig, expectation, _actorName, actorKind, manifest) {
80
+ const actorsContext = {};
81
+ for (const [name, def] of Object.entries(manifest.actors)) {
82
+ const k = getActorKind(def);
83
+ if (k != null)
84
+ actorsContext[name] = k;
85
+ }
57
86
  const datasetName = expectation.name;
58
87
  const locationName = expectation.location;
59
88
  // Look up dataset config
@@ -77,16 +106,22 @@ async function attestDataset(sceneConfig, expectation, actorName, actorKind) {
77
106
  const resolvedFiles = datasetConfig.files.map((f) => join(baseDir, f));
78
107
  // Load files
79
108
  const { records, errors: loadErrors } = await loadDatasetFiles(resolvedFiles, datasetConfig.format, datasetConfig.mode);
80
- // Validate records
109
+ // Validate records (skip if kind not available, e.g. new manifest shape without conversion)
81
110
  const validationErrors = [...loadErrors];
82
- for (let i = 0; i < records.length; i++) {
83
- const record = records[i];
84
- const recordErrors = validateRecord(record, actorKind, `record[${i}]`);
85
- for (const err of recordErrors) {
86
- const fieldPart = err.field ? ` (${err.field})` : "";
87
- validationErrors.push(`${err.message}${fieldPart}`);
111
+ if (actorKind != null) {
112
+ const opts = { actors: actorsContext };
113
+ for (let i = 0; i < records.length; i++) {
114
+ const record = records[i];
115
+ const recordErrors = validateRecord(record, actorKind, `record[${i}]`, opts);
116
+ for (const err of recordErrors) {
117
+ const fieldPart = err.field ? ` (${err.field})` : "";
118
+ validationErrors.push(`${err.message}${fieldPart}`);
119
+ }
88
120
  }
89
121
  }
122
+ else if (records.length > 0) {
123
+ validationErrors.push("Actor kind not available for validation (manifest may use new format)");
124
+ }
90
125
  const status = validationErrors.length === 0 ? "present" : "failed";
91
126
  const sampleErrors = validationErrors.slice(0, 10); // Keep first 10
92
127
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/attestation/generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/attestation/generate.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,41 @@
1
1
  /**
2
- * Validate a record against an actor shape (Kind)
2
+ * Validate a record against an actor shape (Kind).
3
+ * When options.actors is provided, actor-typed fields are validated recursively
4
+ * against the referenced actor's shape.
3
5
  */
6
+ /** Field in an object shape; may be optional. */
7
+ type FieldOrOptional = KindRef | {
8
+ kind: KindRef;
9
+ optional: true;
10
+ };
11
+ /** Primitive constraints from manifest (min, max, enum). */
12
+ interface TypeConstraints {
13
+ min?: number;
14
+ max?: number;
15
+ of?: (string | number)[];
16
+ }
4
17
  type Kind = {
5
18
  primitive: "string" | "integer" | "boolean" | "float" | "date" | "route";
19
+ constraints?: TypeConstraints;
6
20
  } | {
7
- object: Record<string, KindRef>;
21
+ object: Record<string, FieldOrOptional>;
8
22
  } | {
9
23
  array: KindRef;
10
24
  };
11
25
  type KindRef = Kind | {
12
26
  actor: string;
13
27
  };
28
+ /** Exported for use by callers (e.g. getActorKind return type). */
29
+ export type ValidationKind = Kind;
14
30
  export interface ValidationError {
15
31
  field?: string;
16
32
  message: string;
17
33
  }
18
- export declare function validateRecord(record: unknown, kind: Kind, fieldPath?: string): ValidationError[];
34
+ /** Optional context for recursive validation of actor-typed fields. */
35
+ export interface ValidateRecordOptions {
36
+ /** Map actor name -> Kind (from getActorKind) for nested shape validation. */
37
+ actors?: Record<string, unknown>;
38
+ }
39
+ export declare function validateRecord(record: unknown, kind: ValidationKind, fieldPath?: string, options?: ValidateRecordOptions): ValidationError[];
19
40
  export {};
20
41
  //# sourceMappingURL=validate-record.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-record.d.ts","sourceRoot":"","sources":["../../src/attestation/validate-record.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,KAAK,IAAI,GACL;IAAE,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GAC5E;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACnC;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvB,KAAK,OAAO,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,IAAI,EACV,SAAS,SAAK,GACb,eAAe,EAAE,CAmGnB"}
1
+ {"version":3,"file":"validate-record.d.ts","sourceRoot":"","sources":["../../src/attestation/validate-record.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iDAAiD;AACjD,KAAK,eAAe,GAAG,OAAO,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnE,4DAA4D;AAC5D,UAAU,eAAe;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC1B;AAED,KAAK,IAAI,GACL;IAAE,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,eAAe,CAAA;CAAE,GAC3G;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,GAC3C;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvB,KAAK,OAAO,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC;AAUlC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,cAAc,EACpB,SAAS,SAAK,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,eAAe,EAAE,CAyJnB"}
@@ -1,8 +1,20 @@
1
1
  /**
2
- * Validate a record against an actor shape (Kind)
2
+ * Validate a record against an actor shape (Kind).
3
+ * When options.actors is provided, actor-typed fields are validated recursively
4
+ * against the referenced actor's shape.
3
5
  */
4
- export function validateRecord(record, kind, fieldPath = "") {
6
+ function isOptionalField(f) {
7
+ return typeof f === "object" && f !== null && "optional" in f && f.optional === true;
8
+ }
9
+ function resolveFieldKind(f) {
10
+ return isOptionalField(f) ? f.kind : f;
11
+ }
12
+ export function validateRecord(record, kind, fieldPath = "", options) {
5
13
  const errors = [];
14
+ if (kind == null || typeof kind !== "object") {
15
+ errors.push({ field: fieldPath, message: "Missing or invalid kind for validation" });
16
+ return errors;
17
+ }
6
18
  // Primitive validation
7
19
  if ("primitive" in kind) {
8
20
  const expectedType = kind.primitive;
@@ -35,6 +47,25 @@ export function validateRecord(record, kind, fieldPath = "") {
35
47
  }
36
48
  break;
37
49
  }
50
+ // Enforce primitive constraints if present
51
+ const constraints = kind.constraints;
52
+ if (constraints && actualType !== "undefined" && record !== null) {
53
+ if (typeof constraints.min === "number" && typeof record === "number" && record < constraints.min) {
54
+ errors.push({ field: fieldPath, message: `Value ${record} is below min (${constraints.min})` });
55
+ }
56
+ if (typeof constraints.max === "number" && typeof record === "number" && record > constraints.max) {
57
+ errors.push({ field: fieldPath, message: `Value ${record} is above max (${constraints.max})` });
58
+ }
59
+ if (Array.isArray(constraints.of) && constraints.of.length > 0) {
60
+ const val = record;
61
+ if (!constraints.of.includes(val)) {
62
+ errors.push({
63
+ field: fieldPath,
64
+ message: `Value ${JSON.stringify(val)} is not in allowed set [${constraints.of.map((x) => JSON.stringify(x)).join(", ")}]`,
65
+ });
66
+ }
67
+ }
68
+ }
38
69
  return errors;
39
70
  }
40
71
  // Array validation
@@ -48,7 +79,7 @@ export function validateRecord(record, kind, fieldPath = "") {
48
79
  return errors;
49
80
  }
50
81
  for (let i = 0; i < record.length; i++) {
51
- const itemErrors = validateRecord(record[i], kind.array, `${fieldPath}[${i}]`);
82
+ const itemErrors = validateRecord(record[i], kind.array, `${fieldPath}[${i}]`, options);
52
83
  errors.push(...itemErrors);
53
84
  }
54
85
  return errors;
@@ -61,20 +92,39 @@ export function validateRecord(record, kind, fieldPath = "") {
61
92
  }
62
93
  const recordObj = record;
63
94
  const shapeFields = kind.object;
64
- // Check required fields
65
- for (const [fieldName, fieldKind] of Object.entries(shapeFields)) {
95
+ // Check required fields (optional fields may be missing)
96
+ for (const [fieldName, fieldOrOpt] of Object.entries(shapeFields)) {
66
97
  const fieldValue = recordObj[fieldName];
67
98
  const fullPath = fieldPath ? `${fieldPath}.${fieldName}` : fieldName;
99
+ const fieldKind = resolveFieldKind(fieldOrOpt);
100
+ const isOptional = isOptionalField(fieldOrOpt);
68
101
  if (fieldValue === undefined || fieldValue === null) {
69
- errors.push({ field: fullPath, message: "Required field missing" });
102
+ if (!isOptional) {
103
+ errors.push({ field: fullPath, message: "Required field missing" });
104
+ }
105
+ continue;
70
106
  }
71
- else {
72
- // Recurse for nested validation (skip actor references)
73
- if ("actor" in fieldKind) {
74
- // Skip actor reference validation for now (would need manifest context)
75
- continue;
107
+ if ("actor" in fieldKind) {
108
+ const actorName = fieldKind.actor;
109
+ if (typeof fieldValue !== "object" || fieldValue === null || Array.isArray(fieldValue)) {
110
+ errors.push({
111
+ field: fullPath,
112
+ message: `Expected object (actor ${actorName}), got ${typeof fieldValue}`,
113
+ });
76
114
  }
77
- const fieldErrors = validateRecord(fieldValue, fieldKind, fullPath);
115
+ else {
116
+ const nestedKind = options?.actors?.[actorName];
117
+ if (nestedKind != null &&
118
+ typeof nestedKind === "object" &&
119
+ "object" in nestedKind &&
120
+ nestedKind.object != null) {
121
+ const nestedErrors = validateRecord(fieldValue, nestedKind, fullPath, options);
122
+ errors.push(...nestedErrors);
123
+ }
124
+ }
125
+ }
126
+ else {
127
+ const fieldErrors = validateRecord(fieldValue, fieldKind, fullPath, options);
78
128
  errors.push(...fieldErrors);
79
129
  }
80
130
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validate-record.js","sourceRoot":"","sources":["../../src/attestation/validate-record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate-record.js","sourceRoot":"","sources":["../../src/attestation/validate-record.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/check/render.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,qBAAqB,CAAC;AAWnE,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzF"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/check/render.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,qBAAqB,CAAC;AAWnE,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBzF"}
@@ -18,6 +18,13 @@ export async function handleCheck(config, sceneFilter) {
18
18
  for (const sceneConfig of scenesToProcess) {
19
19
  await checkScene(sceneConfig);
20
20
  }
21
+ if (scenesToProcess.length > 0) {
22
+ console.log("\n Legend:");
23
+ console.log(" ⚪ expected - Projection declared but not yet attested");
24
+ console.log(" 🟢 attested - Projection exists and is attested");
25
+ console.log(" 🟠 drifted - Shape has changed (not yet implemented)");
26
+ console.log(" 🔴 failed - Attestation exists but status is not 'present'");
27
+ }
21
28
  }
22
29
  async function checkScene(sceneConfig) {
23
30
  // Load manifest
@@ -64,16 +71,10 @@ function renderStatusReport(sceneName, status) {
64
71
  console.log(` ${actorName}:`);
65
72
  for (const exp of expectations) {
66
73
  const icon = getStatusIcon(exp.status);
67
- const statusText = exp.status.toUpperCase().padEnd(10);
74
+ const statusText = exp.status.padEnd(10);
68
75
  console.log(` ${icon} ${statusText} → ${exp.location} / ${exp.artifactType} / ${exp.name}`);
69
76
  }
70
77
  }
71
- // Print legend
72
- console.log("\n Legend:");
73
- console.log(" ⚪ EXPECTED - Projection declared but not yet attested");
74
- console.log(" 🟢 ATTESTED - Projection exists and is attested");
75
- console.log(" 🟠 DRIFTED - Shape has changed (not yet implemented)");
76
- console.log(" 🔴 FAILED - Attestation exists but status is not 'present'");
77
78
  }
78
79
  function getStatusIcon(status) {
79
80
  switch (status) {
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/check/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/check/render.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprig-and-prose/sprig-edge",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Edge CLI for Sprig attestation and checking",
6
6
  "main": "dist/cli.js",
@@ -1,9 +1,34 @@
1
1
  import { writeFile, mkdir } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
  import type { EdgeConfig, SceneConfig } from "../config/schema.js";
4
- import { loadManifest, type ProjectionExpectation } from "../manifest/reader.js";
4
+ import { loadManifest, type ActorDef, type ProjectionExpectation } from "../manifest/reader.js";
5
5
  import { loadDatasetFiles } from "./file-loader.js";
6
- import { validateRecord } from "./validate-record.js";
6
+ import { validateRecord, type ValidationKind } from "./validate-record.js";
7
+
8
+ /**
9
+ * Get the Kind used for record validation. Supports both legacy manifest (actorDef.kind)
10
+ * and new manifest (actorDef.type === "shape" with actorDef.fields).
11
+ * Passes through optional flags and field types (including primitive constraints).
12
+ */
13
+ function getActorKind(actorDef: ActorDef): ValidationKind | undefined {
14
+ if (actorDef.kind != null && typeof actorDef.kind === "object") {
15
+ return actorDef.kind as ValidationKind;
16
+ }
17
+ const def = actorDef as {
18
+ type?: string;
19
+ fields?: Record<string, { type?: unknown; optional?: boolean }>;
20
+ };
21
+ if (def.type === "shape" && def.fields && typeof def.fields === "object") {
22
+ const object: Record<string, unknown> = {};
23
+ for (const [name, field] of Object.entries(def.fields)) {
24
+ if (field?.type == null) continue;
25
+ object[name] =
26
+ field.optional === true ? { kind: field.type, optional: true as const } : field.type;
27
+ }
28
+ return { object } as ValidationKind;
29
+ }
30
+ return undefined;
31
+ }
7
32
 
8
33
  interface Attestation {
9
34
  location: string;
@@ -69,11 +94,13 @@ async function attestScene(sceneConfig: SceneConfig): Promise<void> {
69
94
  // Only process dataset expectations
70
95
  if (expectation.artifactType !== "dataset") continue;
71
96
 
97
+ const actorKind = getActorKind(actorDef);
72
98
  const attestation = await attestDataset(
73
99
  sceneConfig,
74
100
  expectation,
75
101
  actorName,
76
- actorDef.kind,
102
+ actorKind,
103
+ manifest,
77
104
  );
78
105
  attestations.push(attestation);
79
106
  }
@@ -93,9 +120,15 @@ async function attestScene(sceneConfig: SceneConfig): Promise<void> {
93
120
  async function attestDataset(
94
121
  sceneConfig: SceneConfig,
95
122
  expectation: ProjectionExpectation,
96
- actorName: string,
97
- actorKind: unknown,
123
+ _actorName: string,
124
+ actorKind: ValidationKind | undefined,
125
+ manifest: { actors: Record<string, ActorDef> },
98
126
  ): Promise<Attestation> {
127
+ const actorsContext: Record<string, ValidationKind> = {};
128
+ for (const [name, def] of Object.entries(manifest.actors)) {
129
+ const k = getActorKind(def);
130
+ if (k != null) actorsContext[name] = k;
131
+ }
99
132
  const datasetName = expectation.name;
100
133
  const locationName = expectation.location;
101
134
 
@@ -128,15 +161,20 @@ async function attestDataset(
128
161
  datasetConfig.mode,
129
162
  );
130
163
 
131
- // Validate records
164
+ // Validate records (skip if kind not available, e.g. new manifest shape without conversion)
132
165
  const validationErrors: string[] = [...loadErrors];
133
- for (let i = 0; i < records.length; i++) {
134
- const record = records[i];
135
- const recordErrors = validateRecord(record, actorKind as any, `record[${i}]`);
136
- for (const err of recordErrors) {
137
- const fieldPart = err.field ? ` (${err.field})` : "";
138
- validationErrors.push(`${err.message}${fieldPart}`);
166
+ if (actorKind != null) {
167
+ const opts = { actors: actorsContext };
168
+ for (let i = 0; i < records.length; i++) {
169
+ const record = records[i];
170
+ const recordErrors = validateRecord(record, actorKind, `record[${i}]`, opts);
171
+ for (const err of recordErrors) {
172
+ const fieldPart = err.field ? ` (${err.field})` : "";
173
+ validationErrors.push(`${err.message}${fieldPart}`);
174
+ }
139
175
  }
176
+ } else if (records.length > 0) {
177
+ validationErrors.push("Actor kind not available for validation (manifest may use new format)");
140
178
  }
141
179
 
142
180
  const status = validationErrors.length === 0 ? "present" : "failed";
@@ -1,26 +1,61 @@
1
1
  /**
2
- * Validate a record against an actor shape (Kind)
2
+ * Validate a record against an actor shape (Kind).
3
+ * When options.actors is provided, actor-typed fields are validated recursively
4
+ * against the referenced actor's shape.
3
5
  */
4
6
 
5
- type Kind =
6
- | { primitive: "string" | "integer" | "boolean" | "float" | "date" | "route" }
7
- | { object: Record<string, KindRef> }
7
+ /** Field in an object shape; may be optional. */
8
+ type FieldOrOptional = KindRef | { kind: KindRef; optional: true };
9
+
10
+ /** Primitive constraints from manifest (min, max, enum). */
11
+ interface TypeConstraints {
12
+ min?: number;
13
+ max?: number;
14
+ of?: (string | number)[];
15
+ }
16
+
17
+ type Kind =
18
+ | { primitive: "string" | "integer" | "boolean" | "float" | "date" | "route"; constraints?: TypeConstraints }
19
+ | { object: Record<string, FieldOrOptional> }
8
20
  | { array: KindRef };
9
21
 
10
22
  type KindRef = Kind | { actor: string };
11
23
 
24
+ /** Exported for use by callers (e.g. getActorKind return type). */
25
+ export type ValidationKind = Kind;
26
+
27
+ function isOptionalField(f: FieldOrOptional): f is { kind: KindRef; optional: true } {
28
+ return typeof f === "object" && f !== null && "optional" in f && (f as { optional?: boolean }).optional === true;
29
+ }
30
+
31
+ function resolveFieldKind(f: FieldOrOptional): KindRef {
32
+ return isOptionalField(f) ? f.kind : f;
33
+ }
34
+
12
35
  export interface ValidationError {
13
36
  field?: string;
14
37
  message: string;
15
38
  }
16
39
 
40
+ /** Optional context for recursive validation of actor-typed fields. */
41
+ export interface ValidateRecordOptions {
42
+ /** Map actor name -> Kind (from getActorKind) for nested shape validation. */
43
+ actors?: Record<string, unknown>;
44
+ }
45
+
17
46
  export function validateRecord(
18
47
  record: unknown,
19
- kind: Kind,
48
+ kind: ValidationKind,
20
49
  fieldPath = "",
50
+ options?: ValidateRecordOptions,
21
51
  ): ValidationError[] {
22
52
  const errors: ValidationError[] = [];
23
53
 
54
+ if (kind == null || typeof kind !== "object") {
55
+ errors.push({ field: fieldPath, message: "Missing or invalid kind for validation" });
56
+ return errors;
57
+ }
58
+
24
59
  // Primitive validation
25
60
  if ("primitive" in kind) {
26
61
  const expectedType = kind.primitive;
@@ -54,6 +89,25 @@ export function validateRecord(
54
89
  }
55
90
  break;
56
91
  }
92
+ // Enforce primitive constraints if present
93
+ const constraints = kind.constraints;
94
+ if (constraints && actualType !== "undefined" && record !== null) {
95
+ if (typeof constraints.min === "number" && typeof record === "number" && record < constraints.min) {
96
+ errors.push({ field: fieldPath, message: `Value ${record} is below min (${constraints.min})` });
97
+ }
98
+ if (typeof constraints.max === "number" && typeof record === "number" && record > constraints.max) {
99
+ errors.push({ field: fieldPath, message: `Value ${record} is above max (${constraints.max})` });
100
+ }
101
+ if (Array.isArray(constraints.of) && constraints.of.length > 0) {
102
+ const val = record as string | number;
103
+ if (!constraints.of.includes(val)) {
104
+ errors.push({
105
+ field: fieldPath,
106
+ message: `Value ${JSON.stringify(val)} is not in allowed set [${constraints.of.map((x) => JSON.stringify(x)).join(", ")}]`,
107
+ });
108
+ }
109
+ }
110
+ }
57
111
  return errors;
58
112
  }
59
113
 
@@ -70,7 +124,12 @@ export function validateRecord(
70
124
  }
71
125
 
72
126
  for (let i = 0; i < record.length; i++) {
73
- const itemErrors = validateRecord(record[i], kind.array as Kind, `${fieldPath}[${i}]`);
127
+ const itemErrors = validateRecord(
128
+ record[i],
129
+ kind.array as Kind,
130
+ `${fieldPath}[${i}]`,
131
+ options,
132
+ );
74
133
  errors.push(...itemErrors);
75
134
  }
76
135
  return errors;
@@ -86,20 +145,45 @@ export function validateRecord(
86
145
  const recordObj = record as Record<string, unknown>;
87
146
  const shapeFields = kind.object;
88
147
 
89
- // Check required fields
90
- for (const [fieldName, fieldKind] of Object.entries(shapeFields)) {
148
+ // Check required fields (optional fields may be missing)
149
+ for (const [fieldName, fieldOrOpt] of Object.entries(shapeFields)) {
91
150
  const fieldValue = recordObj[fieldName];
92
151
  const fullPath = fieldPath ? `${fieldPath}.${fieldName}` : fieldName;
152
+ const fieldKind = resolveFieldKind(fieldOrOpt);
153
+ const isOptional = isOptionalField(fieldOrOpt);
93
154
 
94
155
  if (fieldValue === undefined || fieldValue === null) {
95
- errors.push({ field: fullPath, message: "Required field missing" });
96
- } else {
97
- // Recurse for nested validation (skip actor references)
98
- if ("actor" in fieldKind) {
99
- // Skip actor reference validation for now (would need manifest context)
100
- continue;
156
+ if (!isOptional) {
157
+ errors.push({ field: fullPath, message: "Required field missing" });
101
158
  }
102
- const fieldErrors = validateRecord(fieldValue, fieldKind as Kind, fullPath);
159
+ continue;
160
+ }
161
+ if ("actor" in fieldKind) {
162
+ const actorName = (fieldKind as { actor: string }).actor;
163
+ if (typeof fieldValue !== "object" || fieldValue === null || Array.isArray(fieldValue)) {
164
+ errors.push({
165
+ field: fullPath,
166
+ message: `Expected object (actor ${actorName}), got ${typeof fieldValue}`,
167
+ });
168
+ } else {
169
+ const nestedKind = options?.actors?.[actorName];
170
+ if (
171
+ nestedKind != null &&
172
+ typeof nestedKind === "object" &&
173
+ "object" in nestedKind &&
174
+ (nestedKind as { object?: unknown }).object != null
175
+ ) {
176
+ const nestedErrors = validateRecord(
177
+ fieldValue,
178
+ nestedKind as Kind,
179
+ fullPath,
180
+ options,
181
+ );
182
+ errors.push(...nestedErrors);
183
+ }
184
+ }
185
+ } else {
186
+ const fieldErrors = validateRecord(fieldValue, fieldKind as Kind, fullPath, options);
103
187
  errors.push(...fieldErrors);
104
188
  }
105
189
  }
@@ -30,6 +30,14 @@ export async function handleCheck(config: EdgeConfig, sceneFilter?: string): Pro
30
30
  for (const sceneConfig of scenesToProcess) {
31
31
  await checkScene(sceneConfig);
32
32
  }
33
+
34
+ if (scenesToProcess.length > 0) {
35
+ console.log("\n Legend:");
36
+ console.log(" ⚪ expected - Projection declared but not yet attested");
37
+ console.log(" 🟢 attested - Projection exists and is attested");
38
+ console.log(" 🟠 drifted - Shape has changed (not yet implemented)");
39
+ console.log(" 🔴 failed - Attestation exists but status is not 'present'");
40
+ }
33
41
  }
34
42
 
35
43
  async function checkScene(sceneConfig: SceneConfig): Promise<void> {
@@ -88,19 +96,12 @@ function renderStatusReport(
88
96
  console.log(` ${actorName}:`);
89
97
  for (const exp of expectations) {
90
98
  const icon = getStatusIcon(exp.status);
91
- const statusText = exp.status.toUpperCase().padEnd(10);
99
+ const statusText = exp.status.padEnd(10);
92
100
  console.log(
93
101
  ` ${icon} ${statusText} → ${exp.location} / ${exp.artifactType} / ${exp.name}`,
94
102
  );
95
103
  }
96
104
  }
97
-
98
- // Print legend
99
- console.log("\n Legend:");
100
- console.log(" ⚪ EXPECTED - Projection declared but not yet attested");
101
- console.log(" 🟢 ATTESTED - Projection exists and is attested");
102
- console.log(" 🟠 DRIFTED - Shape has changed (not yet implemented)");
103
- console.log(" 🔴 FAILED - Attestation exists but status is not 'present'");
104
105
  }
105
106
 
106
107
  function getStatusIcon(status: string): string {