@effected/sbom 0.9.1 → 0.10.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 CHANGED
@@ -24,13 +24,21 @@ var IdentityTokenError = class extends Schema.TaggedError()("IdentityTokenError"
24
24
  /** The token every double answers with unless a test says otherwise. */
25
25
  const TEST_TOKEN = "test-identity-token";
26
26
  /**
27
- * A source of workload identity tokens.
27
+ * A source of workload identity tokens (OIDC), the input `SigstoreSigner` needs
28
+ * to obtain a signing certificate.
29
+ *
30
+ * @remarks
31
+ * In GitHub Actions, provide `ActionsIdentityToken.layer` from
32
+ * `@effected/github-actions`. A consumer that already holds a token uses
33
+ * {@link (IdentityToken:class).layerStatic}; tests use
34
+ * {@link (IdentityToken:class).layerTest}.
28
35
  *
29
36
  * @example
30
37
  * ```ts
31
38
  * import { IdentityToken, SigstoreSigner } from "@effected/sbom";
32
39
  * import { Layer } from "effect";
33
40
  *
41
+ * const token = process.env.OIDC_TOKEN ?? "";
34
42
  * const layer = SigstoreSigner.layer.pipe(Layer.provide(IdentityToken.layerStatic(token)));
35
43
  * ```
36
44
  *
@@ -45,7 +45,7 @@ const parseResult = (value) => {
45
45
  * A deliberate small duplication rather than a shared package: `@effected/github`
46
46
  * types the same value structurally on its attestation surface, and dragging a
47
47
  * package across that seam to share one branded string would cost more than the
48
- * duplication does. Recorded under the program's shared-vocabulary rule.
48
+ * duplication does.
49
49
  *
50
50
  * @public
51
51
  */
@@ -96,12 +96,16 @@ var InTotoSubject = class InTotoSubject extends Schema.Class("InTotoSubject")({
96
96
  * @example
97
97
  * ```ts
98
98
  * import { InTotoStatement, Sha256Digest, SlsaProvenance } from "@effected/sbom";
99
+ * import { Effect } from "effect";
99
100
  *
100
- * const statement = InTotoStatement.forSubject({
101
- * name: "pkg:npm/%40scope/pkg@1.0.0",
102
- * digest,
103
- * predicateType: SlsaProvenance.predicateType,
104
- * predicate: provenance,
101
+ * const program = Effect.gen(function* () {
102
+ * const digest = yield* Sha256Digest.parse("ab".repeat(32));
103
+ * return InTotoStatement.forSubject({
104
+ * name: "pkg:npm/%40scope/pkg@1.0.0",
105
+ * digest,
106
+ * predicateType: SlsaProvenance.predicateType,
107
+ * predicate: {}, // a SlsaProvenance, a BOM, or any predicate body
108
+ * });
105
109
  * });
106
110
  * ```
107
111
  *
package/NtiaReport.js CHANGED
@@ -102,10 +102,13 @@ const timestamp = (document) => {
102
102
  *
103
103
  * @example
104
104
  * ```ts
105
- * import { NtiaReport } from "@effected/sbom";
105
+ * import { Component, NtiaReport, Sbom } from "@effected/sbom";
106
106
  *
107
- * const report = NtiaReport.of(document);
108
- * if (!report.compliant) yield* Effect.logWarning(`SBOM missing: ${report.missing.join(", ")}`);
107
+ * const root = Component.make({ type: "library", name: "lib", version: "1.0.0" });
108
+ * const report = NtiaReport.of(Sbom.generate({ root, components: [] }));
109
+ *
110
+ * report.compliant; // => false
111
+ * report.missing; // => ["supplierName", "uniqueIdentifier", "sbomAuthor", "timestamp"]
109
112
  * ```
110
113
  *
111
114
  * @public
package/README.md CHANGED
@@ -7,10 +7,10 @@
7
7
 
8
8
  Supply-chain artifacts for [Effect](https://effect.website) v4: a CycloneDX 1.6 SBOM, an NTIA minimum-elements report, in-toto statements, SLSA provenance, and Sigstore DSSE signing. `Sbom.generate` and `Sbom.toJson` are total, plain functions — assembling and serializing a document cannot fail, so the package's only error channel belongs to `Sbom.write`, the one member that touches a filesystem. Signing is a separate, deliberately walled-off capability: a consumer that only ever emits an SBOM never reaches `@sigstore/*` or its Fulcio/Rekor network calls.
9
9
 
10
- > **Pre-release.** This package is part of the `@effected/*` kit, in pre-`1.0.0`
11
- > development against a single pinned Effect v4 prerelease. Packages graduate to
12
- > `1.0.0` once Effect `4.0.0` ships. To hold your own `effect` versions at
13
- > exactly the ones the kit is built and tested against, install
10
+ > **Pre-`1.0.0`.** This package is part of the `@effected/*` kit, built on stable
11
+ > Effect v4 (`effect` `^4.0.0`) and still in `0.x` development. Stable Effect
12
+ > makes a kit `1.0.0` possible, not automatic. To keep your `effect` and
13
+ > `@effect/*` versions on the line the kit is built and tested against, install
14
14
  > [`@effected/pnpm-plugin-effect`](https://www.npmjs.com/package/@effected/pnpm-plugin-effect).
15
15
  >
16
16
  > **Stability: unstable.** This package's API surface is not yet considered
@@ -53,7 +53,7 @@ declare const pkg: Package;
53
53
  const root = SbomMetadataSource.rootComponent(pkg);
54
54
  const metadata = SbomMetadataSource.fromPackage(pkg, { timestamp: new Date().toISOString() });
55
55
  const components = [
56
- SbomMetadataSource.componentFor({ name: "effect", version: "4.0.0-rc.109", license: "MIT" }),
56
+ SbomMetadataSource.componentFor({ name: "effect", version: "4.0.0", license: "MIT" }),
57
57
  ];
58
58
 
59
59
  const document = Sbom.generate({ root, components, metadata });
package/Sbom.js CHANGED
@@ -57,10 +57,11 @@ const write = Effect.fn("Sbom.write")(function* (document, path, options) {
57
57
  *
58
58
  * @example
59
59
  * ```ts
60
- * import { Sbom } from "@effected/sbom";
60
+ * import { Component, Sbom } from "@effected/sbom";
61
61
  *
62
- * const document = Sbom.generate({ root, components });
63
- * const json = Sbom.toJson(document);
62
+ * const root = Component.make({ type: "application", name: "app", version: "1.0.0" });
63
+ * const document = Sbom.generate({ root, components: [] });
64
+ * const json = Sbom.toJson(document); // CycloneDX 1.6 JSON text
64
65
  * ```
65
66
  *
66
67
  * @public
@@ -89,7 +90,8 @@ var Sbom = class {
89
90
  * Write a document to `path` as canonical JSON.
90
91
  *
91
92
  * @remarks
92
- * The one fallible member. It does not create parent directories — a caller
93
+ * The one fallible member; it fails with {@link SbomWriteError} and requires
94
+ * `FileSystem` in `R`. It does not create parent directories — a caller
93
95
  * that wants one creates it, so the failure mode stays "the path you gave me
94
96
  * is not writable" rather than "something was created somewhere".
95
97
  */
package/SbomDocument.js CHANGED
@@ -84,7 +84,7 @@ var Supplier = class extends Schema.Class("Supplier")({
84
84
  * @remarks
85
85
  * `bomRef` is spelled **`bom-ref`** in the emitted JSON; the rename happens in
86
86
  * `Sbom.toJson`. Emitting `bomRef` produces a document that looks
87
- * correct and validates wrong, which is why a test pins the key name.
87
+ * correct and validates wrong.
88
88
  *
89
89
  * @public
90
90
  */
@@ -108,11 +108,16 @@ const merge = (base, override) => {
108
108
  *
109
109
  * @example
110
110
  * ```ts
111
- * import { Sbom, SbomMetadataSource } from "@effected/sbom";
111
+ * import { Package, Sbom, SbomMetadataSource, Supplier } from "@effected/sbom";
112
+ * import { Effect } from "effect";
112
113
  *
113
- * const root = SbomMetadataSource.rootComponent(pkg, { supplier });
114
- * const metadata = SbomMetadataSource.fromPackage(pkg, { supplier, timestamp });
115
- * const document = Sbom.generate({ root, components, metadata });
114
+ * const program = Effect.gen(function* () {
115
+ * const pkg = yield* Package.decode({ name: "@acme/app", version: "1.0.0", license: "MIT" });
116
+ * const supplier = Supplier.make({ name: "Acme Inc." });
117
+ * const root = SbomMetadataSource.rootComponent(pkg, { supplier });
118
+ * const metadata = SbomMetadataSource.fromPackage(pkg, { supplier, timestamp: "2026-01-01T00:00:00Z" });
119
+ * return Sbom.generate({ root, components: [], metadata });
120
+ * });
116
121
  * ```
117
122
  *
118
123
  * @public
@@ -184,10 +189,8 @@ var SbomMetadataSource = class {
184
189
  * A copyright statement for a holder and a year, or a span of years.
185
190
  *
186
191
  * @remarks
187
- * The year is an **argument**. The predecessor defaulted it to
188
- * `new Date().getFullYear()`, which made its output untestable and its
189
- * purity a claim rather than a property; the ambient read belongs at the
190
- * caller's edge.
192
+ * The year is an **argument**: nothing here reads the clock, so the output is
193
+ * deterministic. Read the ambient year at the caller's edge.
191
194
  */
192
195
  static formatCopyright = formatCopyright;
193
196
  /**
package/SigstoreBundle.js CHANGED
@@ -24,8 +24,8 @@ const IN_TOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
24
24
  * @remarks
25
25
  * `verificationMaterial` and `dsseEnvelope` are `unknown` because their shapes
26
26
  * belong to the Sigstore protobuf specifications, and re-declaring them here
27
- * would be a second, drifting copy of a wire format we do not own. The bundle
28
- * is opaque to everything that merely stores or forwards it.
27
+ * would be a second, drifting copy of a wire format this package does not own.
28
+ * The bundle is opaque to everything that merely stores or forwards it.
29
29
  *
30
30
  * `mediaType` is carried through from what the builder produced rather than
31
31
  * asserted — the version is the producer's statement about the bundle, and a
package/SigstoreSigner.js CHANGED
@@ -12,9 +12,7 @@ import { DSSEBundleBuilder, FulcioSigner, RekorWitness } from "@sigstore/sign";
12
12
  * It lives here, not at the call site, because it is the **signing protocol's**
13
13
  * requirement rather than the caller's knowledge — which is why
14
14
  * {@link SigstoreSignerShape.sign} takes only a statement and asks the identity
15
- * contract for a token. Considered and rejected: `sign(statement, { token })`,
16
- * which reads simpler and forces every caller to learn a constant that is none
17
- * of its business.
15
+ * contract for a token.
18
16
  *
19
17
  * @public
20
18
  */
@@ -51,14 +49,6 @@ var SigningError = class extends Schema.TaggedError()("SigningError", {
51
49
  return `Failed to sign the statement (${this.kind})`;
52
50
  }
53
51
  };
54
- /**
55
- * Attribute a `@sigstore/sign` failure to a step.
56
- *
57
- * `InternalError` carries a `code`, which is a far better signal than the
58
- * message text the predecessor scraped. An unrecognized failure is `bundle` —
59
- * literally "the bundle did not get built" — rather than being guessed into a
60
- * step it may not belong to.
61
- */
62
52
  const kindOf = (cause) => {
63
53
  const code = cause?.code;
64
54
  if (typeof code !== "string") return "bundle";
@@ -113,17 +103,28 @@ const unstubbed = () => {
113
103
  throw new Error("SigstoreSigner.makeTest: sign() was called but not stubbed — a fabricated bundle would be a signature-shaped lie. Pass a `sign` override, or drive the real builder through SigstoreSigner.layerWith({ signer, witnesses }).");
114
104
  };
115
105
  /**
116
- * Sigstore signing.
106
+ * Signs an in-toto statement into a Sigstore DSSE bundle, using a Fulcio
107
+ * certificate and a Rekor transparency-log entry.
108
+ *
109
+ * @remarks
110
+ * Fails with {@link SigningError}. The live {@link (SigstoreSigner:class).layer}
111
+ * requires {@link IdentityToken} in `R`.
117
112
  *
118
113
  * @example
119
114
  * ```ts
115
+ * import type { InTotoStatement } from "@effected/sbom";
120
116
  * import { IdentityToken, SigstoreSigner } from "@effected/sbom";
121
- * import { Effect, Layer } from "effect";
117
+ * import { Effect, Layer, Redacted } from "effect";
118
+ *
119
+ * const sign = (statement: InTotoStatement) =>
120
+ * Effect.gen(function* () {
121
+ * const signer = yield* SigstoreSigner;
122
+ * return yield* signer.sign(statement);
123
+ * });
122
124
  *
123
- * const program = Effect.gen(function* () {
124
- * const signer = yield* SigstoreSigner;
125
- * return yield* signer.sign(statement);
126
- * });
125
+ * const live = SigstoreSigner.layer.pipe(
126
+ * Layer.provide(IdentityToken.layerStatic(Redacted.make(process.env.OIDC_TOKEN ?? ""))),
127
+ * );
127
128
  * ```
128
129
  *
129
130
  * @public
package/SlsaProvenance.js CHANGED
@@ -90,7 +90,20 @@ const workflowPathOf = (input) => input.workflowRef.replace(`${input.repository}
90
90
  * ```ts
91
91
  * import { SlsaProvenance } from "@effected/sbom";
92
92
  *
93
- * const provenance = SlsaProvenance.forGitHubWorkflow(claims);
93
+ * const provenance = SlsaProvenance.forGitHubWorkflow({
94
+ * serverUrl: "https://github.com",
95
+ * repository: "acme/app",
96
+ * ref: "refs/heads/main",
97
+ * sha: "0123456789abcdef0123456789abcdef01234567",
98
+ * eventName: "push",
99
+ * workflowRef: "acme/app/.github/workflows/release.yml@refs/heads/main",
100
+ * jobWorkflowRef: "acme/app/.github/workflows/release.yml@refs/heads/main",
101
+ * repositoryId: "1",
102
+ * repositoryOwnerId: "2",
103
+ * runnerEnvironment: "github-hosted",
104
+ * runId: "3",
105
+ * runAttempt: "1",
106
+ * });
94
107
  * ```
95
108
  *
96
109
  * @public
package/index.d.ts CHANGED
@@ -38,13 +38,21 @@ interface IdentityTokenShape {
38
38
  }
39
39
  declare const IdentityToken_base: Context.ServiceClass<IdentityToken, "@effected/sbom/IdentityToken", IdentityTokenShape>;
40
40
  /**
41
- * A source of workload identity tokens.
41
+ * A source of workload identity tokens (OIDC), the input `SigstoreSigner` needs
42
+ * to obtain a signing certificate.
43
+ *
44
+ * @remarks
45
+ * In GitHub Actions, provide `ActionsIdentityToken.layer` from
46
+ * `@effected/github-actions`. A consumer that already holds a token uses
47
+ * {@link (IdentityToken:class).layerStatic}; tests use
48
+ * {@link (IdentityToken:class).layerTest}.
42
49
  *
43
50
  * @example
44
51
  * ```ts
45
52
  * import { IdentityToken, SigstoreSigner } from "@effected/sbom";
46
53
  * import { Layer } from "effect";
47
54
  *
55
+ * const token = process.env.OIDC_TOKEN ?? "";
48
56
  * const layer = SigstoreSigner.layer.pipe(Layer.provide(IdentityToken.layerStatic(token)));
49
57
  * ```
50
58
  *
@@ -124,7 +132,7 @@ export declare class InvalidSha256DigestError extends InvalidSha256DigestError_b
124
132
  * A deliberate small duplication rather than a shared package: `@effected/github`
125
133
  * types the same value structurally on its attestation surface, and dragging a
126
134
  * 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.
135
+ * duplication does.
128
136
  *
129
137
  * @public
130
138
  */
@@ -169,7 +177,7 @@ export declare class InTotoSubject extends InTotoSubject_base {
169
177
  /**
170
178
  * Input to {@link (InTotoStatement:class).of}.
171
179
  *
172
- * @remarks
180
+ * @privateRemarks
173
181
  * The two predicate members are spelled out here and again on
174
182
  * {@link InTotoSubjectInput} rather than shared through a base interface: an
175
183
  * internal type named on a `@public` signature is a forgotten export, and a
@@ -227,12 +235,16 @@ declare const InTotoStatement_base: Schema.Class<InTotoStatement, Schema.Struct<
227
235
  * @example
228
236
  * ```ts
229
237
  * import { InTotoStatement, Sha256Digest, SlsaProvenance } from "@effected/sbom";
238
+ * import { Effect } from "effect";
230
239
  *
231
- * const statement = InTotoStatement.forSubject({
232
- * name: "pkg:npm/%40scope/pkg@1.0.0",
233
- * digest,
234
- * predicateType: SlsaProvenance.predicateType,
235
- * predicate: provenance,
240
+ * const program = Effect.gen(function* () {
241
+ * const digest = yield* Sha256Digest.parse("ab".repeat(32));
242
+ * return InTotoStatement.forSubject({
243
+ * name: "pkg:npm/%40scope/pkg@1.0.0",
244
+ * digest,
245
+ * predicateType: SlsaProvenance.predicateType,
246
+ * predicate: {}, // a SlsaProvenance, a BOM, or any predicate body
247
+ * });
236
248
  * });
237
249
  * ```
238
250
  *
@@ -367,7 +379,7 @@ declare const Component_base: Schema.Class<Component, Schema.Struct<{
367
379
  * @remarks
368
380
  * `bomRef` is spelled **`bom-ref`** in the emitted JSON; the rename happens in
369
381
  * `Sbom.toJson`. Emitting `bomRef` produces a document that looks
370
- * correct and validates wrong, which is why a test pins the key name.
382
+ * correct and validates wrong.
371
383
  *
372
384
  * @public
373
385
  */
@@ -452,10 +464,13 @@ declare const NtiaReport_base: Schema.Class<NtiaReport, Schema.Struct<{
452
464
  *
453
465
  * @example
454
466
  * ```ts
455
- * import { NtiaReport } from "@effected/sbom";
467
+ * import { Component, NtiaReport, Sbom } from "@effected/sbom";
456
468
  *
457
- * const report = NtiaReport.of(document);
458
- * if (!report.compliant) yield* Effect.logWarning(`SBOM missing: ${report.missing.join(", ")}`);
469
+ * const root = Component.make({ type: "library", name: "lib", version: "1.0.0" });
470
+ * const report = NtiaReport.of(Sbom.generate({ root, components: [] }));
471
+ *
472
+ * report.compliant; // => false
473
+ * report.missing; // => ["supplierName", "uniqueIdentifier", "sbomAuthor", "timestamp"]
459
474
  * ```
460
475
  *
461
476
  * @public
@@ -518,10 +533,11 @@ export declare class SbomWriteError extends SbomWriteError_base {
518
533
  *
519
534
  * @example
520
535
  * ```ts
521
- * import { Sbom } from "@effected/sbom";
536
+ * import { Component, Sbom } from "@effected/sbom";
522
537
  *
523
- * const document = Sbom.generate({ root, components });
524
- * const json = Sbom.toJson(document);
538
+ * const root = Component.make({ type: "application", name: "app", version: "1.0.0" });
539
+ * const document = Sbom.generate({ root, components: [] });
540
+ * const json = Sbom.toJson(document); // CycloneDX 1.6 JSON text
525
541
  * ```
526
542
  *
527
543
  * @public
@@ -550,7 +566,8 @@ export declare class Sbom {
550
566
  * Write a document to `path` as canonical JSON.
551
567
  *
552
568
  * @remarks
553
- * The one fallible member. It does not create parent directories — a caller
569
+ * The one fallible member; it fails with {@link SbomWriteError} and requires
570
+ * `FileSystem` in `R`. It does not create parent directories — a caller
554
571
  * that wants one creates it, so the failure mode stays "the path you gave me
555
572
  * is not writable" rather than "something was created somewhere".
556
573
  */
@@ -615,7 +632,7 @@ interface ComponentInput {
615
632
  interface CopyrightYears {
616
633
  /** The first year of the range. Omit for a single-year statement. */
617
634
  readonly startYear?: number | undefined;
618
- /** The year the statement is current through — the caller's clock read, never ours. */
635
+ /** The year the statement is current through, supplied by the caller. */
619
636
  readonly year: number;
620
637
  }
621
638
  /**
@@ -623,11 +640,16 @@ interface CopyrightYears {
623
640
  *
624
641
  * @example
625
642
  * ```ts
626
- * import { Sbom, SbomMetadataSource } from "@effected/sbom";
643
+ * import { Package, Sbom, SbomMetadataSource, Supplier } from "@effected/sbom";
644
+ * import { Effect } from "effect";
627
645
  *
628
- * const root = SbomMetadataSource.rootComponent(pkg, { supplier });
629
- * const metadata = SbomMetadataSource.fromPackage(pkg, { supplier, timestamp });
630
- * const document = Sbom.generate({ root, components, metadata });
646
+ * const program = Effect.gen(function* () {
647
+ * const pkg = yield* Package.decode({ name: "@acme/app", version: "1.0.0", license: "MIT" });
648
+ * const supplier = Supplier.make({ name: "Acme Inc." });
649
+ * const root = SbomMetadataSource.rootComponent(pkg, { supplier });
650
+ * const metadata = SbomMetadataSource.fromPackage(pkg, { supplier, timestamp: "2026-01-01T00:00:00Z" });
651
+ * return Sbom.generate({ root, components: [], metadata });
652
+ * });
631
653
  * ```
632
654
  *
633
655
  * @public
@@ -699,10 +721,8 @@ export declare class SbomMetadataSource {
699
721
  * A copyright statement for a holder and a year, or a span of years.
700
722
  *
701
723
  * @remarks
702
- * The year is an **argument**. The predecessor defaulted it to
703
- * `new Date().getFullYear()`, which made its output untestable and its
704
- * purity a claim rather than a property; the ambient read belongs at the
705
- * caller's edge.
724
+ * The year is an **argument**: nothing here reads the clock, so the output is
725
+ * deterministic. Read the ambient year at the caller's edge.
706
726
  */
707
727
  static readonly formatCopyright: (holder: string, years: CopyrightYears) => string;
708
728
  /**
@@ -749,8 +769,8 @@ declare const SigstoreBundle_base: Schema.Class<SigstoreBundle, Schema.Struct<{
749
769
  * @remarks
750
770
  * `verificationMaterial` and `dsseEnvelope` are `unknown` because their shapes
751
771
  * belong to the Sigstore protobuf specifications, and re-declaring them here
752
- * would be a second, drifting copy of a wire format we do not own. The bundle
753
- * is opaque to everything that merely stores or forwards it.
772
+ * would be a second, drifting copy of a wire format this package does not own.
773
+ * The bundle is opaque to everything that merely stores or forwards it.
754
774
  *
755
775
  * `mediaType` is carried through from what the builder produced rather than
756
776
  * asserted — the version is the producer's statement about the bundle, and a
@@ -770,9 +790,7 @@ export declare class SigstoreBundle extends SigstoreBundle_base {}
770
790
  * It lives here, not at the call site, because it is the **signing protocol's**
771
791
  * requirement rather than the caller's knowledge — which is why
772
792
  * {@link SigstoreSignerShape.sign} takes only a statement and asks the identity
773
- * contract for a token. Considered and rejected: `sign(statement, { token })`,
774
- * which reads simpler and forces every caller to learn a constant that is none
775
- * of its business.
793
+ * contract for a token.
776
794
  *
777
795
  * @public
778
796
  */
@@ -848,17 +866,28 @@ interface SigstoreSignerShape {
848
866
  }
849
867
  declare const SigstoreSigner_base: Context.ServiceClass<SigstoreSigner, "@effected/sbom/SigstoreSigner", SigstoreSignerShape>;
850
868
  /**
851
- * Sigstore signing.
869
+ * Signs an in-toto statement into a Sigstore DSSE bundle, using a Fulcio
870
+ * certificate and a Rekor transparency-log entry.
871
+ *
872
+ * @remarks
873
+ * Fails with {@link SigningError}. The live {@link (SigstoreSigner:class).layer}
874
+ * requires {@link IdentityToken} in `R`.
852
875
  *
853
876
  * @example
854
877
  * ```ts
878
+ * import type { InTotoStatement } from "@effected/sbom";
855
879
  * import { IdentityToken, SigstoreSigner } from "@effected/sbom";
856
- * import { Effect, Layer } from "effect";
880
+ * import { Effect, Layer, Redacted } from "effect";
857
881
  *
858
- * const program = Effect.gen(function* () {
859
- * const signer = yield* SigstoreSigner;
860
- * return yield* signer.sign(statement);
861
- * });
882
+ * const sign = (statement: InTotoStatement) =>
883
+ * Effect.gen(function* () {
884
+ * const signer = yield* SigstoreSigner;
885
+ * return yield* signer.sign(statement);
886
+ * });
887
+ *
888
+ * const live = SigstoreSigner.layer.pipe(
889
+ * Layer.provide(IdentityToken.layerStatic(Redacted.make(process.env.OIDC_TOKEN ?? ""))),
890
+ * );
862
891
  * ```
863
892
  *
864
893
  * @public
@@ -970,8 +999,7 @@ export declare class SlsaRunDetails extends SlsaRunDetails_base {}
970
999
  *
971
1000
  * @remarks
972
1001
  * A plain input record, **not** a service. There is nothing to swap and no IO
973
- * to invert — it is the argument to a data constructor, and inventing a seam
974
- * for one would repeat a mistake this program already reversed once.
1002
+ * to invert — it is the argument to a data constructor.
975
1003
  *
976
1004
  * Fields are camelCase here and re-spelled to the platform's claim names where
977
1005
  * the predicate demands it, so a caller reads its own vocabulary and the
@@ -1018,7 +1046,20 @@ declare const SlsaProvenance_base: Schema.Class<SlsaProvenance, Schema.Struct<{
1018
1046
  * ```ts
1019
1047
  * import { SlsaProvenance } from "@effected/sbom";
1020
1048
  *
1021
- * const provenance = SlsaProvenance.forGitHubWorkflow(claims);
1049
+ * const provenance = SlsaProvenance.forGitHubWorkflow({
1050
+ * serverUrl: "https://github.com",
1051
+ * repository: "acme/app",
1052
+ * ref: "refs/heads/main",
1053
+ * sha: "0123456789abcdef0123456789abcdef01234567",
1054
+ * eventName: "push",
1055
+ * workflowRef: "acme/app/.github/workflows/release.yml@refs/heads/main",
1056
+ * jobWorkflowRef: "acme/app/.github/workflows/release.yml@refs/heads/main",
1057
+ * repositoryId: "1",
1058
+ * repositoryOwnerId: "2",
1059
+ * runnerEnvironment: "github-hosted",
1060
+ * runId: "3",
1061
+ * runAttempt: "1",
1062
+ * });
1022
1063
  * ```
1023
1064
  *
1024
1065
  * @public
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/sbom",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "private": false,
5
5
  "description": "CycloneDX 1.6 SBOM construction, SLSA provenance, NTIA validation and Sigstore signing as typed services.",
6
6
  "keywords": [
@@ -39,13 +39,13 @@
39
39
  "./package.json": "./package.json"
40
40
  },
41
41
  "dependencies": {
42
- "@effected/package-json": "^0.19.1",
43
- "@effected/spdx": "^0.10.0",
42
+ "@effected/package-json": "^0.20.0",
43
+ "@effected/spdx": "^0.11.0",
44
44
  "@sigstore/bundle": "^5.0.0",
45
45
  "@sigstore/sign": "^5.0.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "effect": "4.0.0-rc.118"
48
+ "effect": "^4.0.0"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=24.11.0"