borgmcp-shared 0.2.2 → 0.4.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/README.md +52 -35
- package/dist/conformance/adapter.d.ts +34 -6
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +215 -54
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +49 -0
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +111 -0
- package/dist/conformance/index.js.map +1 -1
- package/dist/protocol/contract.d.ts +81 -28
- package/dist/protocol/contract.d.ts.map +1 -1
- package/dist/protocol/contract.js +213 -128
- package/dist/protocol/contract.js.map +1 -1
- package/dist/protocol/errors.d.ts +2 -4
- package/dist/protocol/errors.d.ts.map +1 -1
- package/dist/protocol/errors.js +1 -1
- package/dist/protocol/errors.js.map +1 -1
- package/dist/protocol/version.d.ts +2 -10
- package/dist/protocol/version.d.ts.map +1 -1
- package/dist/protocol/version.js +1 -13
- package/dist/protocol/version.js.map +1 -1
- package/docs/compatibility.md +44 -25
- package/docs/enrollment.md +167 -0
- package/docs/releasing.md +77 -6
- package/package.json +2 -1
- package/src/conformance/adapter.ts +386 -63
- package/src/conformance/index.ts +139 -0
- package/src/protocol/contract.ts +373 -180
- package/src/protocol/errors.ts +7 -3
- package/src/protocol/version.ts +3 -30
package/docs/compatibility.md
CHANGED
|
@@ -1,38 +1,57 @@
|
|
|
1
1
|
# Protocol Compatibility
|
|
2
2
|
|
|
3
|
-
`borgmcp-shared`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
`borgmcp-shared` carries the wire contract shared by the Borg MCP client and
|
|
4
|
+
server. The client and server are a single clean-slate product: they ship and
|
|
5
|
+
update together, so the contract has no negotiation surface and no
|
|
6
|
+
backwards-compatibility machinery.
|
|
7
|
+
|
|
8
|
+
## Exact Protocol Tag
|
|
9
|
+
|
|
10
|
+
`PROTOCOL_VERSION` is the sole acceptance authority. The credential-free,
|
|
11
|
+
mutation-free `GET /api/protocol` preflight returns only the exact tag, and
|
|
12
|
+
`decodeProtocolTagPreflight` fails closed on any other tag, an extra field, or a
|
|
13
|
+
non-object body with a clear static mismatch diagnostic — so a client verifies
|
|
14
|
+
pinned TLS and the tag before it creates or sends any credential. Every
|
|
15
|
+
subsequent envelope also carries the tag and decodes it before any payload as
|
|
16
|
+
defense in depth. There is no capability negotiation, no supported-version list,
|
|
17
|
+
no compatibility matrix, and no package-range or version-range fallback. A peer
|
|
18
|
+
that presents a different tag is rejected — it is never adapted to.
|
|
11
19
|
|
|
12
20
|
## Change Policy
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
the
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
compatibility review. A broad `<1.0.0` range is unsafe because pre-1.0 minor
|
|
19
|
-
versions may break the wire contract.
|
|
22
|
+
A wire-shape change is simply made: the protocol tag increments and both the
|
|
23
|
+
client and server adopt the new tag together in a coordinated release. There is
|
|
24
|
+
no mixed-version window in which an old client and a new server (or the reverse)
|
|
25
|
+
interoperate; incompatible peers fail closed rather than degrade.
|
|
20
26
|
|
|
21
|
-
A wire-shape change must include
|
|
27
|
+
A wire-shape change must include:
|
|
22
28
|
|
|
23
29
|
1. A new or updated implementation-neutral conformance vector.
|
|
24
30
|
2. A documented client and server rollout order.
|
|
25
|
-
3. A
|
|
26
|
-
|
|
27
|
-
4. A migration window when older deployed clients or servers can still be in
|
|
28
|
-
use.
|
|
31
|
+
3. A package version bump so the new protocol tag never ships under a version
|
|
32
|
+
whose already-published artifact carries a different tag.
|
|
29
33
|
|
|
30
34
|
Removing or reinterpreting an existing field is a protocol-breaking change even
|
|
31
35
|
when TypeScript permits it. Implementations must not infer compatibility from a
|
|
32
|
-
successful build alone
|
|
33
|
-
|
|
36
|
+
successful build alone — they must run the shared conformance suite against the
|
|
37
|
+
exact tag they implement.
|
|
38
|
+
|
|
39
|
+
## Coordinated Rollout
|
|
40
|
+
|
|
41
|
+
The rollout order is fail-closed:
|
|
42
|
+
|
|
43
|
+
1. Publish the reviewed `borgmcp-shared` registry artifact only after its
|
|
44
|
+
separate tag and publication gates pass, under a version that has never been
|
|
45
|
+
published with a different protocol tag.
|
|
46
|
+
2. Update the client and server releases to the reviewed registry range; Git
|
|
47
|
+
dependencies are not an authorized release input.
|
|
48
|
+
3. Run the shared adapter conformance suite in both consumers before release.
|
|
49
|
+
4. Deploy client and server support together. A peer on the prior protocol tag
|
|
50
|
+
and a peer on the new tag are incompatible; neither side falls back.
|
|
51
|
+
|
|
52
|
+
## Model/Provider Selection
|
|
34
53
|
|
|
35
|
-
Model/provider selection is intentionally absent from the
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
Model/provider selection is intentionally absent from the coordination contract.
|
|
55
|
+
Agent CLIs own model configuration; Borg servers may expose the separate
|
|
56
|
+
advisory `reported_model` field for session observability, but clients must not
|
|
57
|
+
use it for routing, launch configuration, or authorization.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Retry-Safe Enrollment and Cube Creation Contract
|
|
2
|
+
|
|
3
|
+
This document defines the data-only enrollment and cube-creation boundaries
|
|
4
|
+
shared by clients and servers. It does not define offline operator commands,
|
|
5
|
+
database transactions, or keychain APIs, but implementations must preserve the
|
|
6
|
+
security properties below.
|
|
7
|
+
|
|
8
|
+
This contract replaces the server-generated bearer response used by the
|
|
9
|
+
published `borgmcp-shared@0.3.0` v1 baseline. It is a breaking clean-slate v2
|
|
10
|
+
wire change; this source now identifies the still-unpublished `0.4.0` candidate
|
|
11
|
+
and requires a coordinated client/server release. The version bump grants no tag
|
|
12
|
+
or publication authority — creating the `v0.4.0` tag and the registry
|
|
13
|
+
publication remain separate, independently gated steps. There is no
|
|
14
|
+
compatibility path that returns a bearer from the server.
|
|
15
|
+
|
|
16
|
+
A client verifies the credential-free `GET /api/protocol` tag preflight before
|
|
17
|
+
it creates or sends any enrollment secret; a peer that presents a different
|
|
18
|
+
protocol tag is rejected outright. The exact protocol tag is the sole acceptance
|
|
19
|
+
authority, so there is no capability a server advertises or a client negotiates
|
|
20
|
+
for this contract. The enrollment
|
|
21
|
+
response still carries the enrolled principal's `server_capabilities` (owner
|
|
22
|
+
enrollment grants `['create_cube']`; ordinary enrollment grants none) — that is
|
|
23
|
+
an authorization fact about the principal, not a negotiated protocol capability.
|
|
24
|
+
|
|
25
|
+
## Client Preconditions
|
|
26
|
+
|
|
27
|
+
Before network I/O, the client generates:
|
|
28
|
+
|
|
29
|
+
- a cryptographically random 256-bit client bearer, encoded as canonical
|
|
30
|
+
unpadded base64url; and
|
|
31
|
+
- a canonical UUID retry key.
|
|
32
|
+
|
|
33
|
+
The client persists both values as a pending enrollment in the operating-system
|
|
34
|
+
keychain before sending the request. It retains and reuses the exact pending
|
|
35
|
+
tuple after an ambiguous timeout or connection loss. The wire contract never
|
|
36
|
+
permits a file fallback, URL/argv/environment transport, or diagnostic output
|
|
37
|
+
for these secrets.
|
|
38
|
+
|
|
39
|
+
## Exchange Request
|
|
40
|
+
|
|
41
|
+
`POST /api/enrollment/exchange` receives one strict payload inside the protocol
|
|
42
|
+
envelope:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"invitation": "<opaque invitation>",
|
|
47
|
+
"retry_key": "00000000-0000-4000-8000-000000000101",
|
|
48
|
+
"client_credential": "<43-character canonical base64url>",
|
|
49
|
+
"client_name": "optional presentation label"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`client_name` is bounded presentation data. All other fields are required.
|
|
54
|
+
Unknown fields, weak credentials, noncanonical UUIDs, controls, and ambiguous
|
|
55
|
+
aliases fail closed. Invitation purpose is server-owned persisted state; the
|
|
56
|
+
request has no caller-controlled owner flag, plan, role, grant, or cube.
|
|
57
|
+
|
|
58
|
+
## Secret-Free Responses
|
|
59
|
+
|
|
60
|
+
Ordinary enrollment returns only:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"purpose": "client",
|
|
65
|
+
"client_id": "<canonical UUID>",
|
|
66
|
+
"server_capabilities": []
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
An ordinary enrollment creates no cube grant. It cannot infer access from
|
|
71
|
+
enrollment order, owner metadata, or a role label.
|
|
72
|
+
|
|
73
|
+
A successful purpose-bound owner enrollment returns only the narrow server
|
|
74
|
+
capability persisted for that client:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"purpose": "owner",
|
|
79
|
+
"client_id": "<canonical UUID>",
|
|
80
|
+
"server_capabilities": ["create_cube"]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The response never contains, echoes, rotates, or recovers the client bearer,
|
|
85
|
+
invitation, retry key, recovery credential, or a session credential. Owner
|
|
86
|
+
enrollment creates zero cubes, roles, and cube grants. `create_cube` authorizes
|
|
87
|
+
only authenticated cube creation; it does not reveal or grant access to any
|
|
88
|
+
existing cube and is never inferred from enrollment order, owner metadata, or a
|
|
89
|
+
role label.
|
|
90
|
+
|
|
91
|
+
## Retry Semantics
|
|
92
|
+
|
|
93
|
+
The server binds the consumed invitation to the canonical retry tuple and stores
|
|
94
|
+
only a keyed client credential digest. A retry is successful only when the retry key,
|
|
95
|
+
submitted credential proof, optional client name, invitation purpose, and
|
|
96
|
+
server-owned owner-claim epoch exactly match the original enrollment. It
|
|
97
|
+
returns the same non-secret response and performs no mutation.
|
|
98
|
+
|
|
99
|
+
A reused invitation with a different retry key, credential, client name,
|
|
100
|
+
purpose, epoch, or plan receives the same non-enumerating `AUTH_INVALID` class as
|
|
101
|
+
an absent, expired, revoked, malformed, or already-consumed invitation. It never
|
|
102
|
+
rotates credentials or creates another client, capability, cube, role, or grant.
|
|
103
|
+
|
|
104
|
+
## Server Transaction Boundary
|
|
105
|
+
|
|
106
|
+
For an owner invitation, the server capacity-preflights and atomically binds the
|
|
107
|
+
invitation/retry tuple, inserts the keyed client credential digest, persists the
|
|
108
|
+
`create_cube` capability, and marks the invitation/owner epoch claimed. It
|
|
109
|
+
creates no cube, role, or cube grant. Any failure rolls back every mutation,
|
|
110
|
+
including invitation consumption.
|
|
111
|
+
|
|
112
|
+
Ordinary invitation exchange atomically creates only the client and credential
|
|
113
|
+
digest. Explicit grants are a separate offline administrative operation. Network
|
|
114
|
+
enrollment and attach routes never create or widen grants.
|
|
115
|
+
|
|
116
|
+
## Cube Creation
|
|
117
|
+
|
|
118
|
+
`POST /api/cubes` requires an active parent-client credential with the persisted
|
|
119
|
+
`create_cube` server capability. Ordinary clients, revoked clients, and drone
|
|
120
|
+
sessions cannot use it. Its strict payload is:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"retry_key": "00000000-0000-4000-8000-000000000201",
|
|
125
|
+
"name": "repository presentation name",
|
|
126
|
+
"template": "default"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The client persists the pending retry tuple before network I/O and reuses it
|
|
131
|
+
after ambiguous transport failure. `name` is bounded presentation data and
|
|
132
|
+
`template` selects allowlisted, server-owned inert data. The request cannot
|
|
133
|
+
supply cube or role IDs, an owner, access, grant target, capability, arbitrary
|
|
134
|
+
template data, paths, URLs, modules, commands, or repository credentials.
|
|
135
|
+
|
|
136
|
+
The server binds `(authenticated client, retry_key)` to the exact canonical name
|
|
137
|
+
and template. A successful transaction atomically creates one cube, exactly one
|
|
138
|
+
human-seat role, exactly one default worker role, and exactly one creator
|
|
139
|
+
`manage` grant. It returns:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"cube_id": "<canonical UUID>",
|
|
144
|
+
"human_seat_role_id": "<canonical UUID>",
|
|
145
|
+
"default_worker_role_id": "<canonical UUID>",
|
|
146
|
+
"access": "manage"
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
An exact retry returns that stable response without mutation. Reusing the same
|
|
151
|
+
retry key with a different name or template returns non-enumerating HTTP `409`
|
|
152
|
+
`INVALID_INPUT` and creates nothing. A fresh retry key may create another cube,
|
|
153
|
+
subject to implementation quotas. `owner_id` and role labels remain metadata;
|
|
154
|
+
cube access derives only from the explicit cube-scoped grant.
|
|
155
|
+
|
|
156
|
+
## Conformance
|
|
157
|
+
|
|
158
|
+
`ENROLLMENT_RETRY_CONFORMANCE` covers exact retry stability plus retry-key,
|
|
159
|
+
credential, and client-name mismatches. `ENROLLMENT_REDACTION_CONFORMANCE` pins
|
|
160
|
+
diagnostic redaction for invitation, bearer, and contextual retry-key values
|
|
161
|
+
while preserving unrelated public UUIDs. `ENROLLMENT_AUTHORITY_CONFORMANCE`
|
|
162
|
+
distinguishes ordinary zero-authority enrollment from owner `create_cube`
|
|
163
|
+
authority with zero initial cube state. The executable adapter runner drives
|
|
164
|
+
every retry vector, observes client/capability/cube/role/grant counts, verifies
|
|
165
|
+
secret-free errors, and proves authorized idempotent cube creation. Hostile
|
|
166
|
+
reference adapters demonstrate that each retry, authority, and idempotency
|
|
167
|
+
violation fails conformance.
|
package/docs/releasing.md
CHANGED
|
@@ -122,6 +122,38 @@ Under the ratified `borgmcp-shared-recovery-version` decision, `0.2.2` is the
|
|
|
122
122
|
selected recovery version. The source bump does not itself authorize a tag,
|
|
123
123
|
environment approval, or publication.
|
|
124
124
|
|
|
125
|
+
Run `29360398007` published `borgmcp-shared@0.2.2` from the exact approved
|
|
126
|
+
artifact, and the registry integrity and maintainer matched that artifact. The
|
|
127
|
+
workflow then failed during immediate postpublish verification when the package
|
|
128
|
+
ownership read returned HTTP 404 before registry propagation completed. The run
|
|
129
|
+
and `v0.2.2` tag are immutable and MUST NOT be rerun, moved, or reused. Consumer
|
|
130
|
+
migration was blocked until provenance and signatures were independently verified
|
|
131
|
+
and Security approved the recovery evidence.
|
|
132
|
+
|
|
133
|
+
Recover out of band without rerunning the workflow:
|
|
134
|
+
|
|
135
|
+
1. Download artifact `8321897865` from run `29360398007` and recheck its recorded
|
|
136
|
+
ZIP digest, `RUN_EVIDENCE`, tarball SHA-512, and artifact verifier report.
|
|
137
|
+
2. With `GITHUB_SHA=508f2dc88658d8e00ff036b7ce6913fcfbef239b` and
|
|
138
|
+
`NPM_EXPECTED_OWNER=byteventures`, run
|
|
139
|
+
`node scripts/verify-registry-release.mjs postpublish <audited-tarball>`. The
|
|
140
|
+
verifier retries only transient HTTP 404 propagation responses. Its production
|
|
141
|
+
envelope performs at most 18 reads over approximately three and a half minutes
|
|
142
|
+
(1, 2, 4, and 8 second waits, then a 15 second cap). Non-404 failures and
|
|
143
|
+
integrity, owner, or provenance mismatches remain immediate terminal failures.
|
|
144
|
+
3. Install exact `borgmcp-shared@0.2.2` from the registry into a clean temporary
|
|
145
|
+
prefix with scripts disabled and run `npm audit signatures` against that
|
|
146
|
+
prefix.
|
|
147
|
+
4. Record the independent integrity, ownership, signed-provenance, and signature
|
|
148
|
+
evidence for a fresh Security verdict before changing any consumer dependency.
|
|
149
|
+
|
|
150
|
+
That recovery completed successfully: the registry tarball is byte-identical to
|
|
151
|
+
the audited artifact, its sole maintainer is `byteventures`, the signed in-toto
|
|
152
|
+
SLSA provenance binds the protected workflow/tag/commit/run, and npm verified one
|
|
153
|
+
registry signature plus one publish attestation. Security approved the recovery
|
|
154
|
+
evidence. Complete the bootstrap credential and Trusted Publisher cleanup below
|
|
155
|
+
before migrating consumers.
|
|
156
|
+
|
|
125
157
|
The eventual first publication will use one temporary credential while still
|
|
126
158
|
generating provenance from GitHub Actions.
|
|
127
159
|
|
|
@@ -185,6 +217,45 @@ Immediately after a successful first publish:
|
|
|
185
217
|
|
|
186
218
|
## Later Releases
|
|
187
219
|
|
|
220
|
+
### 0.4.0 Clean-Slate v2 Contract
|
|
221
|
+
|
|
222
|
+
The ratified `borgmcp-shared-enrollment-version` decision defined this breaking
|
|
223
|
+
retry-safe enrollment and idempotent multi-cube contract. `borgmcp-shared@0.3.0`
|
|
224
|
+
is now the published, immutable v1 baseline on the registry, so the clean-slate
|
|
225
|
+
v2 contract — credential-free tag preflight included — is versioned as the
|
|
226
|
+
still-unpublished `0.4.0` candidate (a breaking change on a `0.x` package bumps
|
|
227
|
+
the minor). This source now identifies `0.4.0`. That reviewed version bump
|
|
228
|
+
does not authorize creating `v0.4.0` or publishing the package, and the source
|
|
229
|
+
branch must not republish `0.3.0`.
|
|
230
|
+
|
|
231
|
+
Before a separately authorized `v0.4.0` tag is created:
|
|
232
|
+
|
|
233
|
+
1. The exact `0.4.0` source commit must be merged to protected `main` after Code
|
|
234
|
+
Review, Security, and Release Quality approve the package identity, public
|
|
235
|
+
API, conformance behavior, generated output, and release documentation.
|
|
236
|
+
2. The package and root lockfile, `SHARED_PACKAGE_VERSION`, the exact protocol
|
|
237
|
+
version tag, packed-artifact verifier, and version assertions all identify
|
|
238
|
+
`0.4.0` (done in this source bump).
|
|
239
|
+
3. The protected workflow must build one exact tarball and pass its full source,
|
|
240
|
+
test, audit, public-export, source-map, install/import, dry-run, lock-derived
|
|
241
|
+
CycloneDX SBOM, integrity, and provenance gates. Security must approve that
|
|
242
|
+
exact workflow artifact.
|
|
243
|
+
4. The `0.4.0` workflow must generate a CycloneDX SBOM, canonicalize npm's
|
|
244
|
+
checkout-derived root display name to the already-verified manifest name,
|
|
245
|
+
and validate every component's exact canonical registry tarball URL, single
|
|
246
|
+
matching CycloneDX distribution reference, purl, and lock SHA-512 plus the
|
|
247
|
+
exact installed dependency graph and zero package runtime dependencies. The
|
|
248
|
+
tarball, SBOM, and SBOM validation report must be
|
|
249
|
+
checksummed and uploaded together for Security audit.
|
|
250
|
+
5. The tag and publication each require their own explicit authorization. A
|
|
251
|
+
source-version approval, merge, or successful verification run grants neither.
|
|
252
|
+
|
|
253
|
+
After registry publication and independent integrity/provenance verification,
|
|
254
|
+
the first borgmcp client and borgmcp-server releases may replace their temporary
|
|
255
|
+
development dependency with the reviewed registry range `^0.4.0`. They must not
|
|
256
|
+
ship a Git dependency or fall back to the incompatible published `0.3.0` v1
|
|
257
|
+
enrollment response.
|
|
258
|
+
|
|
188
259
|
Later releases follow the same source gates, annotated protected tag, exact
|
|
189
260
|
tarball audit, Queen authorization, and environment approval. The registry
|
|
190
261
|
preflight requires the package to be owned by `NPM_EXPECTED_OWNER` and rejects
|
|
@@ -210,11 +281,11 @@ Stop without approving the environment when any of these conditions occurs:
|
|
|
210
281
|
- final CR, Security, Release Quality, exact-tarball Security approval, or Queen
|
|
211
282
|
authorization is missing.
|
|
212
283
|
|
|
213
|
-
npm versions are immutable. Never retry by overwriting
|
|
214
|
-
force-pushing a branch, or publishing from a local rebuild.
|
|
215
|
-
before publication requires fixing the source and
|
|
216
|
-
reviewed version/tag plan. If npm accepted the version
|
|
217
|
-
provenance verification failed, block every consumer migration,
|
|
218
|
-
workflow logs and artifact, and escalate as a release incident. Do not unpublish,
|
|
284
|
+
npm versions are immutable. Never retry by overwriting any published version,
|
|
285
|
+
moving a release tag, force-pushing a branch, or publishing from a local rebuild.
|
|
286
|
+
A failed verification before publication requires fixing the source and
|
|
287
|
+
beginning again with a new reviewed version/tag plan. If npm accepted the version
|
|
288
|
+
but integrity or provenance verification failed, block every consumer migration,
|
|
289
|
+
preserve the workflow logs and artifact, and escalate as a release incident. Do not unpublish,
|
|
219
290
|
deprecate, or publish a replacement version without a separately reviewed and
|
|
220
291
|
authorized recovery decision.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borgmcp-shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared protocol, domain, templates, and conformance contracts for Borg MCP implementations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"check": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
57
57
|
"test": "vitest run",
|
|
58
58
|
"verify:artifact": "node scripts/verify-packed-artifact.mjs",
|
|
59
|
+
"verify:sbom": "node scripts/verify-release-sbom.mjs",
|
|
59
60
|
"prepack": "npm run check && npm test && npm run build"
|
|
60
61
|
},
|
|
61
62
|
"keywords": [
|