@effected/sbom 0.1.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/IdentityToken.js +65 -0
- package/InTotoStatement.js +159 -0
- package/LICENSE +21 -0
- package/NtiaReport.js +142 -0
- package/Sbom.js +100 -0
- package/SbomDocument.js +223 -0
- package/SbomMetadataSource.js +202 -0
- package/SigstoreBundle.js +48 -0
- package/SigstoreSigner.js +150 -0
- package/SlsaProvenance.js +145 -0
- package/index.d.ts +1034 -0
- package/index.js +11 -0
- package/package.json +53 -0
- package/tsdoc-metadata.json +11 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,1034 @@
|
|
|
1
|
+
import { Brand, Context, Effect, FileSystem, Layer, Redacted, Result, Schema } from "effect";
|
|
2
|
+
import { Package } from "@effected/package-json";
|
|
3
|
+
import { Signer, Witness } from "@sigstore/sign";
|
|
4
|
+
//#region src/IdentityToken.d.ts
|
|
5
|
+
declare const IdentityTokenError_base: Schema.Class<IdentityTokenError, Schema.TaggedStruct<"IdentityTokenError", {
|
|
6
|
+
/** The audience the token was requested for. */
|
|
7
|
+
readonly audience: Schema.String;
|
|
8
|
+
/** The underlying failure, preserved structurally. */
|
|
9
|
+
readonly cause: Schema.Defect;
|
|
10
|
+
}>, import("effect/Cause").YieldableError>;
|
|
11
|
+
/**
|
|
12
|
+
* Raised when an identity token cannot be obtained.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* The audience is on the error because "which audience" is the first thing a
|
|
16
|
+
* caller checks when an exchange is refused — a token minted for the wrong one
|
|
17
|
+
* fails at the certificate authority, far from here.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
declare class IdentityTokenError extends IdentityTokenError_base {
|
|
22
|
+
get message(): string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The contract: one method, one audience, one redacted token.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Deliberately smaller than any issuer's own surface. An implementation may
|
|
29
|
+
* cache, may decode claims, may do neither — none of that is this package's
|
|
30
|
+
* business, and a wider contract would make github-actions' issuer the only
|
|
31
|
+
* thing that could satisfy it.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
interface IdentityTokenShape {
|
|
36
|
+
/** A workload identity token for `audience`. */
|
|
37
|
+
readonly token: (audience: string) => Effect.Effect<Redacted.Redacted<string>, IdentityTokenError>;
|
|
38
|
+
}
|
|
39
|
+
declare const IdentityToken_base: Context.ServiceClass<IdentityToken, "@effected/sbom/IdentityToken", IdentityTokenShape>;
|
|
40
|
+
/**
|
|
41
|
+
* A source of workload identity tokens.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { IdentityToken, SigstoreSigner } from "@effected/sbom";
|
|
46
|
+
* import { Layer } from "effect";
|
|
47
|
+
*
|
|
48
|
+
* const layer = SigstoreSigner.layer.pipe(Layer.provide(IdentityToken.layerStatic(token)));
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
declare class IdentityToken extends IdentityToken_base {
|
|
54
|
+
/**
|
|
55
|
+
* A layer answering with a token the caller already holds.
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* For a consumer that obtained a token by some other route — a CI system
|
|
59
|
+
* that is not GitHub Actions, or a script that exchanged one itself. The
|
|
60
|
+
* audience is **ignored**, so it is the caller's job to have minted the token
|
|
61
|
+
* for the audience it will be used with; a layer cannot check that, and
|
|
62
|
+
* pretending otherwise would be theatre.
|
|
63
|
+
*/
|
|
64
|
+
static readonly layerStatic: (token: Redacted.Redacted<string> | string) => Layer.Layer<IdentityToken>;
|
|
65
|
+
/**
|
|
66
|
+
* An in-memory double.
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* Unlike {@link (SigstoreSigner:class).makeTest}, this one **answers** rather than
|
|
70
|
+
* dying: a fabricated OIDC token is a real answer to "give me a token" in a
|
|
71
|
+
* test, where a fabricated signature would be a lie about cryptography.
|
|
72
|
+
*/
|
|
73
|
+
static readonly makeTest: (overrides?: Partial<IdentityTokenShape>) => IdentityTokenShape;
|
|
74
|
+
/** {@link (IdentityToken:class).makeTest} behind a `Layer`. */
|
|
75
|
+
static readonly layerTest: (overrides?: Partial<IdentityTokenShape>) => Layer.Layer<IdentityToken>;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/InTotoStatement.d.ts
|
|
79
|
+
/**
|
|
80
|
+
* The in-toto Statement v1 type URI, stamped onto every statement this package
|
|
81
|
+
* emits.
|
|
82
|
+
*
|
|
83
|
+
* @see {@link https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md | in-toto Statement v1}
|
|
84
|
+
*
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
declare const IN_TOTO_STATEMENT_V1: "https://in-toto.io/Statement/v1";
|
|
88
|
+
/**
|
|
89
|
+
* The CycloneDX BOM predicate type, for attesting an SBOM.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
declare const CYCLONEDX_BOM_PREDICATE: "https://cyclonedx.org/bom";
|
|
94
|
+
/**
|
|
95
|
+
* The URI naming what a statement asserts about its subjects.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* Deliberately an open string rather than a union: the predicate vocabulary is
|
|
99
|
+
* extensible by design, and a closed union here would refuse a valid statement
|
|
100
|
+
* for a predicate type this package has never heard of.
|
|
101
|
+
* {@link (SlsaProvenance:class).predicateType} and {@link CYCLONEDX_BOM_PREDICATE}
|
|
102
|
+
* are the two the kit produces.
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
type PredicateType = string;
|
|
107
|
+
declare const InvalidSha256DigestError_base: Schema.Class<InvalidSha256DigestError, Schema.TaggedStruct<"InvalidSha256DigestError", {
|
|
108
|
+
/** The offending input, preserved verbatim. */
|
|
109
|
+
readonly input: Schema.String;
|
|
110
|
+
}>, import("effect/Cause").YieldableError>;
|
|
111
|
+
/**
|
|
112
|
+
* Raised when a string is not a SHA-256 digest.
|
|
113
|
+
*
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
declare class InvalidSha256DigestError extends InvalidSha256DigestError_base {
|
|
117
|
+
get message(): string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A SHA-256 digest as 64 lowercase hexadecimal characters, without an
|
|
121
|
+
* algorithm prefix.
|
|
122
|
+
*
|
|
123
|
+
* @remarks
|
|
124
|
+
* A deliberate small duplication rather than a shared package: `@effected/github`
|
|
125
|
+
* types the same value structurally on its attestation surface, and dragging a
|
|
126
|
+
* package across that seam to share one branded string would cost more than the
|
|
127
|
+
* duplication does. Recorded under the program's shared-vocabulary rule.
|
|
128
|
+
*
|
|
129
|
+
* @public
|
|
130
|
+
*/
|
|
131
|
+
declare const Sha256Digest: Schema.brand<Schema.String, "Sha256Digest"> & {
|
|
132
|
+
isValid: (value: string) => boolean;
|
|
133
|
+
parseResult: (value: string) => Result.Result<Sha256Digest, InvalidSha256DigestError>;
|
|
134
|
+
parse: (value: string) => Effect.Effect<Sha256Digest, InvalidSha256DigestError, never>;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* A SHA-256 digest as 64 lowercase hexadecimal characters.
|
|
138
|
+
*
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
type Sha256Digest = string & Brand.Brand<"Sha256Digest">;
|
|
142
|
+
declare const InTotoSubject_base: Schema.Class<InTotoSubject, Schema.Struct<{
|
|
143
|
+
/** How the subject is identified — a purl for an npm package. */
|
|
144
|
+
readonly name: Schema.String;
|
|
145
|
+
/** Algorithm to hex digest. */
|
|
146
|
+
readonly digest: Schema.$Record<Schema.String, Schema.String>;
|
|
147
|
+
}>, {}>;
|
|
148
|
+
/**
|
|
149
|
+
* A content-addressed artifact an attestation is about.
|
|
150
|
+
*
|
|
151
|
+
* @remarks
|
|
152
|
+
* `name` is conventionally a package URL (`pkg:npm/%40scope/name@1.0.0`), but
|
|
153
|
+
* the specification requires only that it be unique within the statement.
|
|
154
|
+
* `digest` is an open algorithm → hex map because in-toto permits several; this
|
|
155
|
+
* package writes `sha256`.
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
declare class InTotoSubject extends InTotoSubject_base {
|
|
160
|
+
/**
|
|
161
|
+
* A subject identified by a SHA-256 digest.
|
|
162
|
+
*
|
|
163
|
+
* @remarks
|
|
164
|
+
* **Total** — the digest is already validated, which is what
|
|
165
|
+
* {@link (Sha256Digest:variable).parseResult} is for.
|
|
166
|
+
*/
|
|
167
|
+
static forSha256(name: string, digest: Sha256Digest): InTotoSubject;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Input to {@link (InTotoStatement:class).of}.
|
|
171
|
+
*
|
|
172
|
+
* @remarks
|
|
173
|
+
* The two predicate members are spelled out here and again on
|
|
174
|
+
* {@link InTotoSubjectInput} rather than shared through a base interface: an
|
|
175
|
+
* internal type named on a `@public` signature is a forgotten export, and a
|
|
176
|
+
* named alias is still a named symbol. Structural duplication is the only form
|
|
177
|
+
* the API gate accepts.
|
|
178
|
+
*
|
|
179
|
+
* @public
|
|
180
|
+
*/
|
|
181
|
+
interface InTotoStatementInput {
|
|
182
|
+
/** The artifacts the statement is about. */
|
|
183
|
+
readonly subject: ReadonlyArray<InTotoSubject>;
|
|
184
|
+
/** What the statement asserts. */
|
|
185
|
+
readonly predicateType: PredicateType;
|
|
186
|
+
/** The assertion's body — a `SlsaProvenance`, a BOM, or a caller's own shape. */
|
|
187
|
+
readonly predicate: unknown;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Input to {@link (InTotoStatement:class).forSubject}.
|
|
191
|
+
*
|
|
192
|
+
* @remarks
|
|
193
|
+
* A record rather than positional arguments on purpose: `name` and
|
|
194
|
+
* `predicateType` are both strings, and a positional constructor invites a
|
|
195
|
+
* statement that silently attests the wrong thing.
|
|
196
|
+
*
|
|
197
|
+
* @public
|
|
198
|
+
*/
|
|
199
|
+
interface InTotoSubjectInput {
|
|
200
|
+
/** How the single subject is identified. */
|
|
201
|
+
readonly name: string;
|
|
202
|
+
/** Its SHA-256 digest. */
|
|
203
|
+
readonly digest: Sha256Digest;
|
|
204
|
+
/** What the statement asserts. */
|
|
205
|
+
readonly predicateType: PredicateType;
|
|
206
|
+
/** The assertion's body — a `SlsaProvenance`, a BOM, or a caller's own shape. */
|
|
207
|
+
readonly predicate: unknown;
|
|
208
|
+
}
|
|
209
|
+
declare const InTotoStatement_base: Schema.Class<InTotoStatement, Schema.Struct<{
|
|
210
|
+
/** Always the in-toto Statement v1 URI. */
|
|
211
|
+
readonly _type: Schema.Literal<"https://in-toto.io/Statement/v1">;
|
|
212
|
+
/** The artifacts attested. */
|
|
213
|
+
readonly subject: Schema.$Array<typeof InTotoSubject>;
|
|
214
|
+
/** What is being asserted about them. */
|
|
215
|
+
readonly predicateType: Schema.String;
|
|
216
|
+
/** The assertion body. */
|
|
217
|
+
readonly predicate: Schema.Unknown;
|
|
218
|
+
}>, {}>;
|
|
219
|
+
/**
|
|
220
|
+
* An in-toto Statement v1.
|
|
221
|
+
*
|
|
222
|
+
* @remarks
|
|
223
|
+
* `predicate` is `unknown` by design — SLSA provenance, a CycloneDX BOM and a
|
|
224
|
+
* caller's own predicate all travel here, and the statement layer has no reason
|
|
225
|
+
* to introspect any of them.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* import { InTotoStatement, Sha256Digest, SlsaProvenance } from "@effected/sbom";
|
|
230
|
+
*
|
|
231
|
+
* const statement = InTotoStatement.forSubject({
|
|
232
|
+
* name: "pkg:npm/%40scope/pkg@1.0.0",
|
|
233
|
+
* digest,
|
|
234
|
+
* predicateType: SlsaProvenance.predicateType,
|
|
235
|
+
* predicate: provenance,
|
|
236
|
+
* });
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
239
|
+
* @public
|
|
240
|
+
*/
|
|
241
|
+
declare class InTotoStatement extends InTotoStatement_base {
|
|
242
|
+
/** A statement over any number of subjects. **Total.** */
|
|
243
|
+
static of(input: InTotoStatementInput): InTotoStatement;
|
|
244
|
+
/** A statement over a single artifact — the common case. **Total.** */
|
|
245
|
+
static forSubject(input: InTotoSubjectInput): InTotoStatement;
|
|
246
|
+
/**
|
|
247
|
+
* The statement as JSON — the bytes a DSSE envelope carries as its payload.
|
|
248
|
+
*
|
|
249
|
+
* @remarks
|
|
250
|
+
* Compact and in a fixed key order by default, so the same statement
|
|
251
|
+
* serializes to the same bytes on every run. Pass `space` for a form meant to
|
|
252
|
+
* be read by a person.
|
|
253
|
+
*/
|
|
254
|
+
toJson(options?: {
|
|
255
|
+
readonly space?: number;
|
|
256
|
+
}): string;
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/SbomDocument.d.ts
|
|
260
|
+
/**
|
|
261
|
+
* The CycloneDX component types this package emits.
|
|
262
|
+
*
|
|
263
|
+
* @remarks
|
|
264
|
+
* A deliberate subset of the specification's fourteen: an npm SBOM describes
|
|
265
|
+
* libraries and applications. The full enum is available in the schema; adding
|
|
266
|
+
* a member here is a one-line change when something needs one.
|
|
267
|
+
*
|
|
268
|
+
* @public
|
|
269
|
+
*/
|
|
270
|
+
declare const ComponentType: Schema.Literals<readonly ["library", "application", "framework"]>;
|
|
271
|
+
/**
|
|
272
|
+
* The decoded type of {@link (ComponentType:variable)}.
|
|
273
|
+
*
|
|
274
|
+
* @public
|
|
275
|
+
*/
|
|
276
|
+
type ComponentType = typeof ComponentType.Type;
|
|
277
|
+
/**
|
|
278
|
+
* An external reference's kind.
|
|
279
|
+
*
|
|
280
|
+
* @remarks
|
|
281
|
+
* The four the manifest mapping produces, out of the specification's 43. Each
|
|
282
|
+
* corresponds to a `package.json` field: `vcs` ← `repository`,
|
|
283
|
+
* `issue-tracker` ← `bugs`, `website` and `documentation` ← `homepage`.
|
|
284
|
+
*
|
|
285
|
+
* @public
|
|
286
|
+
*/
|
|
287
|
+
declare const ExternalReferenceType: Schema.Literals<readonly ["vcs", "issue-tracker", "website", "documentation"]>;
|
|
288
|
+
/**
|
|
289
|
+
* The decoded type of {@link (ExternalReferenceType:variable)}.
|
|
290
|
+
*
|
|
291
|
+
* @public
|
|
292
|
+
*/
|
|
293
|
+
type ExternalReferenceType = typeof ExternalReferenceType.Type;
|
|
294
|
+
declare const ExternalReference_base: Schema.Class<ExternalReference, Schema.Struct<{
|
|
295
|
+
/** The reference kind. */
|
|
296
|
+
readonly type: Schema.Literals<readonly ["vcs", "issue-tracker", "website", "documentation"]>;
|
|
297
|
+
/** The URL it points at, passed through exactly as supplied. */
|
|
298
|
+
readonly url: Schema.String;
|
|
299
|
+
}>, {}>;
|
|
300
|
+
/**
|
|
301
|
+
* A link from a component to something outside the BOM.
|
|
302
|
+
*
|
|
303
|
+
* @public
|
|
304
|
+
*/
|
|
305
|
+
declare class ExternalReference extends ExternalReference_base {}
|
|
306
|
+
declare const Contact_base: Schema.Class<Contact, Schema.Struct<{
|
|
307
|
+
/** The contact's name. */
|
|
308
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
309
|
+
/** Their email address. */
|
|
310
|
+
readonly email: Schema.optionalKey<Schema.String>;
|
|
311
|
+
/** Their telephone number. */
|
|
312
|
+
readonly phone: Schema.optionalKey<Schema.String>;
|
|
313
|
+
}>, {}>;
|
|
314
|
+
/**
|
|
315
|
+
* A point of contact — a person at a supplier, or an author of the BOM.
|
|
316
|
+
*
|
|
317
|
+
* @public
|
|
318
|
+
*/
|
|
319
|
+
declare class Contact extends Contact_base {}
|
|
320
|
+
declare const Supplier_base: Schema.Class<Supplier, Schema.Struct<{
|
|
321
|
+
/** The supplier organization's name. */
|
|
322
|
+
readonly name: Schema.String;
|
|
323
|
+
/** Its URLs. */
|
|
324
|
+
readonly url: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
325
|
+
/** Its points of contact. */
|
|
326
|
+
readonly contact: Schema.optionalKey<Schema.$Array<typeof Contact>>;
|
|
327
|
+
}>, {}>;
|
|
328
|
+
/**
|
|
329
|
+
* The organization that supplied a component.
|
|
330
|
+
*
|
|
331
|
+
* @remarks
|
|
332
|
+
* `name` is required because `metadata.supplier.name` is **NTIA minimum
|
|
333
|
+
* element 1**; a supplier without one satisfies nothing.
|
|
334
|
+
*
|
|
335
|
+
* @public
|
|
336
|
+
*/
|
|
337
|
+
declare class Supplier extends Supplier_base {}
|
|
338
|
+
declare const Component_base: Schema.Class<Component, Schema.Struct<{
|
|
339
|
+
/** What kind of component this is. */
|
|
340
|
+
readonly type: Schema.Literals<readonly ["library", "application", "framework"]>;
|
|
341
|
+
/** The component's name — NTIA minimum element 2. */
|
|
342
|
+
readonly name: Schema.String;
|
|
343
|
+
/** Its version — NTIA minimum element 3. */
|
|
344
|
+
readonly version: Schema.optionalKey<Schema.String>;
|
|
345
|
+
/** The package URL uniquely identifying it — NTIA minimum element 4. */
|
|
346
|
+
readonly purl: Schema.optionalKey<Schema.String>;
|
|
347
|
+
/** The identifier other parts of the document reference it by. */
|
|
348
|
+
readonly bomRef: Schema.optionalKey<Schema.String>;
|
|
349
|
+
/** A short description. */
|
|
350
|
+
readonly description: Schema.optionalKey<Schema.String>;
|
|
351
|
+
/** SPDX license identifiers or expressions. */
|
|
352
|
+
readonly licenses: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
353
|
+
/** Links out of the BOM. */
|
|
354
|
+
readonly externalReferences: Schema.optionalKey<Schema.$Array<typeof ExternalReference>>;
|
|
355
|
+
/** Discovery keywords — CycloneDX 1.6's `tags`, from the manifest's `keywords`. */
|
|
356
|
+
readonly tags: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
357
|
+
/** The component's authors. */
|
|
358
|
+
readonly authors: Schema.optionalKey<Schema.$Array<typeof Contact>>;
|
|
359
|
+
/** The entity that published it. */
|
|
360
|
+
readonly publisher: Schema.optionalKey<Schema.String>;
|
|
361
|
+
/** A copyright statement. */
|
|
362
|
+
readonly copyright: Schema.optionalKey<Schema.String>;
|
|
363
|
+
}>, {}>;
|
|
364
|
+
/**
|
|
365
|
+
* One component in the BOM — the root, or a dependency.
|
|
366
|
+
*
|
|
367
|
+
* @remarks
|
|
368
|
+
* `bomRef` is spelled **`bom-ref`** in the emitted JSON; the rename happens in
|
|
369
|
+
* `Sbom.toJson`. Emitting `bomRef` produces a document that looks
|
|
370
|
+
* correct and validates wrong, which is why a test pins the key name.
|
|
371
|
+
*
|
|
372
|
+
* @public
|
|
373
|
+
*/
|
|
374
|
+
declare class Component extends Component_base {}
|
|
375
|
+
declare const SbomMetadata_base: Schema.Class<SbomMetadata, Schema.Struct<{
|
|
376
|
+
/** When the BOM was assembled — NTIA minimum element 7. */
|
|
377
|
+
readonly timestamp: Schema.optionalKey<Schema.String>;
|
|
378
|
+
/** Who created the BOM — NTIA minimum element 6. */
|
|
379
|
+
readonly authors: Schema.optionalKey<Schema.$Array<typeof Contact>>;
|
|
380
|
+
/** The component the BOM describes. */
|
|
381
|
+
readonly component: Schema.optionalKey<typeof Component>;
|
|
382
|
+
/** Who supplied that component — NTIA minimum element 1. */
|
|
383
|
+
readonly supplier: Schema.optionalKey<typeof Supplier>;
|
|
384
|
+
}>, {}>;
|
|
385
|
+
/**
|
|
386
|
+
* Document-level metadata: who made the BOM, when, and about what.
|
|
387
|
+
*
|
|
388
|
+
* @public
|
|
389
|
+
*/
|
|
390
|
+
declare class SbomMetadata extends SbomMetadata_base {}
|
|
391
|
+
declare const SbomDocument_base: Schema.Class<SbomDocument, Schema.Struct<{
|
|
392
|
+
/** Always `"CycloneDX"`. */
|
|
393
|
+
readonly bomFormat: Schema.Literal<"CycloneDX">;
|
|
394
|
+
/** Always `"1.6"`. */
|
|
395
|
+
readonly specVersion: Schema.Literal<"1.6">;
|
|
396
|
+
/** The document revision, `1` for a freshly assembled BOM. */
|
|
397
|
+
readonly version: Schema.Number;
|
|
398
|
+
/** Document metadata. */
|
|
399
|
+
readonly metadata: Schema.optionalKey<typeof SbomMetadata>;
|
|
400
|
+
/** The components the BOM describes, sorted by name. */
|
|
401
|
+
readonly components: Schema.$Array<typeof Component>;
|
|
402
|
+
}>, {}>;
|
|
403
|
+
/**
|
|
404
|
+
* A CycloneDX 1.6 bill of materials.
|
|
405
|
+
*
|
|
406
|
+
* @remarks
|
|
407
|
+
* Constructed by `Sbom.generate` and serialized by `Sbom.toJson`; both are
|
|
408
|
+
* total functions, because an owned model over validated values has nothing to
|
|
409
|
+
* fail at.
|
|
410
|
+
*
|
|
411
|
+
* @public
|
|
412
|
+
*/
|
|
413
|
+
declare class SbomDocument extends SbomDocument_base {}
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region src/NtiaReport.d.ts
|
|
416
|
+
/**
|
|
417
|
+
* The seven NTIA minimum elements, by stable identifier.
|
|
418
|
+
*
|
|
419
|
+
* @remarks
|
|
420
|
+
* A literal union rather than free text: this is what a consumer branches on,
|
|
421
|
+
* and a display name is what it renders afterwards.
|
|
422
|
+
*
|
|
423
|
+
* @public
|
|
424
|
+
*/
|
|
425
|
+
declare const NtiaElementId: Schema.Literals<readonly ["supplierName", "componentName", "componentVersion", "uniqueIdentifier", "dependencyRelationship", "sbomAuthor", "timestamp"]>;
|
|
426
|
+
/**
|
|
427
|
+
* The decoded type of {@link (NtiaElementId:variable)}.
|
|
428
|
+
*
|
|
429
|
+
* @public
|
|
430
|
+
*/
|
|
431
|
+
type NtiaElementId = typeof NtiaElementId.Type;
|
|
432
|
+
declare const NtiaElement_base: Schema.Class<NtiaElement, Schema.Struct<{
|
|
433
|
+
/** Which element this is. */
|
|
434
|
+
readonly id: Schema.Literals<readonly ["supplierName", "componentName", "componentVersion", "uniqueIdentifier", "dependencyRelationship", "sbomAuthor", "timestamp"]>;
|
|
435
|
+
/** Whether the document satisfies it. */
|
|
436
|
+
readonly satisfied: Schema.Boolean;
|
|
437
|
+
/** The value that satisfied it, when one did. */
|
|
438
|
+
readonly value: Schema.optionalKey<Schema.String>;
|
|
439
|
+
}>, {}>;
|
|
440
|
+
/**
|
|
441
|
+
* One element's verdict.
|
|
442
|
+
*
|
|
443
|
+
* @public
|
|
444
|
+
*/
|
|
445
|
+
declare class NtiaElement extends NtiaElement_base {}
|
|
446
|
+
declare const NtiaReport_base: Schema.Class<NtiaReport, Schema.Struct<{
|
|
447
|
+
/** One verdict per element, in the published order. */
|
|
448
|
+
readonly elements: Schema.$Array<typeof NtiaElement>;
|
|
449
|
+
}>, {}>;
|
|
450
|
+
/**
|
|
451
|
+
* A document's standing against the NTIA minimum elements.
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* ```ts
|
|
455
|
+
* import { NtiaReport } from "@effected/sbom";
|
|
456
|
+
*
|
|
457
|
+
* const report = NtiaReport.of(document);
|
|
458
|
+
* if (!report.compliant) yield* Effect.logWarning(`SBOM missing: ${report.missing.join(", ")}`);
|
|
459
|
+
* ```
|
|
460
|
+
*
|
|
461
|
+
* @public
|
|
462
|
+
*/
|
|
463
|
+
declare class NtiaReport extends NtiaReport_base {
|
|
464
|
+
/** Whether every element is satisfied. */
|
|
465
|
+
get compliant(): boolean;
|
|
466
|
+
/** The elements the document does not satisfy, by id. */
|
|
467
|
+
get missing(): ReadonlyArray<NtiaElementId>;
|
|
468
|
+
/**
|
|
469
|
+
* Check a document. **Total** — a report is the answer for every input,
|
|
470
|
+
* including a document that satisfies nothing.
|
|
471
|
+
*/
|
|
472
|
+
static of(document: SbomDocument): NtiaReport;
|
|
473
|
+
}
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/Sbom.d.ts
|
|
476
|
+
/**
|
|
477
|
+
* Input to {@link Sbom.generate}.
|
|
478
|
+
*
|
|
479
|
+
* @public
|
|
480
|
+
*/
|
|
481
|
+
interface SbomInput {
|
|
482
|
+
/** The component the BOM is about. */
|
|
483
|
+
readonly root: Component;
|
|
484
|
+
/** Its dependencies, in any order — the document sorts them. */
|
|
485
|
+
readonly components: ReadonlyArray<Component>;
|
|
486
|
+
/** Document metadata. `root` is threaded onto it automatically. */
|
|
487
|
+
readonly metadata?: SbomMetadata;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Options for {@link Sbom.toJson}.
|
|
491
|
+
*
|
|
492
|
+
* @public
|
|
493
|
+
*/
|
|
494
|
+
interface SbomJsonOptions {
|
|
495
|
+
/** `JSON.stringify` indentation. Defaults to `2`; `0` emits one line. */
|
|
496
|
+
readonly space?: number;
|
|
497
|
+
}
|
|
498
|
+
declare const SbomWriteError_base: Schema.Class<SbomWriteError, Schema.TaggedStruct<"SbomWriteError", {
|
|
499
|
+
/** The path that could not be written. */
|
|
500
|
+
readonly path: Schema.String;
|
|
501
|
+
/** The underlying failure, preserved structurally. */
|
|
502
|
+
readonly cause: Schema.Defect;
|
|
503
|
+
}>, import("effect/Cause").YieldableError>;
|
|
504
|
+
/**
|
|
505
|
+
* Raised when a BOM cannot be written to disk.
|
|
506
|
+
*
|
|
507
|
+
* @remarks
|
|
508
|
+
* The package's **only** error, and it is the filesystem's rather than the
|
|
509
|
+
* emitter's — assembling and serializing a document cannot fail.
|
|
510
|
+
*
|
|
511
|
+
* @public
|
|
512
|
+
*/
|
|
513
|
+
declare class SbomWriteError extends SbomWriteError_base {
|
|
514
|
+
get message(): string;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* The SBOM emitter: assemble, serialize, write.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* ```ts
|
|
521
|
+
* import { Sbom } from "@effected/sbom";
|
|
522
|
+
*
|
|
523
|
+
* const document = Sbom.generate({ root, components });
|
|
524
|
+
* const json = Sbom.toJson(document);
|
|
525
|
+
* ```
|
|
526
|
+
*
|
|
527
|
+
* @public
|
|
528
|
+
*/
|
|
529
|
+
declare class Sbom {
|
|
530
|
+
private constructor();
|
|
531
|
+
/**
|
|
532
|
+
* Assemble a CycloneDX 1.6 document.
|
|
533
|
+
*
|
|
534
|
+
* @remarks
|
|
535
|
+
* **Total** — no error channel, because there is nothing here that can fail.
|
|
536
|
+
* Components are sorted by name so two runs over the same inputs produce the
|
|
537
|
+
* same bytes: an SBOM's digest becomes an attestation subject, and a document
|
|
538
|
+
* that reordered itself between runs would change that digest for no reason.
|
|
539
|
+
*/
|
|
540
|
+
static readonly generate: (input: SbomInput) => SbomDocument;
|
|
541
|
+
/**
|
|
542
|
+
* Serialize a document to canonical CycloneDX 1.6 JSON.
|
|
543
|
+
*
|
|
544
|
+
* @remarks
|
|
545
|
+
* **Total.** Absent optional fields are omitted rather than emitted as `null`,
|
|
546
|
+
* and `bomRef` becomes the specification's hyphenated `bom-ref`.
|
|
547
|
+
*/
|
|
548
|
+
static readonly toJson: (document: SbomDocument, options?: SbomJsonOptions) => string;
|
|
549
|
+
/**
|
|
550
|
+
* Write a document to `path` as canonical JSON.
|
|
551
|
+
*
|
|
552
|
+
* @remarks
|
|
553
|
+
* The one fallible member. It does not create parent directories — a caller
|
|
554
|
+
* that wants one creates it, so the failure mode stays "the path you gave me
|
|
555
|
+
* is not writable" rather than "something was created somewhere".
|
|
556
|
+
*/
|
|
557
|
+
static readonly write: (document: SbomDocument, path: string, options?: SbomJsonOptions | undefined) => Effect.Effect<void, SbomWriteError, FileSystem.FileSystem>;
|
|
558
|
+
}
|
|
559
|
+
//#endregion
|
|
560
|
+
//#region src/SbomMetadataSource.d.ts
|
|
561
|
+
/**
|
|
562
|
+
* What a manifest cannot supply, and the two places an explicit value wins.
|
|
563
|
+
*
|
|
564
|
+
* @remarks
|
|
565
|
+
* A `package.json` says who wrote the software. It never says which
|
|
566
|
+
* organization supplied it, who assembled the BOM, or when — so `supplier`,
|
|
567
|
+
* `authors` and `timestamp` are explicit-only. Deriving them would fabricate
|
|
568
|
+
* three of the seven NTIA minimum elements.
|
|
569
|
+
*
|
|
570
|
+
* @public
|
|
571
|
+
*/
|
|
572
|
+
interface SbomMetadataOptions {
|
|
573
|
+
/** The supplying organization — NTIA minimum element 1. */
|
|
574
|
+
readonly supplier?: Supplier;
|
|
575
|
+
/** Who assembled the BOM — NTIA minimum element 6. */
|
|
576
|
+
readonly authors?: ReadonlyArray<Contact>;
|
|
577
|
+
/** When it was assembled — NTIA minimum element 7, as an ISO 8601 string. */
|
|
578
|
+
readonly timestamp?: string;
|
|
579
|
+
/** The publishing entity. Falls back to the supplier, then the manifest's author. */
|
|
580
|
+
readonly publisher?: string;
|
|
581
|
+
/** A copyright statement; {@link SbomMetadataSource.formatCopyright} builds one. */
|
|
582
|
+
readonly copyright?: string;
|
|
583
|
+
/** The documentation URL, winning over the manifest's `homepage`. */
|
|
584
|
+
readonly documentationUrl?: string;
|
|
585
|
+
/** The root component's type. Defaults to `library`. */
|
|
586
|
+
readonly type?: ComponentType;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* The fields a dependency contributes to its component entry.
|
|
590
|
+
*
|
|
591
|
+
* @public
|
|
592
|
+
*/
|
|
593
|
+
interface ComponentInput {
|
|
594
|
+
/** The package name, scope included. */
|
|
595
|
+
readonly name: string;
|
|
596
|
+
/** Its resolved version. Absent produces a component with no version and no purl version segment. */
|
|
597
|
+
readonly version?: string;
|
|
598
|
+
/** An SPDX identifier or expression. */
|
|
599
|
+
readonly license?: string;
|
|
600
|
+
/** A short description. */
|
|
601
|
+
readonly description?: string;
|
|
602
|
+
/** The component type. Defaults to `library`. */
|
|
603
|
+
readonly type?: ComponentType;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* The years a copyright statement spans.
|
|
607
|
+
*
|
|
608
|
+
* @public
|
|
609
|
+
*/
|
|
610
|
+
interface CopyrightYears {
|
|
611
|
+
/** The first year of the range. Omit for a single-year statement. */
|
|
612
|
+
readonly startYear?: number;
|
|
613
|
+
/** The year the statement is current through — the caller's clock read, never ours. */
|
|
614
|
+
readonly year: number;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Derivation of CycloneDX metadata from a `package.json` manifest.
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* ```ts
|
|
621
|
+
* import { Sbom, SbomMetadataSource } from "@effected/sbom";
|
|
622
|
+
*
|
|
623
|
+
* const root = SbomMetadataSource.rootComponent(pkg, { supplier });
|
|
624
|
+
* const metadata = SbomMetadataSource.fromPackage(pkg, { supplier, timestamp });
|
|
625
|
+
* const document = Sbom.generate({ root, components, metadata });
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* @public
|
|
629
|
+
*/
|
|
630
|
+
declare class SbomMetadataSource {
|
|
631
|
+
private constructor();
|
|
632
|
+
/**
|
|
633
|
+
* The canonical npm package URL for a name and optional version.
|
|
634
|
+
*
|
|
635
|
+
* @remarks
|
|
636
|
+
* The NTIA's "unique identifier" element, and the identifier an in-toto
|
|
637
|
+
* subject names. Exposed because a caller assembling its own components —
|
|
638
|
+
* or a statement subject — needs the same encoding this module applies.
|
|
639
|
+
*/
|
|
640
|
+
static readonly npmPurl: (name: string, version?: string) => string;
|
|
641
|
+
/**
|
|
642
|
+
* A component entry for one resolved dependency.
|
|
643
|
+
*
|
|
644
|
+
* @remarks
|
|
645
|
+
* The caller assembles the component list — the kit has no second merge
|
|
646
|
+
* rule for sibling packages released in the same wave, because which
|
|
647
|
+
* versions are in flight is release planning and `@effected/workspaces`
|
|
648
|
+
* already knows it. This is the mapping that would otherwise be
|
|
649
|
+
* re-derived at every call site.
|
|
650
|
+
*/
|
|
651
|
+
static readonly componentFor: (input: ComponentInput) => Component;
|
|
652
|
+
/**
|
|
653
|
+
* The root component the BOM is about, derived from its own manifest.
|
|
654
|
+
*
|
|
655
|
+
* @remarks
|
|
656
|
+
* `publisher` resolves explicit → supplier name → the manifest's author,
|
|
657
|
+
* which is what lets NTIA element 6 be satisfied from a manifest alone.
|
|
658
|
+
*/
|
|
659
|
+
static readonly rootComponent: (pkg: Package, options?: SbomMetadataOptions) => Component;
|
|
660
|
+
/**
|
|
661
|
+
* The manifest's outward links, as CycloneDX external references.
|
|
662
|
+
*
|
|
663
|
+
* @remarks
|
|
664
|
+
* Four of the specification's 43 types, one per manifest field: `vcs` ←
|
|
665
|
+
* `repository`, `issue-tracker` ← `bugs`, `documentation` ← `homepage`,
|
|
666
|
+
* `website` ← the supplier's first URL.
|
|
667
|
+
*
|
|
668
|
+
* A `repository` value the package-json model cannot interpret produces
|
|
669
|
+
* **no** reference rather than a passed-through string: CycloneDX's
|
|
670
|
+
* `externalReference.url` is a URL, and emitting `owner/name` there is a
|
|
671
|
+
* document that validates and misleads.
|
|
672
|
+
*/
|
|
673
|
+
static readonly externalReferences: (pkg: Package, options?: SbomMetadataOptions) => ReadonlyArray<ExternalReference>;
|
|
674
|
+
/**
|
|
675
|
+
* Document-level metadata for a manifest.
|
|
676
|
+
*
|
|
677
|
+
* @remarks
|
|
678
|
+
* The root component is **not** on the returned value: `Sbom.generate`
|
|
679
|
+
* threads its `root` argument onto the metadata itself, so setting it
|
|
680
|
+
* here would only be overwritten. Build the root with
|
|
681
|
+
* {@link SbomMetadataSource.rootComponent} and pass both.
|
|
682
|
+
*
|
|
683
|
+
* When the caller supplies a supplier with no contacts, the manifest's
|
|
684
|
+
* maintainers fill them — the one derivation that crosses from manifest
|
|
685
|
+
* vocabulary into supplier vocabulary, and only where the caller left a
|
|
686
|
+
* hole.
|
|
687
|
+
*/
|
|
688
|
+
static readonly fromPackage: (pkg: Package, options?: SbomMetadataOptions) => SbomMetadata;
|
|
689
|
+
/**
|
|
690
|
+
* A copyright statement for a holder and a year, or a span of years.
|
|
691
|
+
*
|
|
692
|
+
* @remarks
|
|
693
|
+
* The year is an **argument**. The predecessor defaulted it to
|
|
694
|
+
* `new Date().getFullYear()`, which made its output untestable and its
|
|
695
|
+
* purity a claim rather than a property; the ambient read belongs at the
|
|
696
|
+
* caller's edge.
|
|
697
|
+
*/
|
|
698
|
+
static readonly formatCopyright: (holder: string, years: CopyrightYears) => string;
|
|
699
|
+
/**
|
|
700
|
+
* Field-wise metadata merge: every field the override carries wins.
|
|
701
|
+
*
|
|
702
|
+
* @remarks
|
|
703
|
+
* A helper, not a policy. Which side is the override — a config file over
|
|
704
|
+
* inferred values, or the reverse — is the consumer's precedence rule,
|
|
705
|
+
* and a library that decided it would be encoding one repository's
|
|
706
|
+
* release policy.
|
|
707
|
+
*/
|
|
708
|
+
static readonly merge: (base: SbomMetadata, override: SbomMetadata) => SbomMetadata;
|
|
709
|
+
}
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/SigstoreBundle.d.ts
|
|
712
|
+
/**
|
|
713
|
+
* The Sigstore bundle media type this package produces.
|
|
714
|
+
*
|
|
715
|
+
* @remarks
|
|
716
|
+
* v0.3 with a single certificate — what `DSSEBundleBuilder` emits by default,
|
|
717
|
+
* and what GitHub's `POST /repos/{owner}/{repo}/attestations` accepts.
|
|
718
|
+
*
|
|
719
|
+
* @public
|
|
720
|
+
*/
|
|
721
|
+
declare const SIGSTORE_BUNDLE_V0_3_MEDIA_TYPE: "application/vnd.dev.sigstore.bundle.v0.3+json";
|
|
722
|
+
/**
|
|
723
|
+
* The DSSE payload type for an in-toto statement, per the GitHub attestations
|
|
724
|
+
* specification.
|
|
725
|
+
*
|
|
726
|
+
* @public
|
|
727
|
+
*/
|
|
728
|
+
declare const IN_TOTO_PAYLOAD_TYPE: "application/vnd.in-toto+json";
|
|
729
|
+
declare const SigstoreBundle_base: Schema.Class<SigstoreBundle, Schema.Struct<{
|
|
730
|
+
/** The bundle's media type, usually {@link SIGSTORE_BUNDLE_V0_3_MEDIA_TYPE}. */
|
|
731
|
+
readonly mediaType: Schema.String;
|
|
732
|
+
/** The certificate and transparency-log entries a verifier checks. */
|
|
733
|
+
readonly verificationMaterial: Schema.Unknown;
|
|
734
|
+
/** The signed DSSE envelope carrying the statement. */
|
|
735
|
+
readonly dsseEnvelope: Schema.Unknown;
|
|
736
|
+
}>, {}>;
|
|
737
|
+
/**
|
|
738
|
+
* A signed Sigstore bundle: the wire form of an attestation.
|
|
739
|
+
*
|
|
740
|
+
* @remarks
|
|
741
|
+
* `verificationMaterial` and `dsseEnvelope` are `unknown` because their shapes
|
|
742
|
+
* belong to the Sigstore protobuf specifications, and re-declaring them here
|
|
743
|
+
* would be a second, drifting copy of a wire format we do not own. The bundle
|
|
744
|
+
* is opaque to everything that merely stores or forwards it.
|
|
745
|
+
*
|
|
746
|
+
* `mediaType` is carried through from what the builder produced rather than
|
|
747
|
+
* asserted — the version is the producer's statement about the bundle, and a
|
|
748
|
+
* literal here would quietly lie the day a builder emits a different one.
|
|
749
|
+
*
|
|
750
|
+
* @see {@link https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto | sigstore_bundle.proto}
|
|
751
|
+
*
|
|
752
|
+
* @public
|
|
753
|
+
*/
|
|
754
|
+
declare class SigstoreBundle extends SigstoreBundle_base {}
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region src/SigstoreSigner.d.ts
|
|
757
|
+
/**
|
|
758
|
+
* The OIDC audience Sigstore's certificate authority requires.
|
|
759
|
+
*
|
|
760
|
+
* @remarks
|
|
761
|
+
* It lives here, not at the call site, because it is the **signing protocol's**
|
|
762
|
+
* requirement rather than the caller's knowledge — which is why
|
|
763
|
+
* {@link SigstoreSignerShape.sign} takes only a statement and asks the identity
|
|
764
|
+
* contract for a token. Considered and rejected: `sign(statement, { token })`,
|
|
765
|
+
* which reads simpler and forces every caller to learn a constant that is none
|
|
766
|
+
* of its business.
|
|
767
|
+
*
|
|
768
|
+
* @public
|
|
769
|
+
*/
|
|
770
|
+
declare const SIGSTORE_OIDC_AUDIENCE: "sigstore";
|
|
771
|
+
/**
|
|
772
|
+
* Which step of signing failed.
|
|
773
|
+
*
|
|
774
|
+
* @public
|
|
775
|
+
*/
|
|
776
|
+
declare const SigningErrorKind: Schema.Literals<readonly ["identity", "certificate", "transparencyLog", "bundle"]>;
|
|
777
|
+
/**
|
|
778
|
+
* The decoded type of {@link (SigningErrorKind:variable)}.
|
|
779
|
+
*
|
|
780
|
+
* @public
|
|
781
|
+
*/
|
|
782
|
+
type SigningErrorKind = typeof SigningErrorKind.Type;
|
|
783
|
+
declare const SigningError_base: Schema.Class<SigningError, Schema.TaggedStruct<"SigningError", {
|
|
784
|
+
/** Which step failed. */
|
|
785
|
+
readonly kind: Schema.Literals<readonly ["identity", "certificate", "transparencyLog", "bundle"]>;
|
|
786
|
+
/** The underlying failure, preserved structurally. */
|
|
787
|
+
readonly cause: Schema.Defect;
|
|
788
|
+
}>, import("effect/Cause").YieldableError>;
|
|
789
|
+
/**
|
|
790
|
+
* Raised when a statement cannot be signed.
|
|
791
|
+
*
|
|
792
|
+
* @remarks
|
|
793
|
+
* Sized to what a caller can act on: an `identity` failure is a workflow
|
|
794
|
+
* permissions problem, `certificate` is Fulcio, `transparencyLog` is Rekor, and
|
|
795
|
+
* `bundle` is everything else about assembling the result. The original failure
|
|
796
|
+
* is preserved structurally on `cause` rather than flattened into a message.
|
|
797
|
+
*
|
|
798
|
+
* @public
|
|
799
|
+
*/
|
|
800
|
+
declare class SigningError extends SigningError_base {
|
|
801
|
+
get message(): string;
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Where signing happens, and with what.
|
|
805
|
+
*
|
|
806
|
+
* @remarks
|
|
807
|
+
* The URL overrides exist for the Sigstore **staging** instance, which is what
|
|
808
|
+
* an opt-in end-to-end test points at. `signer` and `witnesses` replace the
|
|
809
|
+
* default Fulcio/Rekor pair outright — the seam that lets a test drive the
|
|
810
|
+
* **real** `DSSEBundleBuilder` with no network, no keys and no OIDC.
|
|
811
|
+
*
|
|
812
|
+
* @public
|
|
813
|
+
*/
|
|
814
|
+
interface SigstoreSignerOptions {
|
|
815
|
+
/** Fulcio's base URL. Defaults to the public-good instance. */
|
|
816
|
+
readonly fulcioBaseUrl?: string;
|
|
817
|
+
/** Rekor's base URL. Defaults to the public-good instance. */
|
|
818
|
+
readonly rekorBaseUrl?: string;
|
|
819
|
+
/** Replace the certificate signer. */
|
|
820
|
+
readonly signer?: Signer;
|
|
821
|
+
/** Replace the witnesses. An empty array signs without a transparency log. */
|
|
822
|
+
readonly witnesses?: ReadonlyArray<Witness>;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* The signing surface.
|
|
826
|
+
*
|
|
827
|
+
* @public
|
|
828
|
+
*/
|
|
829
|
+
interface SigstoreSignerShape {
|
|
830
|
+
/**
|
|
831
|
+
* Sign a statement into a DSSE bundle.
|
|
832
|
+
*
|
|
833
|
+
* @remarks
|
|
834
|
+
* The identity token is fetched, used and discarded inside this call; it is
|
|
835
|
+
* `Redacted` from the contract to the moment it is handed to Fulcio, and
|
|
836
|
+
* declassified exactly once, here.
|
|
837
|
+
*/
|
|
838
|
+
readonly sign: (statement: InTotoStatement) => Effect.Effect<SigstoreBundle, SigningError>;
|
|
839
|
+
}
|
|
840
|
+
declare const SigstoreSigner_base: Context.ServiceClass<SigstoreSigner, "@effected/sbom/SigstoreSigner", SigstoreSignerShape>;
|
|
841
|
+
/**
|
|
842
|
+
* Sigstore signing.
|
|
843
|
+
*
|
|
844
|
+
* @example
|
|
845
|
+
* ```ts
|
|
846
|
+
* import { IdentityToken, SigstoreSigner } from "@effected/sbom";
|
|
847
|
+
* import { Effect, Layer } from "effect";
|
|
848
|
+
*
|
|
849
|
+
* const program = Effect.gen(function* () {
|
|
850
|
+
* const signer = yield* SigstoreSigner;
|
|
851
|
+
* return yield* signer.sign(statement);
|
|
852
|
+
* });
|
|
853
|
+
* ```
|
|
854
|
+
*
|
|
855
|
+
* @public
|
|
856
|
+
*/
|
|
857
|
+
declare class SigstoreSigner extends SigstoreSigner_base {
|
|
858
|
+
/** Signing against the public-good Fulcio and Rekor instances. */
|
|
859
|
+
static readonly layer: Layer.Layer<SigstoreSigner, never, IdentityToken>;
|
|
860
|
+
/** {@link (SigstoreSigner:class).layer} with the signing endpoints, or the signer and witnesses, replaced. */
|
|
861
|
+
static readonly layerWith: (options: SigstoreSignerOptions) => Layer.Layer<SigstoreSigner, never, IdentityToken>;
|
|
862
|
+
/**
|
|
863
|
+
* An in-memory double whose `sign` **dies** unless stubbed.
|
|
864
|
+
*
|
|
865
|
+
* @remarks
|
|
866
|
+
* The strongest case in the kit for the die-loudly default: no honest
|
|
867
|
+
* fabricated answer exists, because a bundle that looks signed and is not is
|
|
868
|
+
* exactly the failure an attestation exists to prevent. A test that wants a
|
|
869
|
+
* real bundle without a network drives the real builder through
|
|
870
|
+
* {@link (SigstoreSigner:class).layerWith}.
|
|
871
|
+
*/
|
|
872
|
+
static readonly makeTest: (overrides?: Partial<SigstoreSignerShape>) => SigstoreSignerShape;
|
|
873
|
+
/** {@link (SigstoreSigner:class).makeTest} behind a `Layer`. */
|
|
874
|
+
static readonly layerTest: (overrides?: Partial<SigstoreSignerShape>) => Layer.Layer<SigstoreSigner>;
|
|
875
|
+
}
|
|
876
|
+
//#endregion
|
|
877
|
+
//#region src/SlsaProvenance.d.ts
|
|
878
|
+
/**
|
|
879
|
+
* The SLSA Provenance v1 predicate type URI.
|
|
880
|
+
*
|
|
881
|
+
* @public
|
|
882
|
+
*/
|
|
883
|
+
declare const SLSA_PROVENANCE_V1: "https://slsa.dev/provenance/v1";
|
|
884
|
+
/**
|
|
885
|
+
* The SLSA build type identifying a GitHub Actions workflow build.
|
|
886
|
+
*
|
|
887
|
+
* @remarks
|
|
888
|
+
* A published **SLSA build-type identifier** — it names a provenance shape, not
|
|
889
|
+
* an Actions runtime detail — which is why it lives with the provenance model
|
|
890
|
+
* rather than in `@effected/github-actions`.
|
|
891
|
+
*
|
|
892
|
+
* @see {@link https://github.com/slsa-framework/github-actions-buildtypes/tree/main/workflow/v1 | workflow/v1}
|
|
893
|
+
*
|
|
894
|
+
* @public
|
|
895
|
+
*/
|
|
896
|
+
declare const GITHUB_BUILD_TYPE: "https://actions.github.io/buildtypes/workflow/v1";
|
|
897
|
+
declare const SlsaBuildDefinition_base: Schema.Class<SlsaBuildDefinition, Schema.Struct<{
|
|
898
|
+
/** The build type URI — {@link GITHUB_BUILD_TYPE} for an Actions workflow. */
|
|
899
|
+
readonly buildType: Schema.String;
|
|
900
|
+
/** Parameters an external party controls: for Actions, the workflow itself. */
|
|
901
|
+
readonly externalParameters: Schema.Struct<{
|
|
902
|
+
/** The workflow the build ran. */
|
|
903
|
+
readonly workflow: Schema.Struct<{
|
|
904
|
+
/** The git ref the workflow ran on. */
|
|
905
|
+
readonly ref: Schema.String;
|
|
906
|
+
/** The repository's browsable URL. */
|
|
907
|
+
readonly repository: Schema.String;
|
|
908
|
+
/** The workflow file's path within the repository. */
|
|
909
|
+
readonly path: Schema.String;
|
|
910
|
+
}>;
|
|
911
|
+
}>;
|
|
912
|
+
/** Parameters the build platform controls. */
|
|
913
|
+
readonly internalParameters: Schema.Struct<{
|
|
914
|
+
/** The Actions-specific half, spelled in the claim names the platform uses. */
|
|
915
|
+
readonly github: Schema.Struct<{
|
|
916
|
+
/** The event that triggered the workflow. */
|
|
917
|
+
readonly event_name: Schema.String;
|
|
918
|
+
/** The repository's numeric id. */
|
|
919
|
+
readonly repository_id: Schema.String;
|
|
920
|
+
/** The repository owner's numeric id. */
|
|
921
|
+
readonly repository_owner_id: Schema.String;
|
|
922
|
+
/** `github-hosted` or `self-hosted`. */
|
|
923
|
+
readonly runner_environment: Schema.String;
|
|
924
|
+
}>;
|
|
925
|
+
}>;
|
|
926
|
+
/** The artifacts the build consumed — for Actions, the commit it built. */
|
|
927
|
+
readonly resolvedDependencies: Schema.$Array<Schema.Struct<{
|
|
928
|
+
/** A URI naming the dependency. */
|
|
929
|
+
readonly uri: Schema.String;
|
|
930
|
+
/** Algorithm to digest; `gitCommit` for a repository. */
|
|
931
|
+
readonly digest: Schema.$Record<Schema.String, Schema.String>;
|
|
932
|
+
}>>;
|
|
933
|
+
}>, {}>;
|
|
934
|
+
/**
|
|
935
|
+
* How the build was invoked, and what it was invoked from.
|
|
936
|
+
*
|
|
937
|
+
* @public
|
|
938
|
+
*/
|
|
939
|
+
declare class SlsaBuildDefinition extends SlsaBuildDefinition_base {}
|
|
940
|
+
declare const SlsaRunDetails_base: Schema.Class<SlsaRunDetails, Schema.Struct<{
|
|
941
|
+
/** The build platform's identity. */
|
|
942
|
+
readonly builder: Schema.Struct<{
|
|
943
|
+
/** A URI identifying the builder — the reusable workflow, for Actions. */
|
|
944
|
+
readonly id: Schema.String;
|
|
945
|
+
}>;
|
|
946
|
+
/** Metadata about this particular run. */
|
|
947
|
+
readonly metadata: Schema.Struct<{
|
|
948
|
+
/** A URI locating the run that produced the artifact. */
|
|
949
|
+
readonly invocationId: Schema.String;
|
|
950
|
+
}>;
|
|
951
|
+
}>, {}>;
|
|
952
|
+
/**
|
|
953
|
+
* Who ran the build, and the record of that run.
|
|
954
|
+
*
|
|
955
|
+
* @public
|
|
956
|
+
*/
|
|
957
|
+
declare class SlsaRunDetails extends SlsaRunDetails_base {}
|
|
958
|
+
/**
|
|
959
|
+
* The claims and runner facts a GitHub Actions provenance predicate is built
|
|
960
|
+
* from.
|
|
961
|
+
*
|
|
962
|
+
* @remarks
|
|
963
|
+
* A plain input record, **not** a service. There is nothing to swap and no IO
|
|
964
|
+
* to invert — it is the argument to a data constructor, and inventing a seam
|
|
965
|
+
* for one would repeat a mistake this program already reversed once.
|
|
966
|
+
*
|
|
967
|
+
* Fields are camelCase here and re-spelled to the platform's claim names where
|
|
968
|
+
* the predicate demands it, so a caller reads its own vocabulary and the
|
|
969
|
+
* emitted document keeps the specification's.
|
|
970
|
+
*
|
|
971
|
+
* @public
|
|
972
|
+
*/
|
|
973
|
+
interface GitHubWorkflowProvenance {
|
|
974
|
+
/** The GitHub server's base URL — `https://github.com`, or a GHES host. */
|
|
975
|
+
readonly serverUrl: string;
|
|
976
|
+
/** `owner/repo`. */
|
|
977
|
+
readonly repository: string;
|
|
978
|
+
/** The git ref built. */
|
|
979
|
+
readonly ref: string;
|
|
980
|
+
/** The commit built. */
|
|
981
|
+
readonly sha: string;
|
|
982
|
+
/** The event that triggered the workflow. */
|
|
983
|
+
readonly eventName: string;
|
|
984
|
+
/** The workflow reference: `owner/repo/.github/workflows/x.yml@ref`. */
|
|
985
|
+
readonly workflowRef: string;
|
|
986
|
+
/** The job's workflow reference, which identifies the builder. */
|
|
987
|
+
readonly jobWorkflowRef: string;
|
|
988
|
+
/** The repository's numeric id. */
|
|
989
|
+
readonly repositoryId: string;
|
|
990
|
+
/** The repository owner's numeric id. */
|
|
991
|
+
readonly repositoryOwnerId: string;
|
|
992
|
+
/** `github-hosted` or `self-hosted`. */
|
|
993
|
+
readonly runnerEnvironment: string;
|
|
994
|
+
/** The workflow run's id. */
|
|
995
|
+
readonly runId: string;
|
|
996
|
+
/** Which attempt of that run this is. */
|
|
997
|
+
readonly runAttempt: string;
|
|
998
|
+
}
|
|
999
|
+
declare const SlsaProvenance_base: Schema.Class<SlsaProvenance, Schema.Struct<{
|
|
1000
|
+
/** What was built, and from what. */
|
|
1001
|
+
readonly buildDefinition: typeof SlsaBuildDefinition;
|
|
1002
|
+
/** Who built it, and when. */
|
|
1003
|
+
readonly runDetails: typeof SlsaRunDetails;
|
|
1004
|
+
}>, {}>;
|
|
1005
|
+
/**
|
|
1006
|
+
* A SLSA Provenance v1 predicate.
|
|
1007
|
+
*
|
|
1008
|
+
* @example
|
|
1009
|
+
* ```ts
|
|
1010
|
+
* import { SlsaProvenance } from "@effected/sbom";
|
|
1011
|
+
*
|
|
1012
|
+
* const provenance = SlsaProvenance.forGitHubWorkflow(claims);
|
|
1013
|
+
* ```
|
|
1014
|
+
*
|
|
1015
|
+
* @public
|
|
1016
|
+
*/
|
|
1017
|
+
declare class SlsaProvenance extends SlsaProvenance_base {
|
|
1018
|
+
/** The predicate type URI a statement carrying this must declare. */
|
|
1019
|
+
static readonly predicateType: PredicateType;
|
|
1020
|
+
/** The build type this package's GitHub-workflow constructor stamps. */
|
|
1021
|
+
static readonly buildType: string;
|
|
1022
|
+
/**
|
|
1023
|
+
* Provenance for a GitHub Actions `workflow/v1` build.
|
|
1024
|
+
*
|
|
1025
|
+
* @remarks
|
|
1026
|
+
* **Total** — a pure projection of its argument. Every value it needs is
|
|
1027
|
+
* already in the input; nothing is read from the environment and nothing can
|
|
1028
|
+
* fail.
|
|
1029
|
+
*/
|
|
1030
|
+
static forGitHubWorkflow(input: GitHubWorkflowProvenance): SlsaProvenance;
|
|
1031
|
+
}
|
|
1032
|
+
//#endregion
|
|
1033
|
+
export { CYCLONEDX_BOM_PREDICATE, Component, type ComponentInput, ComponentType, Contact, type CopyrightYears, ExternalReference, ExternalReferenceType, GITHUB_BUILD_TYPE, type GitHubWorkflowProvenance, IN_TOTO_PAYLOAD_TYPE, IN_TOTO_STATEMENT_V1, IdentityToken, IdentityTokenError, type IdentityTokenShape, InTotoStatement, type InTotoStatementInput, InTotoSubject, type InTotoSubjectInput, InvalidSha256DigestError, NtiaElement, NtiaElementId, NtiaReport, type PredicateType, SIGSTORE_BUNDLE_V0_3_MEDIA_TYPE, SIGSTORE_OIDC_AUDIENCE, SLSA_PROVENANCE_V1, Sbom, SbomDocument, type SbomInput, type SbomJsonOptions, SbomMetadata, type SbomMetadataOptions, SbomMetadataSource, SbomWriteError, Sha256Digest, SigningError, SigningErrorKind, SigstoreBundle, SigstoreSigner, type SigstoreSignerOptions, type SigstoreSignerShape, SlsaBuildDefinition, SlsaProvenance, SlsaRunDetails, Supplier };
|
|
1034
|
+
//# sourceMappingURL=index.d.ts.map
|