@sprig-and-prose/sprig-edge 0.1.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 (48) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/attestation/file-loader.d.ts +5 -0
  3. package/dist/attestation/file-loader.d.ts.map +1 -0
  4. package/dist/attestation/file-loader.js +42 -0
  5. package/dist/attestation/file-loader.js.map +1 -0
  6. package/dist/attestation/generate.d.ts +3 -0
  7. package/dist/attestation/generate.d.ts.map +1 -0
  8. package/dist/attestation/generate.js +134 -0
  9. package/dist/attestation/generate.js.map +1 -0
  10. package/dist/attestation/validate-record.d.ts +20 -0
  11. package/dist/attestation/validate-record.d.ts.map +1 -0
  12. package/dist/attestation/validate-record.js +93 -0
  13. package/dist/attestation/validate-record.js.map +1 -0
  14. package/dist/check/render.d.ts +3 -0
  15. package/dist/check/render.d.ts.map +1 -0
  16. package/dist/check/render.js +92 -0
  17. package/dist/check/render.js.map +1 -0
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +93 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/config/load.d.ts +3 -0
  23. package/dist/config/load.d.ts.map +1 -0
  24. package/dist/config/load.js +33 -0
  25. package/dist/config/load.js.map +1 -0
  26. package/dist/config/schema.d.ts +28 -0
  27. package/dist/config/schema.d.ts.map +1 -0
  28. package/dist/config/schema.js +28 -0
  29. package/dist/config/schema.js.map +1 -0
  30. package/dist/init.d.ts +2 -0
  31. package/dist/init.d.ts.map +1 -0
  32. package/dist/init.js +37 -0
  33. package/dist/init.js.map +1 -0
  34. package/dist/manifest/reader.d.ts +26 -0
  35. package/dist/manifest/reader.d.ts.map +1 -0
  36. package/dist/manifest/reader.js +18 -0
  37. package/dist/manifest/reader.js.map +1 -0
  38. package/package.json +34 -0
  39. package/src/attestation/file-loader.ts +45 -0
  40. package/src/attestation/generate.ts +196 -0
  41. package/src/attestation/validate-record.ts +120 -0
  42. package/src/check/render.ts +119 -0
  43. package/src/cli.ts +107 -0
  44. package/src/config/load.ts +39 -0
  45. package/src/config/schema.ts +60 -0
  46. package/src/init.ts +38 -0
  47. package/src/manifest/reader.ts +47 -0
  48. package/tsconfig.json +20 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # @sprig-and-prose/sprig-edge
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9557987: Add dataset expectations, sprig-edge initial commit, and scene tutorial scaffolder
8
+ - Updated dependencies [9557987]
9
+ - @sprig-and-prose/sprig-scenes@0.1.1
@@ -0,0 +1,5 @@
1
+ export declare function loadDatasetFiles(files: string[], format: "yaml" | "json", mode: "array" | "object"): Promise<{
2
+ records: unknown[];
3
+ errors: string[];
4
+ }>;
5
+ //# sourceMappingURL=file-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/attestation/file-loader.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,OAAO,GAAG,QAAQ,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqCnD"}
@@ -0,0 +1,42 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parse as parseYAML } from "yaml";
3
+ export async function loadDatasetFiles(files, format, mode) {
4
+ const allRecords = [];
5
+ const errors = [];
6
+ for (const filePath of files) {
7
+ try {
8
+ const text = await readFile(filePath, "utf-8");
9
+ let data;
10
+ if (format === "yaml") {
11
+ data = parseYAML(text);
12
+ }
13
+ else {
14
+ data = JSON.parse(text);
15
+ }
16
+ // Extract records based on mode
17
+ if (mode === "array") {
18
+ if (Array.isArray(data)) {
19
+ allRecords.push(...data);
20
+ }
21
+ else {
22
+ errors.push(`File ${filePath}: expected array, got ${typeof data}`);
23
+ }
24
+ }
25
+ else {
26
+ // mode === "object"
27
+ if (data && typeof data === "object" && !Array.isArray(data)) {
28
+ allRecords.push(data);
29
+ }
30
+ else {
31
+ errors.push(`File ${filePath}: expected object, got ${typeof data}`);
32
+ }
33
+ }
34
+ }
35
+ catch (error) {
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ errors.push(`File ${filePath}: ${message}`);
38
+ }
39
+ }
40
+ return { records: allRecords, errors };
41
+ }
42
+ //# sourceMappingURL=file-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-loader.js","sourceRoot":"","sources":["../../src/attestation/file-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAe,EACf,MAAuB,EACvB,IAAwB;IAExB,MAAM,UAAU,GAAc,EAAE,CAAC;IACjC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/C,IAAI,IAAa,CAAC;YAElB,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;YAED,gCAAgC;YAChC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxB,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,QAAQ,QAAQ,yBAAyB,OAAO,IAAI,EAAE,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,oBAAoB;gBACpB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,QAAQ,QAAQ,0BAA0B,OAAO,IAAI,EAAE,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,QAAQ,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { EdgeConfig } from "../config/schema.js";
2
+ export declare function handleAttest(config: EdgeConfig, sceneFilter?: string): Promise<void>;
3
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,134 @@
1
+ import { writeFile, mkdir } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { loadManifest } from "../manifest/reader.js";
4
+ import { loadDatasetFiles } from "./file-loader.js";
5
+ import { validateRecord } from "./validate-record.js";
6
+ export async function handleAttest(config, sceneFilter) {
7
+ const scenesToProcess = sceneFilter
8
+ ? config.scenes.filter((s) => s.scene === sceneFilter)
9
+ : config.scenes;
10
+ if (scenesToProcess.length === 0) {
11
+ if (sceneFilter) {
12
+ console.error(`No scene found with name: ${sceneFilter}`);
13
+ process.exit(1);
14
+ }
15
+ console.log("No scenes configured");
16
+ return;
17
+ }
18
+ for (const sceneConfig of scenesToProcess) {
19
+ await attestScene(sceneConfig);
20
+ }
21
+ }
22
+ async function attestScene(sceneConfig) {
23
+ // Load manifest
24
+ const manifest = await loadManifest(sceneConfig.manifestPath);
25
+ // Extract manifestId
26
+ const manifestId = manifest.meta?.manifestId || null;
27
+ // Build attestation file
28
+ const attestationFile = {
29
+ version: 1,
30
+ scene: manifest.sceneName,
31
+ manifestId,
32
+ generatedAt: new Date().toISOString(),
33
+ actors: {},
34
+ };
35
+ // Process each actor's expectations
36
+ for (const [actorName, actorDef] of Object.entries(manifest.actors)) {
37
+ if (!actorDef.expectations)
38
+ continue;
39
+ const attestations = [];
40
+ for (const expectation of actorDef.expectations) {
41
+ // Only process dataset expectations
42
+ if (expectation.artifactType !== "dataset")
43
+ continue;
44
+ const attestation = await attestDataset(sceneConfig, expectation, actorName, actorDef.kind);
45
+ attestations.push(attestation);
46
+ }
47
+ if (attestations.length > 0) {
48
+ attestationFile.actors[actorName] = attestations;
49
+ }
50
+ }
51
+ // Write attestation file
52
+ await writeAttestationFile(sceneConfig.attestationsPath, attestationFile);
53
+ // Print summary
54
+ printAttestationSummary(manifest.sceneName, attestationFile);
55
+ }
56
+ async function attestDataset(sceneConfig, expectation, actorName, actorKind) {
57
+ const datasetName = expectation.name;
58
+ const locationName = expectation.location;
59
+ // Look up dataset config
60
+ const datasetConfig = sceneConfig.datasets?.[datasetName];
61
+ if (!datasetConfig) {
62
+ return {
63
+ location: locationName,
64
+ artifactType: "dataset",
65
+ name: datasetName,
66
+ status: "failed",
67
+ observedAt: new Date().toISOString(),
68
+ counts: { files: 0, records: 0, errors: 1 },
69
+ inputs: [],
70
+ sampleErrors: [`Dataset ${datasetName} not found in config`],
71
+ };
72
+ }
73
+ // Look up location config
74
+ const locationConfig = sceneConfig.locations?.[locationName];
75
+ const baseDir = locationConfig?.baseDir || ".";
76
+ // Resolve file paths
77
+ const resolvedFiles = datasetConfig.files.map((f) => join(baseDir, f));
78
+ // Load files
79
+ const { records, errors: loadErrors } = await loadDatasetFiles(resolvedFiles, datasetConfig.format, datasetConfig.mode);
80
+ // Validate records
81
+ 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}`);
88
+ }
89
+ }
90
+ const status = validationErrors.length === 0 ? "present" : "failed";
91
+ const sampleErrors = validationErrors.slice(0, 10); // Keep first 10
92
+ return {
93
+ location: locationName,
94
+ artifactType: "dataset",
95
+ name: datasetName,
96
+ status,
97
+ observedAt: new Date().toISOString(),
98
+ counts: {
99
+ files: resolvedFiles.length,
100
+ records: records.length,
101
+ errors: validationErrors.length,
102
+ },
103
+ inputs: resolvedFiles,
104
+ sampleErrors,
105
+ };
106
+ }
107
+ async function writeAttestationFile(path, data) {
108
+ // Ensure directory exists
109
+ await mkdir(dirname(path), { recursive: true });
110
+ const json = JSON.stringify(data, null, 2);
111
+ await writeFile(path, json, "utf-8");
112
+ }
113
+ function printAttestationSummary(sceneName, attestationFile) {
114
+ console.log(`\n✓ Attested ${sceneName}:`);
115
+ for (const [actorName, attestations] of Object.entries(attestationFile.actors)) {
116
+ for (const att of attestations) {
117
+ if (att.status === "present") {
118
+ console.log(` 🟢 ${actorName}: ${att.name} present (${att.counts.records} records, ${att.counts.files} files)`);
119
+ }
120
+ else {
121
+ console.log(` 🔴 ${actorName}: ${att.name} FAILED (${att.counts.errors} errors, ${att.counts.records} records)`);
122
+ if (att.sampleErrors.length > 0) {
123
+ for (const err of att.sampleErrors.slice(0, 3)) {
124
+ console.log(` - ${err}`);
125
+ }
126
+ if (att.sampleErrors.length > 3) {
127
+ console.log(` ... and ${att.sampleErrors.length - 3} more errors`);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/attestation/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Validate a record against an actor shape (Kind)
3
+ */
4
+ type Kind = {
5
+ primitive: "string" | "integer" | "boolean" | "float" | "date" | "route";
6
+ } | {
7
+ object: Record<string, KindRef>;
8
+ } | {
9
+ array: KindRef;
10
+ };
11
+ type KindRef = Kind | {
12
+ actor: string;
13
+ };
14
+ export interface ValidationError {
15
+ field?: string;
16
+ message: string;
17
+ }
18
+ export declare function validateRecord(record: unknown, kind: Kind, fieldPath?: string): ValidationError[];
19
+ export {};
20
+ //# sourceMappingURL=validate-record.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Validate a record against an actor shape (Kind)
3
+ */
4
+ export function validateRecord(record, kind, fieldPath = "") {
5
+ const errors = [];
6
+ // Primitive validation
7
+ if ("primitive" in kind) {
8
+ const expectedType = kind.primitive;
9
+ const actualType = typeof record;
10
+ switch (expectedType) {
11
+ case "string":
12
+ if (actualType !== "string") {
13
+ errors.push({ field: fieldPath, message: `Expected string, got ${actualType}` });
14
+ }
15
+ break;
16
+ case "integer":
17
+ case "float":
18
+ if (actualType !== "number") {
19
+ errors.push({ field: fieldPath, message: `Expected number, got ${actualType}` });
20
+ }
21
+ break;
22
+ case "boolean":
23
+ if (actualType !== "boolean") {
24
+ errors.push({ field: fieldPath, message: `Expected boolean, got ${actualType}` });
25
+ }
26
+ break;
27
+ case "date":
28
+ if (actualType !== "string") {
29
+ errors.push({ field: fieldPath, message: `Expected date string, got ${actualType}` });
30
+ }
31
+ break;
32
+ case "route":
33
+ if (actualType !== "string") {
34
+ errors.push({ field: fieldPath, message: `Expected route string, got ${actualType}` });
35
+ }
36
+ break;
37
+ }
38
+ return errors;
39
+ }
40
+ // Array validation
41
+ if ("array" in kind) {
42
+ if (!Array.isArray(record)) {
43
+ errors.push({ field: fieldPath, message: `Expected array, got ${typeof record}` });
44
+ return errors;
45
+ }
46
+ // Skip validation if array contains actor references
47
+ if ("actor" in kind.array) {
48
+ return errors;
49
+ }
50
+ for (let i = 0; i < record.length; i++) {
51
+ const itemErrors = validateRecord(record[i], kind.array, `${fieldPath}[${i}]`);
52
+ errors.push(...itemErrors);
53
+ }
54
+ return errors;
55
+ }
56
+ // Object validation
57
+ if ("object" in kind) {
58
+ if (!record || typeof record !== "object" || Array.isArray(record)) {
59
+ errors.push({ field: fieldPath, message: `Expected object, got ${typeof record}` });
60
+ return errors;
61
+ }
62
+ const recordObj = record;
63
+ const shapeFields = kind.object;
64
+ // Check required fields
65
+ for (const [fieldName, fieldKind] of Object.entries(shapeFields)) {
66
+ const fieldValue = recordObj[fieldName];
67
+ const fullPath = fieldPath ? `${fieldPath}.${fieldName}` : fieldName;
68
+ if (fieldValue === undefined || fieldValue === null) {
69
+ errors.push({ field: fullPath, message: "Required field missing" });
70
+ }
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;
76
+ }
77
+ const fieldErrors = validateRecord(fieldValue, fieldKind, fullPath);
78
+ errors.push(...fieldErrors);
79
+ }
80
+ }
81
+ // Check for unknown fields (strict mode)
82
+ const knownFields = new Set(Object.keys(shapeFields));
83
+ for (const recordField of Object.keys(recordObj)) {
84
+ if (!knownFields.has(recordField)) {
85
+ const fullPath = fieldPath ? `${fieldPath}.${recordField}` : recordField;
86
+ errors.push({ field: fullPath, message: "Unknown field" });
87
+ }
88
+ }
89
+ return errors;
90
+ }
91
+ return errors;
92
+ }
93
+ //# sourceMappingURL=validate-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-record.js","sourceRoot":"","sources":["../../src/attestation/validate-record.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { EdgeConfig } from "../config/schema.js";
2
+ export declare function handleCheck(config: EdgeConfig, sceneFilter?: string): Promise<void>;
3
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,92 @@
1
+ import { readFile } from "node:fs/promises";
2
+ // Import directly from compute_status to avoid scene-engine dependency
3
+ // @ts-expect-error - sprig-scenes doesn't have full TypeScript types
4
+ import { computeProjectionStatus } from "@sprig-and-prose/sprig-scenes/attestations/compute-status";
5
+ import { loadManifest } from "../manifest/reader.js";
6
+ export async function handleCheck(config, sceneFilter) {
7
+ const scenesToProcess = sceneFilter
8
+ ? config.scenes.filter((s) => s.scene === sceneFilter)
9
+ : config.scenes;
10
+ if (scenesToProcess.length === 0) {
11
+ if (sceneFilter) {
12
+ console.error(`No scene found with name: ${sceneFilter}`);
13
+ process.exit(1);
14
+ }
15
+ console.log("No scenes configured");
16
+ return;
17
+ }
18
+ for (const sceneConfig of scenesToProcess) {
19
+ await checkScene(sceneConfig);
20
+ }
21
+ }
22
+ async function checkScene(sceneConfig) {
23
+ // Load manifest
24
+ const manifest = await loadManifest(sceneConfig.manifestPath);
25
+ // Load attestations (if they exist)
26
+ let attestations;
27
+ try {
28
+ const text = await readFile(sceneConfig.attestationsPath, "utf-8");
29
+ attestations = JSON.parse(text);
30
+ }
31
+ catch (error) {
32
+ if (error.code === "ENOENT") {
33
+ // No attestations file -> all expectations are EXPECTED
34
+ attestations = {
35
+ version: 1,
36
+ scene: manifest.sceneName,
37
+ generatedAt: new Date().toISOString(),
38
+ actors: {},
39
+ };
40
+ }
41
+ else {
42
+ throw error;
43
+ }
44
+ }
45
+ // Check for manifestId drift
46
+ const manifestId = manifest.meta?.manifestId;
47
+ const attestationManifestId = attestations.manifestId;
48
+ if (manifestId && attestationManifestId && manifestId !== attestationManifestId) {
49
+ console.log(`\n⚠️ ${manifest.sceneName}: Attestations from ${attestationManifestId}, manifest is ${manifestId}`);
50
+ console.log(" Consider re-running: sprig-edge attest");
51
+ }
52
+ // Compute status
53
+ const status = computeProjectionStatus(manifest, attestations);
54
+ // Render status report
55
+ renderStatusReport(manifest.sceneName, status);
56
+ }
57
+ function renderStatusReport(sceneName, status) {
58
+ console.log(`\n📊 Status for ${sceneName}:\n`);
59
+ if (Object.keys(status.actors).length === 0) {
60
+ console.log(" No expectations defined");
61
+ return;
62
+ }
63
+ for (const [actorName, expectations] of Object.entries(status.actors)) {
64
+ console.log(` ${actorName}:`);
65
+ for (const exp of expectations) {
66
+ const icon = getStatusIcon(exp.status);
67
+ const statusText = exp.status.toUpperCase().padEnd(10);
68
+ console.log(` ${icon} ${statusText} → ${exp.location} / ${exp.artifactType} / ${exp.name}`);
69
+ }
70
+ }
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
+ function getStatusIcon(status) {
79
+ switch (status) {
80
+ case "expected":
81
+ return "⚪";
82
+ case "attested":
83
+ return "🟢";
84
+ case "drifted":
85
+ return "🟠";
86
+ case "failed":
87
+ return "🔴";
88
+ default:
89
+ return "❓";
90
+ }
91
+ }
92
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/check/render.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { loadConfig } from "./config/load.js";
4
+ import { handleAttest } from "./attestation/generate.js";
5
+ import { handleCheck } from "./check/render.js";
6
+ import { handleInit } from "./init.js";
7
+ const commands = ["attest", "check", "init"];
8
+ function printHelp() {
9
+ console.log("Usage: sprig-edge <command> [options]");
10
+ console.log("");
11
+ console.log("Commands:");
12
+ console.log(" attest Generate attestations from edge artifacts");
13
+ console.log(" check Check expectations against attestations");
14
+ console.log(" init Generate starter sprig.edge.json config");
15
+ console.log("");
16
+ console.log("Options:");
17
+ console.log(" --config <path> Path to sprig.edge.json (default: ./sprig.edge.json)");
18
+ console.log(" --scene <name> Process only the specified scene");
19
+ }
20
+ function parseArgs() {
21
+ const args = process.argv.slice(2);
22
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
23
+ return { command: null };
24
+ }
25
+ const command = args[0];
26
+ if (!commands.includes(command)) {
27
+ console.error(`Error: Unknown command "${command}"`);
28
+ console.error("Run 'sprig-edge --help' for usage information");
29
+ process.exit(1);
30
+ }
31
+ let configPath;
32
+ let scene;
33
+ for (let i = 1; i < args.length; i++) {
34
+ const arg = args[i];
35
+ if (arg === "--config") {
36
+ const value = args[i + 1];
37
+ if (!value) {
38
+ console.error("Error: --config requires a value");
39
+ process.exit(1);
40
+ }
41
+ configPath = resolve(value);
42
+ i++;
43
+ }
44
+ else if (arg === "--scene") {
45
+ const value = args[i + 1];
46
+ if (!value) {
47
+ console.error("Error: --scene requires a value");
48
+ process.exit(1);
49
+ }
50
+ scene = value;
51
+ i++;
52
+ }
53
+ else {
54
+ console.error(`Error: Unknown option "${arg}"`);
55
+ console.error("Run 'sprig-edge --help' for usage information");
56
+ process.exit(1);
57
+ }
58
+ }
59
+ return { command, configPath, scene };
60
+ }
61
+ async function main() {
62
+ const { command, configPath, scene } = parseArgs();
63
+ if (!command) {
64
+ printHelp();
65
+ process.exit(0);
66
+ }
67
+ try {
68
+ switch (command) {
69
+ case "attest":
70
+ {
71
+ const config = await loadConfig(configPath);
72
+ await handleAttest(config, scene);
73
+ }
74
+ break;
75
+ case "check":
76
+ {
77
+ const config = await loadConfig(configPath);
78
+ await handleCheck(config, scene);
79
+ }
80
+ break;
81
+ case "init":
82
+ await handleInit();
83
+ break;
84
+ }
85
+ }
86
+ catch (error) {
87
+ const message = error instanceof Error ? error.message : String(error);
88
+ console.error(`Error: ${message}`);
89
+ process.exit(1);
90
+ }
91
+ }
92
+ main();
93
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type EdgeConfig } from "./schema.js";
2
+ export declare function loadConfig(configPath?: string): Promise<EdgeConfig>;
3
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9D,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgCzE"}
@@ -0,0 +1,33 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { validateConfig } from "./schema.js";
4
+ const DEFAULT_CONFIG_PATH = "sprig.edge.json";
5
+ export async function loadConfig(configPath) {
6
+ const path = resolve(configPath || DEFAULT_CONFIG_PATH);
7
+ try {
8
+ const text = await readFile(path, "utf-8");
9
+ const data = JSON.parse(text);
10
+ if (!validateConfig(data)) {
11
+ throw new Error("Invalid config format");
12
+ }
13
+ // Resolve all paths relative to config file directory
14
+ const configDir = resolve(path, "..");
15
+ for (const scene of data.scenes) {
16
+ scene.manifestPath = resolve(configDir, scene.manifestPath);
17
+ scene.attestationsPath = resolve(configDir, scene.attestationsPath);
18
+ if (scene.locations) {
19
+ for (const loc of Object.values(scene.locations)) {
20
+ loc.baseDir = resolve(configDir, loc.baseDir);
21
+ }
22
+ }
23
+ }
24
+ return data;
25
+ }
26
+ catch (error) {
27
+ if (error.code === "ENOENT") {
28
+ throw new Error(`Config file not found: ${path}`);
29
+ }
30
+ throw error;
31
+ }
32
+ }
33
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAE9D,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE9B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAED,sDAAsD;QACtD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEtC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5D,KAAK,CAAC,gBAAgB,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAEpE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjD,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Edge configuration schema and types
3
+ */
4
+ export interface EdgeConfig {
5
+ version: 1;
6
+ defaults?: {
7
+ attestationsDir?: string;
8
+ appDir?: string;
9
+ };
10
+ scenes: SceneConfig[];
11
+ }
12
+ export interface SceneConfig {
13
+ scene: string;
14
+ manifestPath: string;
15
+ attestationsPath: string;
16
+ locations?: Record<string, LocationConfig>;
17
+ datasets?: Record<string, DatasetConfig>;
18
+ }
19
+ export interface LocationConfig {
20
+ baseDir: string;
21
+ }
22
+ export interface DatasetConfig {
23
+ files: string[];
24
+ format: "yaml" | "json";
25
+ mode: "array" | "object";
26
+ }
27
+ export declare function validateConfig(config: unknown): config is EdgeConfig;
28
+ //# sourceMappingURL=schema.d.ts.map