@charter-agreement-protocol/signer 0.2.1 → 0.3.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/CHANGELOG.md +149 -3
- package/CODE_OF_CONDUCT.md +87 -0
- package/CONTRIBUTING.md +71 -0
- package/README.md +211 -71
- package/SECURITY.md +55 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -4
- package/dist/signer.d.ts +17 -22
- package/dist/signer.js +258 -149
- package/package.json +13 -8
package/README.md
CHANGED
|
@@ -7,15 +7,12 @@ Holder-side companion signer for the
|
|
|
7
7
|
|
|
8
8
|
**CAP verifies; it never authorizes. This signer signs; it never takes
|
|
9
9
|
custody.** You keep the key (HSM, OS keychain, key server) behind a handle
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
the wrong-key guard against the snapshot's public key, and the post-sign
|
|
17
|
-
verification of the assembled artifact through the
|
|
18
|
-
`@charter-agreement-protocol/verifier` package.
|
|
10
|
+
with two callbacks. The signer resolves limits, profile, and algorithm, copies
|
|
11
|
+
claims and context at entry, and takes one atomic `keyIdentity` snapshot.
|
|
12
|
+
The verifier's `prepareSigning` checks framing, claims, context, profile,
|
|
13
|
+
limits, and the holder's own descriptor key before the callback signs.
|
|
14
|
+
The signer checks the signature against the snapshot public key, then calls
|
|
15
|
+
`finishSigning` to assemble and verify under the retained context and settings.
|
|
19
16
|
|
|
20
17
|
## Install
|
|
21
18
|
|
|
@@ -23,13 +20,18 @@ verification of the assembled artifact through the
|
|
|
23
20
|
npm install @charter-agreement-protocol/signer
|
|
24
21
|
```
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
Version **0.3.0** requires Node >= 24.8.0 and
|
|
24
|
+
`@charter-agreement-protocol/verifier` ^0.7.0, for its pre-sign API.
|
|
27
25
|
|
|
28
26
|
## Quickstart
|
|
29
27
|
|
|
28
|
+
This runnable Ed25519 example keeps the private key in a Node `KeyObject`.
|
|
29
|
+
For an HSM, OS keychain, or remote key server, replace the handle's callbacks
|
|
30
|
+
with your custodian's key identity and signing operations.
|
|
31
|
+
|
|
30
32
|
```js
|
|
31
33
|
import { signDescriptor } from "@charter-agreement-protocol/signer";
|
|
32
|
-
import { generateKeyPairSync } from "node:crypto";
|
|
34
|
+
import { generateKeyPairSync, sign as nodeSign } from "node:crypto";
|
|
33
35
|
|
|
34
36
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
35
37
|
const publicKeyBase64url = publicKey.export({ type: "spki", format: "der" }).subarray(-32).toString("base64url");
|
|
@@ -41,7 +43,7 @@ const handle = {
|
|
|
41
43
|
},
|
|
42
44
|
// The holder's job: sign the exact message bytes with the held key.
|
|
43
45
|
sign(message) {
|
|
44
|
-
return
|
|
46
|
+
return nodeSign(null, message, privateKey); // Buffer is a Uint8Array
|
|
45
47
|
},
|
|
46
48
|
};
|
|
47
49
|
|
|
@@ -54,86 +56,188 @@ const result = await signDescriptor(
|
|
|
54
56
|
],
|
|
55
57
|
attestation_hints: [],
|
|
56
58
|
extensions: { critical: {}, optional: {} },
|
|
57
|
-
effective_from:
|
|
59
|
+
effective_from: new Date().toISOString(),
|
|
58
60
|
},
|
|
59
61
|
handle,
|
|
60
62
|
);
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
if (!result.ok) throw new Error(JSON.stringify(result));
|
|
65
|
+
console.log(result.result.descriptor); // Post-verified compact JWS
|
|
63
66
|
```
|
|
64
67
|
|
|
65
68
|
For ML-DSA-65 artifacts pass `{ algorithm: "ML-DSA-65" }` as the options
|
|
66
69
|
argument with `protocol_revision: 3` claims (pure ML-DSA per RFC 9964, the
|
|
67
70
|
empty context — your handle signs the exact message bytes as with Ed25519).
|
|
68
71
|
|
|
72
|
+
An absent, `undefined` or `null` algorithm selects Ed25519. Explicit
|
|
73
|
+
algorithms are `Ed25519` and `ML-DSA-65`; any other value returns
|
|
74
|
+
`invalid_input` with `code: "algorithm_unsupported"` before either key
|
|
75
|
+
callback runs.
|
|
76
|
+
|
|
69
77
|
## API
|
|
70
78
|
|
|
71
79
|
| Export | What it does |
|
|
72
80
|
|---|---|
|
|
73
|
-
| `signDescriptor(claims, handle, opts?)` | Signs
|
|
74
|
-
| `signReceipt(claims, handle,
|
|
75
|
-
| `signAcceptance(claims, handle,
|
|
76
|
-
| `signTermination(claims, handle,
|
|
77
|
-
|
|
78
|
-
The acceptance/termination `view` is `{ revisionText, descriptorCompacts,
|
|
79
|
-
chain }`: the revision the claims name, the signing party's descriptor
|
|
80
|
-
chain, and the caller's full `ChainView` (`{ revisions, acceptances,
|
|
81
|
-
descriptors, terminations }`) the refusal guards verify and bind against.
|
|
82
|
-
|
|
83
|
-
Errors are closed: `{ ok: false, error: "invalid_handle" \| "signing_failed"
|
|
84
|
-
\| "invalid_input" \| "refused" \| "verification_failed" }` — `code` rides
|
|
85
|
-
only on `invalid_input` and `refused`; `verification_failed` is bare
|
|
86
|
-
(reference parity).
|
|
87
|
-
`"refused"` is the honest-signer refusal: the claims contradict the caller's
|
|
88
|
-
own verified view, and the handle's `sign` callback is never reached (the
|
|
89
|
-
atomic `keyIdentity` snapshot resolves first — the reference ordering).
|
|
90
|
-
`"verification_failed"` is the separate post-sign discipline: the assembled
|
|
91
|
-
artifact did not verify against the caller's view (for example a key that is
|
|
92
|
-
not in the party descriptor's `verification_keys`). Malformed claims are
|
|
93
|
-
rejected pre-sign as `"invalid_input"` through the verifier package's
|
|
94
|
-
producer claims gate — they never burn a key operation. A signing failure is
|
|
95
|
-
never a silent pass.
|
|
81
|
+
| `signDescriptor(claims, handle, opts?)` | Signs a genesis or successor Party Descriptor; successors require `opts.predecessor` |
|
|
82
|
+
| `signReceipt(claims, handle, context, opts?)` | Signs a Receipt against a chain view or bare revision text |
|
|
83
|
+
| `signAcceptance(claims, handle, chain, opts?)` | Signs an Acceptance using the context the verifier derives from the chain |
|
|
84
|
+
| `signTermination(claims, handle, chain, opts?)` | Signs a Termination using the context the verifier derives from the chain |
|
|
85
|
+
| `SigningOptions`, `DescriptorOptions`, `ChainView`, `KeyHandle`, `KeySnapshot`, `SignError`, `SignResult` | Public TypeScript contracts |
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
A `ChainView` contains four string arrays: `{ revisions, acceptances,
|
|
88
|
+
descriptors, terminations }`. Pass all four, including explicit empty arrays.
|
|
89
|
+
Acceptance and termination use this chain directly. The verifier derives the
|
|
90
|
+
claimed revision and the holder's own descriptor history from its verified
|
|
91
|
+
contents. The signer copies claims at entry, before awaiting a key callback.
|
|
92
|
+
Claims copies contain fresh plain JSON objects and arrays, strings, finite
|
|
93
|
+
numbers, booleans, and null. Repeated objects are copied separately. Non-JSON
|
|
94
|
+
claims, cycles, and throwing reads return `invalid_input`/`invalid_type`.
|
|
95
|
+
Chain context and predecessor use their defined members with ordinary property
|
|
96
|
+
reads, and retained artifact lists get fresh arrays. Valid members are immutable
|
|
97
|
+
text; invalid member values stay opaque for the verifier.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
Claims copies use an iterative traversal guarded by the verifier's maximum
|
|
100
|
+
supported JSON bounds, rather than the caller's limits. Values beyond those
|
|
101
|
+
maximums return `invalid_input`/`signing_input_invalid`. Smaller claims reach
|
|
102
|
+
`prepareSigning`, which owns all checks under caller limits, including final
|
|
103
|
+
compact size. Context list copies retain enough entries to exceed every
|
|
104
|
+
supported artifact item limit, letting the verifier return its own result.
|
|
105
|
+
Predecessor lineage has no signer item limit. The verifier checks immutable
|
|
106
|
+
artifact text under artifact byte limits, separately from parsed claims' string
|
|
107
|
+
limits.
|
|
104
108
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
Migration from the previous issuing view:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
// Before
|
|
113
|
+
await signAcceptance(claims, handle, { revisionText, descriptorCompacts, chain }, opts);
|
|
114
|
+
// Now
|
|
115
|
+
await signAcceptance(claims, handle, chain, opts);
|
|
116
|
+
await signTermination(terminationClaims, handle, chain, opts);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For a successor descriptor, pass the verifier's `DescriptorPredecessor` facts
|
|
120
|
+
with retained signed `lineage`. The signing key must match an active key in
|
|
121
|
+
the predecessor:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { verifyDescriptor } from "@charter-agreement-protocol/verifier";
|
|
125
|
+
|
|
126
|
+
const previous = verifyDescriptor(genesisCompact);
|
|
127
|
+
if (!previous.ok) throw new Error(previous.code);
|
|
128
|
+
const next = await signDescriptor(successorClaims, handle, { predecessor: previous.facts });
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
For a receipt against bare revision text, the verifier checks the receipt's
|
|
132
|
+
claims against that revision. The revision names no signing key, so the signer
|
|
133
|
+
uses its snapshot for the custody guard; receipt verification reports
|
|
134
|
+
`signature` in `not_verified`. A chain-backed receipt checks the key against
|
|
135
|
+
the issuing party's descriptor keys in the holder's own view.
|
|
136
|
+
|
|
137
|
+
`opts` is absent or an object with known own keys only: `algorithm`, `limits`,
|
|
138
|
+
and `profile`, plus `predecessor` for `signDescriptor`. Another root shape, an
|
|
139
|
+
unknown own key, or a throwing getter returns `invalid_input` with
|
|
140
|
+
`code: "invalid_type"`. Defined members use ordinary property reads, once at
|
|
141
|
+
entry, including inherited and nonenumerable members. Class instances and
|
|
142
|
+
`Map` objects work where the verifier accepts their properties; Map entries
|
|
143
|
+
are not option properties.
|
|
144
|
+
|
|
145
|
+
`limits` is the verifier's `Partial<Limits>` and `profile` is its `Profile`.
|
|
146
|
+
The signer reads only their defined shape. Invalid values stay opaque for the
|
|
147
|
+
verifier's synchronous checks; they are not recursively copied by the signer.
|
|
148
|
+
Limits are checked before profile, algorithm, and the key snapshot. Malformed
|
|
149
|
+
values, including bigint, symbol, and boxed numbers, retain the verifier's
|
|
150
|
+
`invalid_limits` or `invalid_profile` result. Sparse algorithm lists return
|
|
151
|
+
`invalid_profile`; nonfinite or explicitly undefined limit values return
|
|
152
|
+
`invalid_limits`. A list longer than the algorithm registry cannot be a valid
|
|
153
|
+
unique subset, so its invalid length reaches the verifier without reading its
|
|
154
|
+
entries. The verifier's copy failures are also returned unchanged.
|
|
155
|
+
Limits bound the final compact, including signature bytes, and
|
|
156
|
+
every context artifact read; raised limits also apply to assembly and the
|
|
157
|
+
custody guard. Profiles can restrict `algorithms` and/or
|
|
158
|
+
`revisions: { min, max }`; an omitted axis keeps the full supported range.
|
|
159
|
+
An EdDSA-only profile, an ML-DSA-44/87-only profile, or revisions 1..1 excludes
|
|
160
|
+
every artifact this signer emits. Exclusions return `algorithm_outside_profile`
|
|
161
|
+
or `revision_outside_profile`.
|
|
162
|
+
|
|
163
|
+
<a id="profile-scope"></a>
|
|
164
|
+
|
|
165
|
+
For acceptance and termination, the caller's profile covers the claimed
|
|
166
|
+
revision, the signing party's own descriptor history, and the new artifact.
|
|
167
|
+
The rest of the set is checked under the full default profile. For receipts,
|
|
168
|
+
the profile covers the new artifact and the whole retained set. For descriptors,
|
|
169
|
+
it covers the new artifact and predecessor history.
|
|
170
|
+
|
|
171
|
+
Errors are closed:
|
|
172
|
+
|
|
173
|
+
| Result error | Meaning |
|
|
174
|
+
|---|---|
|
|
175
|
+
| `invalid_input`, with `code` | The verifier rejected claims, context, limits, or profile, or options were invalid |
|
|
176
|
+
| `invalid_key_handle` | The snapshot callback failed, its shape was malformed, or the verifier returned `signing_key_invalid` |
|
|
177
|
+
| `refused`, with `code: "signing_refused"` | The claims contradict the holder's own verified view (R1–R3) |
|
|
178
|
+
| `refused`, with `code: "signing_key_mismatch"` | The kid, public key bytes, or key algorithm does not match the holder's own descriptor key |
|
|
179
|
+
| `algorithm_unsupported_on_substrate` | The runtime cannot verify the selected algorithm or a context artifact |
|
|
180
|
+
| `signing_failed` | The callback failed, returned a malformed signature, or failed the wrong-key guard |
|
|
181
|
+
| `verification_failed` | `finishSigning` rejected what preparation approved |
|
|
111
182
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
183
|
+
Every failure has `ok: false`. Only `invalid_input` and `refused` carry `code`.
|
|
184
|
+
The signing callback can return a Buffer or any `Uint8Array`, including one
|
|
185
|
+
from another JavaScript realm. The verifier rejects Ed25519 public keys with
|
|
186
|
+
noncanonical y coordinates, no curve point, x = 0 with the sign bit set, or
|
|
187
|
+
small order as `invalid_key_handle` when they are snapshot keys. Descriptor
|
|
188
|
+
claims containing such keys can fail earlier with `signing_input_invalid`.
|
|
189
|
+
All pre-sign rejections leave the `sign` callback untouched; the atomic key
|
|
190
|
+
snapshot precedes `prepareSigning`. A malformed context type returns
|
|
191
|
+
`invalid_input`/`invalid_type`. For otherwise valid descriptor claims, predecessor
|
|
192
|
+
errors return `invalid_input` with these codes before signing:
|
|
193
|
+
|
|
194
|
+
- `invalid_type`: a non-object predecessor, a missing digest alias (both `digest`
|
|
195
|
+
and `descriptor_digest` absent), or missing, null, empty, or non-string `lineage`.
|
|
196
|
+
Throwing reads also return this code.
|
|
197
|
+
- `descriptor_chain_invalid`: an absent or null predecessor for a successor,
|
|
198
|
+
a valid predecessor supplied to a genesis, a broken signed lineage, or digest
|
|
199
|
+
aliases that disagree with the reverified lineage.
|
|
200
|
+
- `algorithm_outside_profile`, `revision_outside_profile`, or
|
|
201
|
+
`algorithm_unsupported_on_substrate`: predecessor history excluded by the
|
|
202
|
+
profile or requiring unavailable crypto.
|
|
203
|
+
|
|
204
|
+
## The sibling verifier
|
|
205
|
+
|
|
206
|
+
The signer and verifier are separate TypeScript packages implementing the
|
|
207
|
+
Charter Agreement Protocol, with no Elixir dependency at runtime. The
|
|
208
|
+
verifier ships a corpus certified against the Elixir protocol reference.
|
|
209
|
+
This signer tests its artifacts through the TypeScript verifier.
|
|
210
|
+
All protocol checks run in `prepareSigning` and `finishSigning`; the signer
|
|
211
|
+
keeps key custody callbacks, the signature guard, entry copies, option
|
|
212
|
+
resolution, and the closed error vocabulary.
|
|
115
213
|
|
|
116
214
|
## Evidence
|
|
117
215
|
|
|
118
|
-
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
216
|
+
- Linux CI runs the suite on Node 24.8.0 and the current Node 24 line.
|
|
217
|
+
Real Node crypto mints Ed25519 and ML-DSA-65 genesis and successor descriptors.
|
|
218
|
+
Pre-sign rejection tests count real signing calls and require zero calls.
|
|
219
|
+
Tests cover key mismatches, predecessor checks, malformed contexts, profiles,
|
|
220
|
+
final compact limits, receipt claims, entry copies, and unknown algorithms.
|
|
221
|
+
- The workshop's browser bundle mints Ed25519 and runs the complete workshop
|
|
222
|
+
flow. It cannot verify ML-DSA-65 and refuses that request before signing with
|
|
223
|
+
the top-level `algorithm_unsupported_on_substrate` error.
|
|
224
|
+
- The [shared table](test/fixtures/README.md) runs all 121 rows from the Elixir
|
|
225
|
+
signer, `charter_agreement_signer` 0.5.0, with its exact source bytes pinned by SHA-256. Real seed
|
|
226
|
+
keys check result shapes and codes, snapshot and custody counts, 12 exact
|
|
227
|
+
Ed25519 success compacts, and five ML-DSA-65 successes through verification.
|
|
228
|
+
All 121 rows run in both Node and the browser bundle with no skips. Eight
|
|
229
|
+
shared requests or contexts that need ML-DSA-65 also return a substrate error
|
|
230
|
+
before custody in the browser bundle.
|
|
231
|
+
This compares the recorded Elixir outcomes; it does not run Elixir locally.
|
|
232
|
+
|
|
233
|
+
## Verifier compatibility and telemetry
|
|
234
|
+
|
|
235
|
+
The verifier requires canonical digests and revision JSON, distinct party
|
|
236
|
+
histories, and all four chain arrays. Build failures surface as `invalid_input`
|
|
237
|
+
with `code: "signing_input_invalid"`; termination claims must omit `extensions`.
|
|
238
|
+
See [CHANGELOG.md](CHANGELOG.md) for migration notes.
|
|
239
|
+
|
|
240
|
+
This package has no telemetry events or hooks and no signer capability report.
|
|
137
241
|
|
|
138
242
|
## SemVer
|
|
139
243
|
|
|
@@ -145,6 +249,42 @@ requires `chain`, `signAcceptance` now enforces the refusal guards over the
|
|
|
145
249
|
at or above 1.0 a package major is owed when a shipped public API is removed
|
|
146
250
|
or changes behavior.
|
|
147
251
|
|
|
252
|
+
## Development
|
|
253
|
+
|
|
254
|
+
Use Node 24 (at least 24.8.0) and npm. The lockfile selects TypeScript 7.0.2
|
|
255
|
+
and `@types/node` 26.6.4. CI runs on Linux with Node 24.8.0 and Node 24
|
|
256
|
+
using a frozen install; the same npm commands are used for local development on macOS and Linux.
|
|
257
|
+
|
|
258
|
+
```console
|
|
259
|
+
npm ci
|
|
260
|
+
npm run typecheck
|
|
261
|
+
npm test
|
|
262
|
+
npm run test:cases
|
|
263
|
+
npm run build
|
|
264
|
+
npm run typecheck:web
|
|
265
|
+
npm run build:site
|
|
266
|
+
npm pack --dry-run
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
`build` emits JavaScript and declarations into `dist/`; `build:site` writes
|
|
270
|
+
the browser workshop to `site-dist/`. `prepack` runs the library build.
|
|
271
|
+
For the TypeScript 7 upgrade, the four library output files were byte-identical
|
|
272
|
+
to the TypeScript 5.9.3 build (observed October 6, 2026 with `diff -ru`).
|
|
273
|
+
|
|
274
|
+
## Release staging
|
|
275
|
+
|
|
276
|
+
The [Release workflow](https://github.com/baselabs/charter_agreement_signer_typescript/blob/main/.github/workflows/release.yml) is the npm trusted
|
|
277
|
+
publisher for this repository. Prepare a release by updating `package.json`,
|
|
278
|
+
`package-lock.json`, this README's release version, the CHANGELOG, and the
|
|
279
|
+
workshop's version badge. Run the development checks above, commit and push
|
|
280
|
+
main, and wait for CI to pass. Then tag that same commit `v<package-version>`
|
|
281
|
+
and push that specific tag.
|
|
282
|
+
|
|
283
|
+
The tag triggers verification and `npm stage publish --provenance` through
|
|
284
|
+
GitHub Actions OIDC. A successful staging step prints the package version and
|
|
285
|
+
stage ID. The package becomes public only after the owner approves the staged
|
|
286
|
+
release on npmjs.com with 2FA. Keep npm staging in this workflow.
|
|
287
|
+
|
|
148
288
|
## License
|
|
149
289
|
|
|
150
290
|
Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
The latest published `0.x` line is supported. Wire compatibility follows
|
|
6
|
+
the public `@charter-agreement-protocol/verifier` package's contract.
|
|
7
|
+
|
|
8
|
+
## Security invariants
|
|
9
|
+
|
|
10
|
+
- The library never solicits, processes or retains private key material.
|
|
11
|
+
Custody lives behind the caller's key-handle callbacks.
|
|
12
|
+
- Every signature is verified against the snapshot public key before
|
|
13
|
+
success. A signature from another key returns `signing_failed`.
|
|
14
|
+
- Key identity (`kid` and public key) comes from one atomic `keyIdentity`
|
|
15
|
+
snapshot per signing call. The signer supplies that snapshot's kid to
|
|
16
|
+
the producer.
|
|
17
|
+
- Errors contain closed names and codes, with no key material, message
|
|
18
|
+
bytes, claims content or callback exception text.
|
|
19
|
+
- The library's only runtime dependency is the public verifier package.
|
|
20
|
+
It contains no transport or HTTP client/server.
|
|
21
|
+
- Test handles stay in test files and do not ship in the npm package.
|
|
22
|
+
|
|
23
|
+
## Reporting a vulnerability
|
|
24
|
+
|
|
25
|
+
Report it privately through GitHub's private vulnerability reporting for
|
|
26
|
+
`baselabs/charter_agreement_signer_typescript` (the repository's Security
|
|
27
|
+
tab, then "Report a vulnerability"). Do not open a public issue containing
|
|
28
|
+
an exploit, credential, private key or unreleased vulnerability detail.
|
|
29
|
+
|
|
30
|
+
A report should include:
|
|
31
|
+
|
|
32
|
+
- the affected version or commit;
|
|
33
|
+
- the violated property;
|
|
34
|
+
- a minimal reproduction with newly generated test keys and no production
|
|
35
|
+
claims or credentials;
|
|
36
|
+
- the expected security outcome.
|
|
37
|
+
|
|
38
|
+
## Verifying a release
|
|
39
|
+
|
|
40
|
+
The [Release workflow](https://github.com/baselabs/charter_agreement_signer_typescript/blob/main/.github/workflows/release.yml)
|
|
41
|
+
checks the package before staging it on npm with provenance through
|
|
42
|
+
GitHub Actions OIDC. The owner approves the staged release on npm with 2FA.
|
|
43
|
+
Inspect the published package's source repository, archive integrity and
|
|
44
|
+
provenance metadata with:
|
|
45
|
+
|
|
46
|
+
```console
|
|
47
|
+
npm view @charter-agreement-protocol/signer repository.url dist.integrity dist.attestations
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Acknowledgment
|
|
51
|
+
|
|
52
|
+
We will acknowledge reports within 7 days and send status updates at least
|
|
53
|
+
weekly until resolution, coordinating disclosure through a private advisory.
|
|
54
|
+
This is a best-effort cadence from a small maintainer team, not a contractual
|
|
55
|
+
SLA. Mark urgent reports clearly.
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { signDescriptor, signReceipt, signAcceptance, signTermination, type KeyHandle, type KeySnapshot, type ChainView, type SignError, type SignResult, } from "./signer.ts";
|
|
1
|
+
export { signDescriptor, signReceipt, signAcceptance, signTermination, type KeyHandle, type KeySnapshot, type ChainView, type SigningOptions, type DescriptorOptions, type SignError, type SignResult, } from "./signer.ts";
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Public surface of the holder-side companion signer: one signing function
|
|
4
4
|
// per artifact kind, the key-handle contract, and the closed error
|
|
5
|
-
// vocabulary.
|
|
6
|
-
//
|
|
7
|
-
// artifact — goes through @charter-agreement-protocol/verifier: exactly
|
|
8
|
-
// one implementation. This package holds the custody half only.
|
|
5
|
+
// vocabulary. Protocol checks run through prepareSigning and finishSigning
|
|
6
|
+
// in @charter-agreement-protocol/verifier. This package keeps custody.
|
|
9
7
|
export { signDescriptor, signReceipt, signAcceptance, signTermination, } from "./signer.js";
|
package/dist/signer.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DescriptorPredecessor, type Limits, type Profile } from "@charter-agreement-protocol/verifier";
|
|
1
2
|
export type KeySnapshot = {
|
|
2
3
|
kid: string;
|
|
3
4
|
publicKey: string;
|
|
@@ -7,7 +8,7 @@ export type KeyHandle = {
|
|
|
7
8
|
sign(message: Uint8Array, handle: unknown): Uint8Array | Promise<Uint8Array>;
|
|
8
9
|
};
|
|
9
10
|
export type SignError = {
|
|
10
|
-
error: "
|
|
11
|
+
error: "invalid_key_handle";
|
|
11
12
|
} | {
|
|
12
13
|
error: "signing_failed";
|
|
13
14
|
} | {
|
|
@@ -15,7 +16,9 @@ export type SignError = {
|
|
|
15
16
|
code: string;
|
|
16
17
|
} | {
|
|
17
18
|
error: "refused";
|
|
18
|
-
code:
|
|
19
|
+
code: "signing_refused" | "signing_key_mismatch";
|
|
20
|
+
} | {
|
|
21
|
+
error: "algorithm_unsupported_on_substrate";
|
|
19
22
|
} | {
|
|
20
23
|
error: "verification_failed";
|
|
21
24
|
};
|
|
@@ -32,31 +35,23 @@ export type ChainView = {
|
|
|
32
35
|
descriptors: string[];
|
|
33
36
|
terminations: string[];
|
|
34
37
|
};
|
|
35
|
-
export
|
|
36
|
-
algorithm?: string;
|
|
37
|
-
|
|
38
|
+
export type SigningOptions = {
|
|
39
|
+
algorithm?: string | null;
|
|
40
|
+
limits?: Partial<Limits>;
|
|
41
|
+
profile?: Profile;
|
|
42
|
+
};
|
|
43
|
+
export type DescriptorOptions = SigningOptions & {
|
|
44
|
+
predecessor?: DescriptorPredecessor | null;
|
|
45
|
+
};
|
|
46
|
+
export declare function signDescriptor(claims: Record<string, unknown>, keyHandle: unknown, opts?: DescriptorOptions): Promise<SignResult<{
|
|
38
47
|
descriptor: string;
|
|
39
48
|
}>>;
|
|
40
|
-
export declare function signReceipt(claims: Record<string, unknown>, keyHandle: unknown,
|
|
41
|
-
algorithm?: string;
|
|
42
|
-
}): Promise<SignResult<{
|
|
49
|
+
export declare function signReceipt(claims: Record<string, unknown>, keyHandle: unknown, context: ChainView | string, opts?: SigningOptions): Promise<SignResult<{
|
|
43
50
|
receipt: string;
|
|
44
51
|
}>>;
|
|
45
|
-
export declare function signAcceptance(claims: Record<string, unknown>, keyHandle: unknown,
|
|
46
|
-
revisionText: string;
|
|
47
|
-
descriptorCompacts: string[];
|
|
48
|
-
chain: ChainView;
|
|
49
|
-
}, opts?: {
|
|
50
|
-
algorithm?: string;
|
|
51
|
-
}): Promise<SignResult<{
|
|
52
|
+
export declare function signAcceptance(claims: Record<string, unknown>, keyHandle: unknown, chain: ChainView, opts?: SigningOptions): Promise<SignResult<{
|
|
52
53
|
acceptance: string;
|
|
53
54
|
}>>;
|
|
54
|
-
export declare function signTermination(claims: Record<string, unknown>, keyHandle: unknown,
|
|
55
|
-
revisionText: string;
|
|
56
|
-
descriptorCompacts: string[];
|
|
57
|
-
chain: ChainView;
|
|
58
|
-
}, opts?: {
|
|
59
|
-
algorithm?: string;
|
|
60
|
-
}): Promise<SignResult<{
|
|
55
|
+
export declare function signTermination(claims: Record<string, unknown>, keyHandle: unknown, chain: ChainView, opts?: SigningOptions): Promise<SignResult<{
|
|
61
56
|
termination: string;
|
|
62
57
|
}>>;
|