@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.
- package/CHANGELOG.md +9 -0
- package/dist/attestation/file-loader.d.ts +5 -0
- package/dist/attestation/file-loader.d.ts.map +1 -0
- package/dist/attestation/file-loader.js +42 -0
- package/dist/attestation/file-loader.js.map +1 -0
- package/dist/attestation/generate.d.ts +3 -0
- package/dist/attestation/generate.d.ts.map +1 -0
- package/dist/attestation/generate.js +134 -0
- package/dist/attestation/generate.js.map +1 -0
- package/dist/attestation/validate-record.d.ts +20 -0
- package/dist/attestation/validate-record.d.ts.map +1 -0
- package/dist/attestation/validate-record.js +93 -0
- package/dist/attestation/validate-record.js.map +1 -0
- package/dist/check/render.d.ts +3 -0
- package/dist/check/render.d.ts.map +1 -0
- package/dist/check/render.js +92 -0
- package/dist/check/render.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/load.d.ts +3 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +33 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/schema.d.ts +28 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +28 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +37 -0
- package/dist/init.js.map +1 -0
- package/dist/manifest/reader.d.ts +26 -0
- package/dist/manifest/reader.d.ts.map +1 -0
- package/dist/manifest/reader.js +18 -0
- package/dist/manifest/reader.js.map +1 -0
- package/package.json +34 -0
- package/src/attestation/file-loader.ts +45 -0
- package/src/attestation/generate.ts +196 -0
- package/src/attestation/validate-record.ts +120 -0
- package/src/check/render.ts +119 -0
- package/src/cli.ts +107 -0
- package/src/config/load.ts +39 -0
- package/src/config/schema.ts +60 -0
- package/src/init.ts +38 -0
- package/src/manifest/reader.ts +47 -0
- package/tsconfig.json +20 -0
package/CHANGELOG.md
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|