@enactprotocol/trust 2.1.15 → 2.1.17
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +181 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +402 -0
- package/dist/manifest.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +18 -0
- package/src/manifest.ts +587 -0
- package/tests/manifest.test.ts +371 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare const version = "0.1.0";
|
|
8
8
|
export { hashContent, hashBuffer, hashFile } from "./hash";
|
|
9
|
+
export { createChecksumManifest, computeManifestHash, verifyChecksumManifest, verifyManifestAttestation, parseChecksumManifest, serializeChecksumManifest, MANIFEST_VERSION, } from "./manifest";
|
|
10
|
+
export type { ChecksumManifest, FileChecksum, CreateManifestOptions, ManifestVerificationResult, ManifestAttestationVerificationResult, } from "./manifest";
|
|
9
11
|
export { generateKeyPair, isValidPEMKey, getKeyTypeFromPEM } from "./keys";
|
|
10
12
|
export * from "./sigstore";
|
|
11
13
|
export type { HashAlgorithm, HashResult, FileHashOptions, KeyType, KeyFormat, KeyPair, KeyGenerationOptions, } from "./types";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAG3D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAG3E,cAAc,YAAY,CAAC;AAG3B,YAAY,EACV,aAAa,EACb,UAAU,EACV,eAAe,EACf,OAAO,EACP,SAAS,EACT,OAAO,EACP,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAG3D,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,0BAA0B,EAC1B,qCAAqC,GACtC,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAG3E,cAAc,YAAY,CAAC;AAG3B,YAAY,EACV,aAAa,EACb,UAAU,EACV,eAAe,EACf,OAAO,EACP,SAAS,EACT,OAAO,EACP,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
export const version = "0.1.0";
|
|
8
8
|
// Hash utilities
|
|
9
9
|
export { hashContent, hashBuffer, hashFile } from "./hash";
|
|
10
|
+
// Checksum manifest (for deterministic signing)
|
|
11
|
+
export { createChecksumManifest, computeManifestHash, verifyChecksumManifest, verifyManifestAttestation, parseChecksumManifest, serializeChecksumManifest, MANIFEST_VERSION, } from "./manifest";
|
|
10
12
|
// Key management
|
|
11
13
|
export { generateKeyPair, isValidPEMKey, getKeyTypeFromPEM } from "./keys";
|
|
12
14
|
// Sigstore integration (attestation signing, verification, trust policies)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE3D,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAE3E,2EAA2E;AAC3E,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE3D,gDAAgD;AAChD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AASpB,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAE3E,2EAA2E;AAC3E,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checksum manifest creation and verification
|
|
3
|
+
*
|
|
4
|
+
* Creates deterministic manifests of file checksums for signing.
|
|
5
|
+
* This enables pre-publish signing by avoiding tar.gz non-determinism.
|
|
6
|
+
*
|
|
7
|
+
* Based on recommendation from Bob Callaway (Google Sigstore team):
|
|
8
|
+
* "Most folks would just create and sign a manifest of checksums."
|
|
9
|
+
*/
|
|
10
|
+
import type { HashResult } from "./types";
|
|
11
|
+
/**
|
|
12
|
+
* Checksum manifest version
|
|
13
|
+
*/
|
|
14
|
+
export declare const MANIFEST_VERSION: "1.0";
|
|
15
|
+
/**
|
|
16
|
+
* Individual file checksum entry
|
|
17
|
+
*/
|
|
18
|
+
export interface FileChecksum {
|
|
19
|
+
/** Relative path from tool root (always uses forward slashes) */
|
|
20
|
+
path: string;
|
|
21
|
+
/** SHA-256 hash of file contents */
|
|
22
|
+
sha256: string;
|
|
23
|
+
/** File size in bytes */
|
|
24
|
+
size: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Complete checksum manifest for a tool
|
|
28
|
+
*/
|
|
29
|
+
export interface ChecksumManifest {
|
|
30
|
+
/** Manifest format version */
|
|
31
|
+
version: typeof MANIFEST_VERSION;
|
|
32
|
+
/** Tool metadata */
|
|
33
|
+
tool: {
|
|
34
|
+
/** Tool name (e.g., "author/tool-name") */
|
|
35
|
+
name: string;
|
|
36
|
+
/** Tool version (e.g., "1.0.0") */
|
|
37
|
+
version: string;
|
|
38
|
+
};
|
|
39
|
+
/** Array of file checksums, sorted by path */
|
|
40
|
+
files: FileChecksum[];
|
|
41
|
+
/** Hash of the manifest itself (for signing) */
|
|
42
|
+
manifestHash: {
|
|
43
|
+
algorithm: "sha256";
|
|
44
|
+
digest: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Options for creating a checksum manifest
|
|
49
|
+
*/
|
|
50
|
+
export interface CreateManifestOptions {
|
|
51
|
+
/** Patterns to ignore (glob-style, relative to tool root) */
|
|
52
|
+
ignorePatterns?: string[] | undefined;
|
|
53
|
+
/** Progress callback for each file processed */
|
|
54
|
+
onProgress?: ((file: string) => void) | undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Result of manifest verification
|
|
58
|
+
*/
|
|
59
|
+
export interface ManifestVerificationResult {
|
|
60
|
+
/** Whether all files match the manifest */
|
|
61
|
+
valid: boolean;
|
|
62
|
+
/** Error messages if verification failed */
|
|
63
|
+
errors?: string[] | undefined;
|
|
64
|
+
/** Files in manifest but missing from directory */
|
|
65
|
+
missingFiles?: string[] | undefined;
|
|
66
|
+
/** Files that exist but have different hashes */
|
|
67
|
+
modifiedFiles?: string[] | undefined;
|
|
68
|
+
/** Files in directory but not in manifest */
|
|
69
|
+
extraFiles?: string[] | undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a checksum manifest for a tool directory
|
|
73
|
+
*
|
|
74
|
+
* Scans all files in the directory, computes SHA-256 hashes,
|
|
75
|
+
* and creates a manifest suitable for signing.
|
|
76
|
+
*
|
|
77
|
+
* @param toolDir - Path to the tool directory
|
|
78
|
+
* @param toolName - Tool name (e.g., "author/tool-name")
|
|
79
|
+
* @param toolVersion - Tool version (e.g., "1.0.0")
|
|
80
|
+
* @param options - Optional settings for ignore patterns and progress
|
|
81
|
+
* @returns Complete checksum manifest ready for signing
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const manifest = await createChecksumManifest(
|
|
86
|
+
* "./my-tool",
|
|
87
|
+
* "alice/my-tool",
|
|
88
|
+
* "1.0.0",
|
|
89
|
+
* { onProgress: (file) => console.log(`Hashing: ${file}`) }
|
|
90
|
+
* );
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function createChecksumManifest(toolDir: string, toolName: string, toolVersion: string, options?: CreateManifestOptions): Promise<ChecksumManifest>;
|
|
94
|
+
/**
|
|
95
|
+
* Compute the canonical hash of a manifest (for signing)
|
|
96
|
+
*
|
|
97
|
+
* Creates a deterministic hash by:
|
|
98
|
+
* 1. Excluding the manifestHash field itself
|
|
99
|
+
* 2. Using canonical JSON (sorted keys, no whitespace)
|
|
100
|
+
* 3. Computing SHA-256
|
|
101
|
+
*
|
|
102
|
+
* @param manifest - The manifest to hash (manifestHash field is ignored)
|
|
103
|
+
* @returns Hash result with algorithm and digest
|
|
104
|
+
*/
|
|
105
|
+
export declare function computeManifestHash(manifest: Omit<ChecksumManifest, "manifestHash"> | ChecksumManifest): HashResult;
|
|
106
|
+
/**
|
|
107
|
+
* Verify that files in a directory match a checksum manifest
|
|
108
|
+
*
|
|
109
|
+
* @param toolDir - Path to the tool directory
|
|
110
|
+
* @param manifest - The manifest to verify against
|
|
111
|
+
* @param options - Optional settings for ignore patterns
|
|
112
|
+
* @returns Verification result with details on any mismatches
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const result = await verifyChecksumManifest("./my-tool", manifest);
|
|
117
|
+
* if (!result.valid) {
|
|
118
|
+
* console.error("Verification failed:", result.errors);
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export declare function verifyChecksumManifest(toolDir: string, manifest: ChecksumManifest, options?: {
|
|
123
|
+
ignorePatterns?: string[];
|
|
124
|
+
}): Promise<ManifestVerificationResult>;
|
|
125
|
+
/**
|
|
126
|
+
* Parse a checksum manifest from JSON string
|
|
127
|
+
*
|
|
128
|
+
* @param json - JSON string containing the manifest
|
|
129
|
+
* @returns Parsed manifest
|
|
130
|
+
* @throws Error if JSON is invalid or manifest structure is wrong
|
|
131
|
+
*/
|
|
132
|
+
export declare function parseChecksumManifest(json: string): ChecksumManifest;
|
|
133
|
+
/**
|
|
134
|
+
* Serialize a checksum manifest to JSON string (pretty-printed for storage)
|
|
135
|
+
*
|
|
136
|
+
* @param manifest - The manifest to serialize
|
|
137
|
+
* @returns Pretty-printed JSON string
|
|
138
|
+
*/
|
|
139
|
+
export declare function serializeChecksumManifest(manifest: ChecksumManifest): string;
|
|
140
|
+
/**
|
|
141
|
+
* Result of verifying a manifest attestation
|
|
142
|
+
*/
|
|
143
|
+
export interface ManifestAttestationVerificationResult {
|
|
144
|
+
/** Whether the attestation is valid */
|
|
145
|
+
valid: boolean;
|
|
146
|
+
/** The auditor identity (email) from the certificate */
|
|
147
|
+
auditor?: string | undefined;
|
|
148
|
+
/** The OIDC provider used for signing */
|
|
149
|
+
provider?: string | undefined;
|
|
150
|
+
/** Error message if verification failed */
|
|
151
|
+
error?: string | undefined;
|
|
152
|
+
/** Detailed verification results */
|
|
153
|
+
details?: {
|
|
154
|
+
/** Whether the Sigstore bundle was verified */
|
|
155
|
+
bundleVerified: boolean;
|
|
156
|
+
/** Whether the manifest hash matches what was signed */
|
|
157
|
+
manifestHashMatches: boolean;
|
|
158
|
+
/** Whether the manifest matches the current files */
|
|
159
|
+
manifestMatchesFiles?: boolean | undefined;
|
|
160
|
+
} | undefined;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Verify a manifest-based attestation
|
|
164
|
+
*
|
|
165
|
+
* This verifies that:
|
|
166
|
+
* 1. The Sigstore bundle is valid
|
|
167
|
+
* 2. The bundle was signed over the manifest hash
|
|
168
|
+
* 3. Optionally, the manifest matches the current files on disk
|
|
169
|
+
*
|
|
170
|
+
* @param manifest - The checksum manifest that was signed
|
|
171
|
+
* @param sigstoreBundle - The Sigstore bundle containing the signature
|
|
172
|
+
* @param options - Verification options
|
|
173
|
+
* @returns Verification result
|
|
174
|
+
*/
|
|
175
|
+
export declare function verifyManifestAttestation(manifest: ChecksumManifest, sigstoreBundle: unknown, options?: {
|
|
176
|
+
/** If provided, also verify manifest matches files in this directory */
|
|
177
|
+
toolDir?: string | undefined;
|
|
178
|
+
/** Additional patterns to ignore when verifying against directory */
|
|
179
|
+
ignorePatterns?: string[] | undefined;
|
|
180
|
+
}): Promise<ManifestAttestationVerificationResult>;
|
|
181
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAM1C;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAG,KAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,oBAAoB;IACpB,IAAI,EAAE;QACJ,2CAA2C;QAC3C,IAAI,EAAE,MAAM,CAAC;QACb,mCAAmC;QACnC,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,8CAA8C;IAC9C,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,gDAAgD;IAChD,YAAY,EAAE;QACZ,SAAS,EAAE,QAAQ,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,gDAAgD;IAChD,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,2CAA2C;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACrC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACnC;AAkJD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAsD3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,GAAG,gBAAgB,GAClE,UAAU,CAOZ;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC1C,OAAO,CAAC,0BAA0B,CAAC,CA8DrC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAuBpE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAE5E;AAMD;;GAEG;AACH,MAAM,WAAW,qCAAqC;IACpD,uCAAuC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,oCAAoC;IACpC,OAAO,CAAC,EACJ;QACE,+CAA+C;QAC/C,cAAc,EAAE,OAAO,CAAC;QACxB,wDAAwD;QACxD,mBAAmB,EAAE,OAAO,CAAC;QAC7B,qDAAqD;QACrD,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC5C,GACD,SAAS,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,gBAAgB,EAC1B,cAAc,EAAE,OAAO,EACvB,OAAO,GAAE;IACP,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAClC,GACL,OAAO,CAAC,qCAAqC,CAAC,CA4EhD"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checksum manifest creation and verification
|
|
3
|
+
*
|
|
4
|
+
* Creates deterministic manifests of file checksums for signing.
|
|
5
|
+
* This enables pre-publish signing by avoiding tar.gz non-determinism.
|
|
6
|
+
*
|
|
7
|
+
* Based on recommendation from Bob Callaway (Google Sigstore team):
|
|
8
|
+
* "Most folks would just create and sign a manifest of checksums."
|
|
9
|
+
*/
|
|
10
|
+
import { readdirSync, statSync } from "node:fs";
|
|
11
|
+
import { join, posix, relative, sep } from "node:path";
|
|
12
|
+
import { hashContent, hashFile } from "./hash";
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Types
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Checksum manifest version
|
|
18
|
+
*/
|
|
19
|
+
export const MANIFEST_VERSION = "1.0";
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Default Ignore Patterns
|
|
22
|
+
// ============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Files that should always be ignored when creating manifests
|
|
25
|
+
*/
|
|
26
|
+
const ALWAYS_IGNORE = [
|
|
27
|
+
// Manifest artifacts (we're creating these)
|
|
28
|
+
".enact-manifest.json",
|
|
29
|
+
".sigstore-bundle.json",
|
|
30
|
+
// Version control
|
|
31
|
+
".git",
|
|
32
|
+
".gitignore",
|
|
33
|
+
".gitattributes",
|
|
34
|
+
// OS artifacts
|
|
35
|
+
".DS_Store",
|
|
36
|
+
"Thumbs.db",
|
|
37
|
+
// IDE/Editor
|
|
38
|
+
".vscode",
|
|
39
|
+
".idea",
|
|
40
|
+
"*.swp",
|
|
41
|
+
"*.swo",
|
|
42
|
+
// Dependencies (should be installed, not bundled)
|
|
43
|
+
"node_modules",
|
|
44
|
+
"__pycache__",
|
|
45
|
+
".pytest_cache",
|
|
46
|
+
"*.pyc",
|
|
47
|
+
"*.pyo",
|
|
48
|
+
// Build artifacts
|
|
49
|
+
"dist",
|
|
50
|
+
"build",
|
|
51
|
+
".next",
|
|
52
|
+
// Logs
|
|
53
|
+
"*.log",
|
|
54
|
+
"npm-debug.log*",
|
|
55
|
+
];
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Helper Functions
|
|
58
|
+
// ============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Check if a path should be ignored
|
|
61
|
+
*/
|
|
62
|
+
function shouldIgnore(relativePath, fileName, customPatterns = []) {
|
|
63
|
+
const allPatterns = [...ALWAYS_IGNORE, ...customPatterns];
|
|
64
|
+
for (const pattern of allPatterns) {
|
|
65
|
+
// Exact match
|
|
66
|
+
if (pattern === fileName || pattern === relativePath) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// Glob pattern matching (simplified)
|
|
70
|
+
if (pattern.startsWith("*")) {
|
|
71
|
+
const suffix = pattern.slice(1);
|
|
72
|
+
if (fileName.endsWith(suffix) || relativePath.endsWith(suffix)) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Directory pattern (pattern without extension matches directories)
|
|
77
|
+
if (!pattern.includes(".") && !pattern.includes("*")) {
|
|
78
|
+
if (relativePath.startsWith(`${pattern}/`) || relativePath === pattern) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Normalize path to use forward slashes (for cross-platform consistency)
|
|
87
|
+
*/
|
|
88
|
+
function normalizePath(filePath) {
|
|
89
|
+
return filePath.split(sep).join(posix.sep);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Recursively collect all files in a directory
|
|
93
|
+
*/
|
|
94
|
+
function collectFiles(dir, baseDir, ignorePatterns, files = []) {
|
|
95
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
const fullPath = join(dir, entry.name);
|
|
98
|
+
const relativePath = normalizePath(relative(baseDir, fullPath));
|
|
99
|
+
// Check if should be ignored
|
|
100
|
+
if (shouldIgnore(relativePath, entry.name, ignorePatterns)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (entry.isDirectory()) {
|
|
104
|
+
collectFiles(fullPath, baseDir, ignorePatterns, files);
|
|
105
|
+
}
|
|
106
|
+
else if (entry.isFile()) {
|
|
107
|
+
files.push(fullPath);
|
|
108
|
+
}
|
|
109
|
+
// Skip symlinks and other special files
|
|
110
|
+
}
|
|
111
|
+
return files;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create canonical JSON string for hashing
|
|
115
|
+
*
|
|
116
|
+
* - Sorts object keys recursively
|
|
117
|
+
* - No whitespace (minified)
|
|
118
|
+
* - Consistent output across platforms
|
|
119
|
+
*/
|
|
120
|
+
function canonicalJSON(obj) {
|
|
121
|
+
if (obj === null || typeof obj !== "object") {
|
|
122
|
+
return JSON.stringify(obj);
|
|
123
|
+
}
|
|
124
|
+
if (Array.isArray(obj)) {
|
|
125
|
+
return `[${obj.map(canonicalJSON).join(",")}]`;
|
|
126
|
+
}
|
|
127
|
+
// Sort keys and recursively process
|
|
128
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
129
|
+
const pairs = sortedKeys.map((key) => `${JSON.stringify(key)}:${canonicalJSON(obj[key])}`);
|
|
130
|
+
return `{${pairs.join(",")}}`;
|
|
131
|
+
}
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Main Functions
|
|
134
|
+
// ============================================================================
|
|
135
|
+
/**
|
|
136
|
+
* Create a checksum manifest for a tool directory
|
|
137
|
+
*
|
|
138
|
+
* Scans all files in the directory, computes SHA-256 hashes,
|
|
139
|
+
* and creates a manifest suitable for signing.
|
|
140
|
+
*
|
|
141
|
+
* @param toolDir - Path to the tool directory
|
|
142
|
+
* @param toolName - Tool name (e.g., "author/tool-name")
|
|
143
|
+
* @param toolVersion - Tool version (e.g., "1.0.0")
|
|
144
|
+
* @param options - Optional settings for ignore patterns and progress
|
|
145
|
+
* @returns Complete checksum manifest ready for signing
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const manifest = await createChecksumManifest(
|
|
150
|
+
* "./my-tool",
|
|
151
|
+
* "alice/my-tool",
|
|
152
|
+
* "1.0.0",
|
|
153
|
+
* { onProgress: (file) => console.log(`Hashing: ${file}`) }
|
|
154
|
+
* );
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export async function createChecksumManifest(toolDir, toolName, toolVersion, options = {}) {
|
|
158
|
+
const { ignorePatterns = [], onProgress } = options;
|
|
159
|
+
// Collect all files
|
|
160
|
+
const filePaths = collectFiles(toolDir, toolDir, ignorePatterns);
|
|
161
|
+
// Hash each file
|
|
162
|
+
const fileChecksums = [];
|
|
163
|
+
for (const filePath of filePaths) {
|
|
164
|
+
const relativePath = normalizePath(relative(toolDir, filePath));
|
|
165
|
+
if (onProgress) {
|
|
166
|
+
onProgress(relativePath);
|
|
167
|
+
}
|
|
168
|
+
const stats = statSync(filePath);
|
|
169
|
+
const hashResult = await hashFile(filePath);
|
|
170
|
+
fileChecksums.push({
|
|
171
|
+
path: relativePath,
|
|
172
|
+
sha256: hashResult.digest,
|
|
173
|
+
size: stats.size,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// Sort by path for deterministic ordering (using simple string comparison)
|
|
177
|
+
fileChecksums.sort((a, b) => {
|
|
178
|
+
if (a.path < b.path)
|
|
179
|
+
return -1;
|
|
180
|
+
if (a.path > b.path)
|
|
181
|
+
return 1;
|
|
182
|
+
return 0;
|
|
183
|
+
});
|
|
184
|
+
// Create manifest without the hash first
|
|
185
|
+
const manifestWithoutHash = {
|
|
186
|
+
version: MANIFEST_VERSION,
|
|
187
|
+
tool: {
|
|
188
|
+
name: toolName,
|
|
189
|
+
version: toolVersion,
|
|
190
|
+
},
|
|
191
|
+
files: fileChecksums,
|
|
192
|
+
};
|
|
193
|
+
// Compute manifest hash from canonical JSON
|
|
194
|
+
const manifestHash = computeManifestHash(manifestWithoutHash);
|
|
195
|
+
// Return complete manifest
|
|
196
|
+
return {
|
|
197
|
+
...manifestWithoutHash,
|
|
198
|
+
manifestHash: {
|
|
199
|
+
algorithm: "sha256",
|
|
200
|
+
digest: manifestHash.digest,
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Compute the canonical hash of a manifest (for signing)
|
|
206
|
+
*
|
|
207
|
+
* Creates a deterministic hash by:
|
|
208
|
+
* 1. Excluding the manifestHash field itself
|
|
209
|
+
* 2. Using canonical JSON (sorted keys, no whitespace)
|
|
210
|
+
* 3. Computing SHA-256
|
|
211
|
+
*
|
|
212
|
+
* @param manifest - The manifest to hash (manifestHash field is ignored)
|
|
213
|
+
* @returns Hash result with algorithm and digest
|
|
214
|
+
*/
|
|
215
|
+
export function computeManifestHash(manifest) {
|
|
216
|
+
// Create a copy without manifestHash
|
|
217
|
+
const { manifestHash: _, ...manifestWithoutHash } = manifest;
|
|
218
|
+
// Compute canonical JSON and hash
|
|
219
|
+
const canonical = canonicalJSON(manifestWithoutHash);
|
|
220
|
+
return hashContent(canonical, "sha256");
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Verify that files in a directory match a checksum manifest
|
|
224
|
+
*
|
|
225
|
+
* @param toolDir - Path to the tool directory
|
|
226
|
+
* @param manifest - The manifest to verify against
|
|
227
|
+
* @param options - Optional settings for ignore patterns
|
|
228
|
+
* @returns Verification result with details on any mismatches
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```ts
|
|
232
|
+
* const result = await verifyChecksumManifest("./my-tool", manifest);
|
|
233
|
+
* if (!result.valid) {
|
|
234
|
+
* console.error("Verification failed:", result.errors);
|
|
235
|
+
* }
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
export async function verifyChecksumManifest(toolDir, manifest, options = {}) {
|
|
239
|
+
const { ignorePatterns = [] } = options;
|
|
240
|
+
const errors = [];
|
|
241
|
+
const missingFiles = [];
|
|
242
|
+
const modifiedFiles = [];
|
|
243
|
+
const extraFiles = [];
|
|
244
|
+
// First, verify the manifest hash itself
|
|
245
|
+
const computedHash = computeManifestHash(manifest);
|
|
246
|
+
if (computedHash.digest !== manifest.manifestHash.digest) {
|
|
247
|
+
errors.push(`Manifest hash mismatch: expected ${manifest.manifestHash.digest}, got ${computedHash.digest}`);
|
|
248
|
+
}
|
|
249
|
+
// Collect current files in directory
|
|
250
|
+
const currentFilePaths = collectFiles(toolDir, toolDir, ignorePatterns);
|
|
251
|
+
const currentFiles = new Set(currentFilePaths.map((fp) => normalizePath(relative(toolDir, fp))));
|
|
252
|
+
// Check each file in manifest
|
|
253
|
+
const manifestFiles = new Set();
|
|
254
|
+
for (const fileEntry of manifest.files) {
|
|
255
|
+
manifestFiles.add(fileEntry.path);
|
|
256
|
+
const fullPath = join(toolDir, fileEntry.path);
|
|
257
|
+
// Check if file exists
|
|
258
|
+
if (!currentFiles.has(fileEntry.path)) {
|
|
259
|
+
missingFiles.push(fileEntry.path);
|
|
260
|
+
errors.push(`Missing file: ${fileEntry.path}`);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
// Check hash
|
|
264
|
+
try {
|
|
265
|
+
const hashResult = await hashFile(fullPath);
|
|
266
|
+
if (hashResult.digest !== fileEntry.sha256) {
|
|
267
|
+
modifiedFiles.push(fileEntry.path);
|
|
268
|
+
errors.push(`Modified file: ${fileEntry.path} (expected ${fileEntry.sha256.slice(0, 12)}..., got ${hashResult.digest.slice(0, 12)}...)`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
errors.push(`Failed to hash file ${fileEntry.path}: ${err}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Check for extra files not in manifest
|
|
276
|
+
for (const currentFile of currentFiles) {
|
|
277
|
+
if (!manifestFiles.has(currentFile)) {
|
|
278
|
+
extraFiles.push(currentFile);
|
|
279
|
+
errors.push(`Extra file not in manifest: ${currentFile}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
valid: errors.length === 0,
|
|
284
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
285
|
+
missingFiles: missingFiles.length > 0 ? missingFiles : undefined,
|
|
286
|
+
modifiedFiles: modifiedFiles.length > 0 ? modifiedFiles : undefined,
|
|
287
|
+
extraFiles: extraFiles.length > 0 ? extraFiles : undefined,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Parse a checksum manifest from JSON string
|
|
292
|
+
*
|
|
293
|
+
* @param json - JSON string containing the manifest
|
|
294
|
+
* @returns Parsed manifest
|
|
295
|
+
* @throws Error if JSON is invalid or manifest structure is wrong
|
|
296
|
+
*/
|
|
297
|
+
export function parseChecksumManifest(json) {
|
|
298
|
+
const parsed = JSON.parse(json);
|
|
299
|
+
// Validate structure
|
|
300
|
+
if (!parsed.version || parsed.version !== MANIFEST_VERSION) {
|
|
301
|
+
throw new Error(`Invalid manifest version: expected ${MANIFEST_VERSION}, got ${parsed.version}`);
|
|
302
|
+
}
|
|
303
|
+
if (!parsed.tool?.name || !parsed.tool?.version) {
|
|
304
|
+
throw new Error("Invalid manifest: missing tool name or version");
|
|
305
|
+
}
|
|
306
|
+
if (!Array.isArray(parsed.files)) {
|
|
307
|
+
throw new Error("Invalid manifest: files must be an array");
|
|
308
|
+
}
|
|
309
|
+
if (!parsed.manifestHash?.algorithm || !parsed.manifestHash?.digest) {
|
|
310
|
+
throw new Error("Invalid manifest: missing manifestHash");
|
|
311
|
+
}
|
|
312
|
+
return parsed;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Serialize a checksum manifest to JSON string (pretty-printed for storage)
|
|
316
|
+
*
|
|
317
|
+
* @param manifest - The manifest to serialize
|
|
318
|
+
* @returns Pretty-printed JSON string
|
|
319
|
+
*/
|
|
320
|
+
export function serializeChecksumManifest(manifest) {
|
|
321
|
+
return JSON.stringify(manifest, null, 2);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Verify a manifest-based attestation
|
|
325
|
+
*
|
|
326
|
+
* This verifies that:
|
|
327
|
+
* 1. The Sigstore bundle is valid
|
|
328
|
+
* 2. The bundle was signed over the manifest hash
|
|
329
|
+
* 3. Optionally, the manifest matches the current files on disk
|
|
330
|
+
*
|
|
331
|
+
* @param manifest - The checksum manifest that was signed
|
|
332
|
+
* @param sigstoreBundle - The Sigstore bundle containing the signature
|
|
333
|
+
* @param options - Verification options
|
|
334
|
+
* @returns Verification result
|
|
335
|
+
*/
|
|
336
|
+
export async function verifyManifestAttestation(manifest, sigstoreBundle, options = {}) {
|
|
337
|
+
// Dynamic import to avoid circular dependencies
|
|
338
|
+
const { verifyBundle, extractIdentityFromBundle } = await import("./sigstore");
|
|
339
|
+
try {
|
|
340
|
+
// Get the manifest hash that should have been signed
|
|
341
|
+
const expectedHash = manifest.manifestHash.digest;
|
|
342
|
+
// Convert hash to Buffer for verification
|
|
343
|
+
const hashBuffer = Buffer.from(expectedHash.match(/.{1,2}/g).map((byte) => Number.parseInt(byte, 16)));
|
|
344
|
+
// Cast the bundle to the expected type
|
|
345
|
+
const bundle = sigstoreBundle;
|
|
346
|
+
// Verify the Sigstore bundle
|
|
347
|
+
const bundleResult = await verifyBundle(bundle, hashBuffer);
|
|
348
|
+
if (!bundleResult.verified) {
|
|
349
|
+
return {
|
|
350
|
+
valid: false,
|
|
351
|
+
error: bundleResult.error ?? "Sigstore bundle verification failed",
|
|
352
|
+
details: {
|
|
353
|
+
bundleVerified: false,
|
|
354
|
+
manifestHashMatches: false,
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
// Extract identity from the bundle
|
|
359
|
+
const identity = extractIdentityFromBundle(bundle);
|
|
360
|
+
// If toolDir is provided, also verify manifest matches files
|
|
361
|
+
let manifestMatchesFiles;
|
|
362
|
+
if (options.toolDir) {
|
|
363
|
+
const ignoreOpts = options.ignorePatterns ? { ignorePatterns: options.ignorePatterns } : {};
|
|
364
|
+
const fileVerification = await verifyChecksumManifest(options.toolDir, manifest, ignoreOpts);
|
|
365
|
+
manifestMatchesFiles = fileVerification.valid;
|
|
366
|
+
if (!fileVerification.valid) {
|
|
367
|
+
return {
|
|
368
|
+
valid: false,
|
|
369
|
+
auditor: identity?.email ?? identity?.subject,
|
|
370
|
+
provider: identity?.issuer,
|
|
371
|
+
error: `Manifest does not match files: ${fileVerification.errors?.join(", ")}`,
|
|
372
|
+
details: {
|
|
373
|
+
bundleVerified: true,
|
|
374
|
+
manifestHashMatches: true,
|
|
375
|
+
manifestMatchesFiles: false,
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
valid: true,
|
|
382
|
+
auditor: identity?.email ?? identity?.subject,
|
|
383
|
+
provider: identity?.issuer,
|
|
384
|
+
details: {
|
|
385
|
+
bundleVerified: true,
|
|
386
|
+
manifestHashMatches: true,
|
|
387
|
+
manifestMatchesFiles,
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
return {
|
|
393
|
+
valid: false,
|
|
394
|
+
error: `Verification failed: ${error.message}`,
|
|
395
|
+
details: {
|
|
396
|
+
bundleVerified: false,
|
|
397
|
+
manifestHashMatches: false,
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -10,6 +10,24 @@ export const version = "0.1.0";
|
|
|
10
10
|
// Hash utilities
|
|
11
11
|
export { hashContent, hashBuffer, hashFile } from "./hash";
|
|
12
12
|
|
|
13
|
+
// Checksum manifest (for deterministic signing)
|
|
14
|
+
export {
|
|
15
|
+
createChecksumManifest,
|
|
16
|
+
computeManifestHash,
|
|
17
|
+
verifyChecksumManifest,
|
|
18
|
+
verifyManifestAttestation,
|
|
19
|
+
parseChecksumManifest,
|
|
20
|
+
serializeChecksumManifest,
|
|
21
|
+
MANIFEST_VERSION,
|
|
22
|
+
} from "./manifest";
|
|
23
|
+
export type {
|
|
24
|
+
ChecksumManifest,
|
|
25
|
+
FileChecksum,
|
|
26
|
+
CreateManifestOptions,
|
|
27
|
+
ManifestVerificationResult,
|
|
28
|
+
ManifestAttestationVerificationResult,
|
|
29
|
+
} from "./manifest";
|
|
30
|
+
|
|
13
31
|
// Key management
|
|
14
32
|
export { generateKeyPair, isValidPEMKey, getKeyTypeFromPEM } from "./keys";
|
|
15
33
|
|