@pipobscure/bundle 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +1924 -0
- package/README.md +623 -0
- package/bundle.run +0 -0
- package/dist/api.d.ts +147 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +174 -0
- package/dist/api.js.map +1 -0
- package/dist/archive.d.ts +115 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +188 -0
- package/dist/archive.js.map +1 -0
- package/dist/audit.d.ts +78 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +119 -0
- package/dist/audit.js.map +1 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +555 -0
- package/dist/cli.js.map +1 -0
- package/dist/files.d.ts +53 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +118 -0
- package/dist/files.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/launch.d.ts +97 -0
- package/dist/launch.d.ts.map +1 -0
- package/dist/launch.js +267 -0
- package/dist/launch.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +19 -0
- package/dist/main.js.map +1 -0
- package/dist/manifest.d.ts +139 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +504 -0
- package/dist/manifest.js.map +1 -0
- package/dist/oidc.d.ts +40 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/oidc.js +320 -0
- package/dist/oidc.js.map +1 -0
- package/dist/preload.d.ts +14 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +38 -0
- package/dist/preload.js.map +1 -0
- package/dist/provider.d.ts +83 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +206 -0
- package/dist/provider.js.map +1 -0
- package/dist/record.d.ts +2 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +23 -0
- package/dist/record.js.map +1 -0
- package/dist/recorder.d.ts +64 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +111 -0
- package/dist/recorder.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +28 -0
- package/dist/register.js.map +1 -0
- package/dist/sea.d.ts +97 -0
- package/dist/sea.d.ts.map +1 -0
- package/dist/sea.js +220 -0
- package/dist/sea.js.map +1 -0
- package/dist/sigstore.d.ts +112 -0
- package/dist/sigstore.d.ts.map +1 -0
- package/dist/sigstore.js +385 -0
- package/dist/sigstore.js.map +1 -0
- package/dist/skill.d.ts +36 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +108 -0
- package/dist/skill.js.map +1 -0
- package/package.json +84 -0
- package/shell-base +2 -0
- package/skills/audit-bundle/SKILL.md +271 -0
- package/src/api.ts +293 -0
- package/src/archive.ts +312 -0
- package/src/audit.ts +206 -0
- package/src/cli.ts +575 -0
- package/src/files.ts +156 -0
- package/src/index.ts +114 -0
- package/src/launch.ts +336 -0
- package/src/main.ts +20 -0
- package/src/manifest.ts +615 -0
- package/src/oidc.ts +372 -0
- package/src/preload.ts +40 -0
- package/src/provider.ts +270 -0
- package/src/record.ts +25 -0
- package/src/recorder.ts +166 -0
- package/src/register.ts +30 -0
- package/src/sea.ts +341 -0
- package/src/sigstore.ts +492 -0
- package/src/skill.ts +132 -0
- package/src/types/node-vfs.d.ts +90 -0
- package/src/types/node-zip.d.ts +85 -0
package/dist/sea.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as FS from 'node:fs';
|
|
2
|
+
import * as OS from 'node:os';
|
|
3
|
+
import * as PATH from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import { mount, start, verify } from './launch.js';
|
|
6
|
+
import { signBundle, createBundle } from './api.js';
|
|
7
|
+
import { moduleFiles, packageRoot, moduleDir } from './files.js';
|
|
8
|
+
/**
|
|
9
|
+
* Verify the running container and mount the archive appended to it. Returns
|
|
10
|
+
* where it landed; nothing has been executed out of it yet.
|
|
11
|
+
*/
|
|
12
|
+
export function mountSelf(options = {}) {
|
|
13
|
+
return mount(options.container ?? process.execPath, options);
|
|
14
|
+
}
|
|
15
|
+
/** Verify the running container, mount it, and run the application inside. */
|
|
16
|
+
export async function bootstrap(options = {}) {
|
|
17
|
+
await start(mountSelf(options));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Verify the running container without mounting it — for an application that
|
|
21
|
+
* wants to report on its own provenance ("signed by X at Y").
|
|
22
|
+
*/
|
|
23
|
+
export function verifySelf(options = {}) {
|
|
24
|
+
return verify(options.container ?? process.execPath, options);
|
|
25
|
+
}
|
|
26
|
+
// -------------------------------------------------------------------- build ---
|
|
27
|
+
/** The default flags the container runs itself with. */
|
|
28
|
+
export const SEA_EXEC_ARGV = ['--no-warnings', '--experimental-vfs'];
|
|
29
|
+
/**
|
|
30
|
+
* Build the SEA base: a node runtime whose injected main mounts this package
|
|
31
|
+
* out of its own blob and hands over to `bootstrap()`. The result is a binary
|
|
32
|
+
* with no application in it yet — append one with `buildSea` or with
|
|
33
|
+
* `sign --prefix`.
|
|
34
|
+
*/
|
|
35
|
+
export async function createSeaBase(options) {
|
|
36
|
+
const scratch = options.scratch ?? FS.mkdtempSync(PATH.join(OS.tmpdir(), 'bundle-sea-'));
|
|
37
|
+
const owned = !options.scratch;
|
|
38
|
+
try {
|
|
39
|
+
let verifier = options.verifier;
|
|
40
|
+
let contents;
|
|
41
|
+
if (verifier) {
|
|
42
|
+
contents = [];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
verifier = PATH.join(scratch, 'verifier.bundle');
|
|
46
|
+
const files = verifierFiles(options);
|
|
47
|
+
await createBundle({ base: packageRoot(), files, output: verifier });
|
|
48
|
+
contents = files;
|
|
49
|
+
}
|
|
50
|
+
const stub = PATH.join(scratch, 'stub.js');
|
|
51
|
+
FS.writeFileSync(stub, stubSource(anchorPolicy(options.bootstrap ?? {})));
|
|
52
|
+
const config = PATH.join(scratch, 'sea-config.json');
|
|
53
|
+
FS.writeFileSync(config, `${JSON.stringify({
|
|
54
|
+
main: stub,
|
|
55
|
+
output: PATH.resolve(options.output),
|
|
56
|
+
disableExperimentalSEAWarning: true,
|
|
57
|
+
useSnapshot: false,
|
|
58
|
+
useCodeCache: false,
|
|
59
|
+
// The verifier bundle is the executable's file system rather than
|
|
60
|
+
// an asset it has to unpack: node embeds the ZIP as it is and
|
|
61
|
+
// mounts it, and the stub — injected at the root of that mount —
|
|
62
|
+
// requires this package out of it by relative path.
|
|
63
|
+
useVfs: true,
|
|
64
|
+
vfsArchive: verifier,
|
|
65
|
+
// The stub is injected at the root of that bundle, where this
|
|
66
|
+
// package's own `"type": "module"` decides what a `.js` is — so it
|
|
67
|
+
// is an ES module, and saying so is what makes it one. Note that
|
|
68
|
+
// `"mainFormat": "commonjs"` would not do the opposite: the mount's
|
|
69
|
+
// package.json still wins, and the only way to a CommonJS stub is a
|
|
70
|
+
// `.cjs` extension.
|
|
71
|
+
mainFormat: 'module',
|
|
72
|
+
execArgv: options.execArgv ?? SEA_EXEC_ARGV,
|
|
73
|
+
execArgvExtension: 'none',
|
|
74
|
+
...(options.node ? { executable: PATH.resolve(options.node) } : {}),
|
|
75
|
+
}, null, 2)}\n`);
|
|
76
|
+
const built = spawnSync(process.execPath, ['--no-warnings', '--build-sea', config], { stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf-8' });
|
|
77
|
+
if (built.error)
|
|
78
|
+
throw built.error;
|
|
79
|
+
if (built.status !== 0) {
|
|
80
|
+
throw new Error(`--build-sea failed (exit ${built.status}): ${(built.stderr || built.stdout || '').trim()}`);
|
|
81
|
+
}
|
|
82
|
+
FS.chmodSync(options.output, 0o755);
|
|
83
|
+
// `--build-sea` ignores configuration keys it does not know, so a node
|
|
84
|
+
// without `vfsArchive` would produce a binary that builds cleanly and
|
|
85
|
+
// fails at startup with nothing mounted. Run the result once: it costs
|
|
86
|
+
// milliseconds and it is the difference between finding that out here
|
|
87
|
+
// and finding it out in front of a user. A cross-build cannot be run,
|
|
88
|
+
// so it is not checked — the platform it is for is not this one.
|
|
89
|
+
if (!options.node)
|
|
90
|
+
selftest(options.output);
|
|
91
|
+
return { output: options.output, size: FS.statSync(options.output).size, verifier: contents };
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
if (owned)
|
|
95
|
+
FS.rmSync(scratch, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Build a self-validating executable: a SEA base with `app` appended and the
|
|
100
|
+
* whole thing signed as one file. Everything the container will check — the
|
|
101
|
+
* runtime, the verifier and the application — is inside what the signature
|
|
102
|
+
* covers.
|
|
103
|
+
*/
|
|
104
|
+
export async function buildSea(options) {
|
|
105
|
+
const log = options.log ?? (() => { });
|
|
106
|
+
const scratch = options.scratch ?? FS.mkdtempSync(PATH.join(OS.tmpdir(), 'bundle-sea-'));
|
|
107
|
+
const owned = !options.scratch;
|
|
108
|
+
try {
|
|
109
|
+
let base = options.base;
|
|
110
|
+
if (!base) {
|
|
111
|
+
base = PATH.join(scratch, 'sea-base');
|
|
112
|
+
log('* building the SEA base (node runtime + verifier)');
|
|
113
|
+
const built = await createSeaBase({ ...options, output: base, scratch });
|
|
114
|
+
log(` base: ${built.size} bytes, ${built.verifier.length} verifier members`);
|
|
115
|
+
}
|
|
116
|
+
log(`* appending ${options.app} behind ${PATH.basename(base)}`);
|
|
117
|
+
const res = await signBundle({
|
|
118
|
+
source: options.app,
|
|
119
|
+
output: options.output,
|
|
120
|
+
prefix: base,
|
|
121
|
+
executable: true,
|
|
122
|
+
hashAlg: options.hashAlg,
|
|
123
|
+
signAlg: options.signAlg,
|
|
124
|
+
signer: options.signer,
|
|
125
|
+
});
|
|
126
|
+
log(res.signed ? `* signed: ${res.hash}` : '* built unsigned — it will refuse to run until it is signed');
|
|
127
|
+
return res;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
if (owned)
|
|
131
|
+
FS.rmSync(scratch, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The files the embedded verifier needs, as paths relative to this package's
|
|
136
|
+
* root. That is this package's own compiled modules plus, unless turned off,
|
|
137
|
+
* the sigstore libraries — resolved through `node_modules` rather than listed,
|
|
138
|
+
* so the set cannot fall behind the dependency tree.
|
|
139
|
+
*/
|
|
140
|
+
export function verifierFiles({ sigstore = true } = {}) {
|
|
141
|
+
return moduleFiles({
|
|
142
|
+
base: packageRoot(),
|
|
143
|
+
files: ['package.json'],
|
|
144
|
+
dirs: [moduleDir()],
|
|
145
|
+
dependencies: sigstore ? SIGSTORE_PACKAGES : [],
|
|
146
|
+
// Source maps and declarations are for reading the code, not running
|
|
147
|
+
// it, and a verifier that ships inside every executable should carry
|
|
148
|
+
// only what it executes.
|
|
149
|
+
filter: (name) => !name.endsWith('.map') && !name.endsWith('.d.ts') && !name.endsWith('.d.cts'),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** The sigstore libraries verification needs; signing pulls in more at runtime. */
|
|
153
|
+
const SIGSTORE_PACKAGES = ['@sigstore/verify', '@sigstore/bundle', '@sigstore/protobuf-specs', '@sigstore/tuf'];
|
|
154
|
+
/**
|
|
155
|
+
* Resolve the paths in a baked policy, because a policy is baked *here* and read
|
|
156
|
+
* *there*. `--root build/certs/root.pem` is a sentence about the directory the
|
|
157
|
+
* build ran in; the binary that carries it may be run anywhere, by anyone, and a
|
|
158
|
+
* trust root it cannot find is a container that refuses everything. PEM text
|
|
159
|
+
* passes through untouched — it is not a path and has no directory to be
|
|
160
|
+
* relative to.
|
|
161
|
+
*/
|
|
162
|
+
function anchorPolicy(options) {
|
|
163
|
+
const anchored = { ...options };
|
|
164
|
+
if (options.roots) {
|
|
165
|
+
anchored.roots = options.roots.map((root) => (root.includes('-----BEGIN') ? root : PATH.resolve(root)));
|
|
166
|
+
}
|
|
167
|
+
if (options.trustedRoot)
|
|
168
|
+
anchored.trustedRoot = PATH.resolve(options.trustedRoot);
|
|
169
|
+
return anchored;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Run the built binary once, to prove that the file system inside it mounts and
|
|
173
|
+
* this package can be required out of it. `--version` is the cheapest thing
|
|
174
|
+
* that touches all of that, and it works whichever shape the binary is.
|
|
175
|
+
*/
|
|
176
|
+
function selftest(output) {
|
|
177
|
+
const res = spawnSync(PATH.resolve(output), ['--version'], { stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf-8' });
|
|
178
|
+
if (res.error)
|
|
179
|
+
throw res.error;
|
|
180
|
+
if (res.status !== 0 || !/bundle/.test(res.stdout)) {
|
|
181
|
+
throw new Error(`the built executable does not run (exit ${res.status}): ${(res.stderr || res.stdout || '').trim()}\n` +
|
|
182
|
+
'A node whose --build-sea does not understand "vfsArchive" builds exactly this: ' +
|
|
183
|
+
'the configuration key is ignored, nothing is mounted, and the stub has nothing to require.');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The CommonJS stub injected as the SEA's main script. It runs at the root of
|
|
188
|
+
* the mounted verifier bundle, so requiring this package is a relative path and
|
|
189
|
+
* nothing more; everything else it needs to decide, `launch` decides by looking
|
|
190
|
+
* at the binary's own tail.
|
|
191
|
+
*
|
|
192
|
+
* It stays the one piece no test can exercise from source, so it stays small.
|
|
193
|
+
*/
|
|
194
|
+
export function stubSource(options) {
|
|
195
|
+
const dir = moduleDir();
|
|
196
|
+
const entry = `./${dir}/launch${dir === 'src' ? '.ts' : '.js'}`;
|
|
197
|
+
return `// Generated by @pipobscure/bundle. The SEA main, running at the root of the
|
|
198
|
+
// archive this executable carries: hand over to the launcher, which verifies
|
|
199
|
+
// either the archive appended to this file or the one named on the command
|
|
200
|
+
// line before running anything out of it.
|
|
201
|
+
import * as launch from ${JSON.stringify(entry)};
|
|
202
|
+
|
|
203
|
+
const OPTIONS = ${JSON.stringify(options, null, 2)};
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
// Only a binary with nothing behind it takes an archive from the command
|
|
207
|
+
// line. One with an *unsigned* archive appended is not a launcher with a
|
|
208
|
+
// stray tail — it is a container somebody forgot to sign, and saying so is
|
|
209
|
+
// worth more than falling back to a usage message.
|
|
210
|
+
const code = launch.appended(process.execPath) === 'none'
|
|
211
|
+
? await launch.main(process.argv.slice(2), OPTIONS)
|
|
212
|
+
: await launch.runSelf(OPTIONS);
|
|
213
|
+
if (typeof code === 'number' && code !== 0) process.exitCode = code;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
process.stderr.write(\`\${err && err.stack || err}\\n\`);
|
|
216
|
+
process.exitCode = 1;
|
|
217
|
+
}
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=sea.js.map
|
package/dist/sea.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sea.js","sourceRoot":"","sources":["../src/sea.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as CRYPTO from 'node:crypto';
|
|
2
|
+
import type { Signer } from './archive.ts';
|
|
3
|
+
import type * as SigstoreSpecs from '@sigstore/protobuf-specs';
|
|
4
|
+
export declare const DEFAULT_FULCIO_URL = "https://fulcio.sigstore.dev";
|
|
5
|
+
export declare const DEFAULT_REKOR_URL = "https://rekor.sigstore.dev";
|
|
6
|
+
export declare const DEFAULT_TSA_URL = "https://timestamp.sigstore.dev/api/v1/timestamp";
|
|
7
|
+
export declare const DEFAULT_TUF_MIRROR = "https://tuf-repo-cdn.sigstore.dev";
|
|
8
|
+
/** The comment field the sigstore bundle travels in. */
|
|
9
|
+
export declare const FIELD = "SIGSTORE";
|
|
10
|
+
/** Where a trust root came from, so a caller can say how fresh it is. */
|
|
11
|
+
export type TrustedRootOrigin = 'explicit' | 'environment' | 'cache' | 'seed';
|
|
12
|
+
export interface TrustedRootLocation {
|
|
13
|
+
origin: TrustedRootOrigin;
|
|
14
|
+
/** The file it was read from, or the seed's mirror key. */
|
|
15
|
+
path: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SigstoreIdentity {
|
|
18
|
+
subject?: string | undefined;
|
|
19
|
+
issuer?: string | undefined;
|
|
20
|
+
/** GitHub Actions tokens name the workflow that ran. */
|
|
21
|
+
workflow?: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface SigstoreSignerOptions {
|
|
24
|
+
/** An OIDC token to use instead of signing in. */
|
|
25
|
+
token?: string | undefined;
|
|
26
|
+
flow?: 'auto' | 'ci' | 'browser' | 'device' | undefined;
|
|
27
|
+
/** OIDC issuer (default: sigstore's Dex). */
|
|
28
|
+
issuer?: string | undefined;
|
|
29
|
+
/** Dex connector to jump to (default: 'github'). */
|
|
30
|
+
connector?: string | undefined;
|
|
31
|
+
fulcioURL?: string | undefined;
|
|
32
|
+
/** Transparency log; '' to skip. */
|
|
33
|
+
rekorURL?: string | undefined;
|
|
34
|
+
/** RFC 3161 timestamp authority; '' to skip. */
|
|
35
|
+
tsaURL?: string | undefined;
|
|
36
|
+
/** Digest the signature uses (default: 'sha256'). */
|
|
37
|
+
signAlg?: string | undefined;
|
|
38
|
+
log?: ((line: string) => void) | undefined;
|
|
39
|
+
}
|
|
40
|
+
/** A sigstore-backed `Signer`, with the identity it authenticated as. */
|
|
41
|
+
export interface SigstoreSigner extends Signer {
|
|
42
|
+
kind: 'sigstore';
|
|
43
|
+
identity: SigstoreIdentity;
|
|
44
|
+
}
|
|
45
|
+
export interface BundleVerification {
|
|
46
|
+
identity?: string | undefined;
|
|
47
|
+
issuer?: string | undefined;
|
|
48
|
+
signedAt?: Date | undefined;
|
|
49
|
+
}
|
|
50
|
+
/** Whether the sigstore libraries needed for *verification* are loadable. */
|
|
51
|
+
export declare function available(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Phase one: authenticate, mint an ephemeral keypair, and get a Fulcio
|
|
54
|
+
* certificate for it. Returns a signer whose `chain` can go straight into
|
|
55
|
+
* `AUTHORITY.PEM` and whose `sign()` finishes the job once the hash exists.
|
|
56
|
+
*/
|
|
57
|
+
export declare function signer(options?: SigstoreSignerOptions): Promise<SigstoreSigner>;
|
|
58
|
+
/**
|
|
59
|
+
* Verify a sigstore bundle over `artifact` (the whole-file hash bytes) and
|
|
60
|
+
* return the identity it establishes. Synchronous, because the mount path is:
|
|
61
|
+
* `provider.ts` decides whether to serve an archive before any of the program
|
|
62
|
+
* in it runs, and cannot await.
|
|
63
|
+
*
|
|
64
|
+
* Throws on a bundle that does not verify. `trustedRoot` must be supplied —
|
|
65
|
+
* this deliberately does not reach for the network.
|
|
66
|
+
*/
|
|
67
|
+
export declare function verifyBundle(encoded: string, artifact: Buffer, { trustedRoot, identity, issuer }: {
|
|
68
|
+
trustedRoot: SigstoreSpecs.TrustedRoot;
|
|
69
|
+
identity?: string | undefined;
|
|
70
|
+
issuer?: string | undefined;
|
|
71
|
+
}): BundleVerification;
|
|
72
|
+
/**
|
|
73
|
+
* The leaf certificate a sigstore bundle carries, as an X509Certificate — so a
|
|
74
|
+
* verifier can confirm the inspectable `AUTHORITY.PEM` names the same
|
|
75
|
+
* certificate the bundle was actually verified against.
|
|
76
|
+
*/
|
|
77
|
+
export declare function bundleCertificate(encoded: string): CRYPTO.X509Certificate | null;
|
|
78
|
+
/**
|
|
79
|
+
* Where the sigstore trust root would be read from, in the order tried:
|
|
80
|
+
* an explicit path, `BUNDLE_SIGSTORE_ROOT`, the cache `bundle trust` maintains,
|
|
81
|
+
* and finally the seed `@sigstore/tuf` ships. Returns null when none exists.
|
|
82
|
+
*
|
|
83
|
+
* The seed is the fallback rather than the first choice because it is frozen at
|
|
84
|
+
* the version of the library that was installed; `bundle trust` fetches the
|
|
85
|
+
* live one over TUF and that copy wins whenever it is present.
|
|
86
|
+
*/
|
|
87
|
+
export declare function trustedRootLocation(source?: string | undefined): TrustedRootLocation | null;
|
|
88
|
+
/**
|
|
89
|
+
* Load the sigstore trust root synchronously. Returns null when there is none —
|
|
90
|
+
* verification then reports that as a reason rather than failing, because
|
|
91
|
+
* "I could not check" and "this is forged" are different answers.
|
|
92
|
+
*/
|
|
93
|
+
export declare function trustedRootSync(source?: string | undefined): SigstoreSpecs.TrustedRoot | null;
|
|
94
|
+
/**
|
|
95
|
+
* Refresh the trust root over the network, through TUF — signed metadata with
|
|
96
|
+
* its own root of trust, not a plain download. Returns the cache path.
|
|
97
|
+
*/
|
|
98
|
+
export declare function refreshTrustedRoot({ mirror, force }?: {
|
|
99
|
+
mirror?: string | undefined;
|
|
100
|
+
force?: boolean | undefined;
|
|
101
|
+
}): Promise<string>;
|
|
102
|
+
/**
|
|
103
|
+
* Where `@sigstore/tuf` keeps the target it downloaded. Mirrors its own
|
|
104
|
+
* `appDataPath()` so the two agree without depending on a private export.
|
|
105
|
+
*/
|
|
106
|
+
export declare function cachedRootPath(mirror?: string): string;
|
|
107
|
+
/**
|
|
108
|
+
* A policy string that matches `value` and nothing else, for a verifier that
|
|
109
|
+
* reads its policy as a regular expression.
|
|
110
|
+
*/
|
|
111
|
+
export declare function exactly(value: string): string;
|
|
112
|
+
//# sourceMappingURL=sigstore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sigstore.d.ts","sourceRoot":"","sources":["../src/sigstore.ts"],"names":[],"mappings":"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"}
|