@metalabel/dfos-protocol 0.44.0 → 0.46.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/dist/chain/index.d.ts +14 -4
- package/dist/chain/index.js +8 -1
- package/dist/chunk-JVSC67DC.js +981 -0
- package/dist/{chunk-4YBXPYEU.js → chunk-ZRA7FRBE.js} +248 -28
- package/dist/credentials/index.d.ts +1 -1
- package/dist/{dfos-credential-X6uvPIth.d.ts → dfos-credential-BtiYPqBT.d.ts} +118 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +24 -2
- package/dist/key-proof/index.d.ts +203 -20
- package/dist/key-proof/index.js +17 -1
- package/examples/identity-restore.json +3 -3
- package/examples/identity-rotation.json +1 -1
- package/package.json +3 -2
- package/dist/chunk-VEJBAY3T.js +0 -200
package/dist/index.js
CHANGED
|
@@ -6,10 +6,12 @@ import {
|
|
|
6
6
|
CountersignPayload,
|
|
7
7
|
CreditClaimPayload,
|
|
8
8
|
CreditClaimVerifyError,
|
|
9
|
+
DeclaredKeyState,
|
|
9
10
|
IdentityOperation,
|
|
10
11
|
Iso8601,
|
|
11
12
|
MAX_ARTIFACT_PAYLOAD_SIZE,
|
|
12
13
|
MAX_CREDIT_CLAIM_SIZE,
|
|
14
|
+
MAX_KEY_PROOFS,
|
|
13
15
|
MAX_OPERATION_SIZE,
|
|
14
16
|
MAX_SERVICES_ENTRIES,
|
|
15
17
|
MAX_SERVICES_PAYLOAD_SIZE,
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
SignRequestPayload,
|
|
24
26
|
SignRequestVerifyError,
|
|
25
27
|
VerifiedIdentity,
|
|
28
|
+
VoidKeyMembership,
|
|
26
29
|
anchorsByLabel,
|
|
27
30
|
assertCanonicalSignRequestPayload,
|
|
28
31
|
assertServicesWithinCap,
|
|
@@ -49,7 +52,7 @@ import {
|
|
|
49
52
|
verifyIdentityExtensionFromTrustedState,
|
|
50
53
|
verifyRevocation,
|
|
51
54
|
verifySignRequest
|
|
52
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-ZRA7FRBE.js";
|
|
53
56
|
import {
|
|
54
57
|
ApiRequestVerifyError,
|
|
55
58
|
Attenuation,
|
|
@@ -90,12 +93,20 @@ import {
|
|
|
90
93
|
import {
|
|
91
94
|
DEFAULT_KEY_PROOF_SKEW_SECONDS,
|
|
92
95
|
KEY_ADD_JWS_TYP,
|
|
96
|
+
KEY_ROLES,
|
|
93
97
|
KeyProofVerifyError,
|
|
94
98
|
MAX_KEY_PROOF_SIZE,
|
|
99
|
+
isCanonicalRoleSet,
|
|
95
100
|
keyProofSigningInput,
|
|
101
|
+
keyWordFingerprint,
|
|
102
|
+
parseRoleSet,
|
|
103
|
+
roleSetCovers,
|
|
104
|
+
serializeRoleSet,
|
|
96
105
|
signKeyProof,
|
|
106
|
+
unsafeKeyProofSubject,
|
|
107
|
+
verifyChainKeyProof,
|
|
97
108
|
verifyKeyProof
|
|
98
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-JVSC67DC.js";
|
|
99
110
|
import {
|
|
100
111
|
ED25519_PRIV_MULTICODEC,
|
|
101
112
|
ED25519_PUB_MULTICODEC,
|
|
@@ -152,6 +163,7 @@ export {
|
|
|
152
163
|
DEFAULT_PROOF_WINDOW_SECONDS,
|
|
153
164
|
DFOSCredentialPayload,
|
|
154
165
|
DFOS_AUTH_SCHEME,
|
|
166
|
+
DeclaredKeyState,
|
|
155
167
|
ED25519_PRIV_MULTICODEC,
|
|
156
168
|
ED25519_PUB_MULTICODEC,
|
|
157
169
|
EMPTY_BODY_SHA256,
|
|
@@ -162,11 +174,13 @@ export {
|
|
|
162
174
|
JwsVerificationError,
|
|
163
175
|
JwtVerificationError,
|
|
164
176
|
KEY_ADD_JWS_TYP,
|
|
177
|
+
KEY_ROLES,
|
|
165
178
|
KeyProofVerifyError,
|
|
166
179
|
MAX_ARTIFACT_PAYLOAD_SIZE,
|
|
167
180
|
MAX_BODY_BYTES,
|
|
168
181
|
MAX_CREDENTIAL_SIZE,
|
|
169
182
|
MAX_CREDIT_CLAIM_SIZE,
|
|
183
|
+
MAX_KEY_PROOFS,
|
|
170
184
|
MAX_KEY_PROOF_SIZE,
|
|
171
185
|
MAX_OPERATION_SIZE,
|
|
172
186
|
MAX_PROOF_FRESHNESS_SPAN_SECONDS,
|
|
@@ -184,6 +198,7 @@ export {
|
|
|
184
198
|
SignRequestPayload,
|
|
185
199
|
SignRequestVerifyError,
|
|
186
200
|
VerifiedIdentity,
|
|
201
|
+
VoidKeyMembership,
|
|
187
202
|
anchorsByLabel,
|
|
188
203
|
apiIdentitySigningInput,
|
|
189
204
|
apiRequestSigningInput,
|
|
@@ -220,11 +235,13 @@ export {
|
|
|
220
235
|
importEd25519Keypair,
|
|
221
236
|
invalidProof,
|
|
222
237
|
isAttenuated,
|
|
238
|
+
isCanonicalRoleSet,
|
|
223
239
|
isCanonicallyEqual,
|
|
224
240
|
isRecognizedServiceType,
|
|
225
241
|
isValidEd25519Signature,
|
|
226
242
|
isValidId,
|
|
227
243
|
keyProofSigningInput,
|
|
244
|
+
keyWordFingerprint,
|
|
228
245
|
linearize,
|
|
229
246
|
matchesResource,
|
|
230
247
|
misconfiguredProof,
|
|
@@ -232,7 +249,10 @@ export {
|
|
|
232
249
|
parseDagCborCID,
|
|
233
250
|
parseDfosAuthorization,
|
|
234
251
|
parseProtocolTimestampUnix,
|
|
252
|
+
parseRoleSet,
|
|
235
253
|
relayEndpoints,
|
|
254
|
+
roleSetCovers,
|
|
255
|
+
serializeRoleSet,
|
|
236
256
|
sha256,
|
|
237
257
|
sha256BodyHash,
|
|
238
258
|
signApiIdentityRequest,
|
|
@@ -245,8 +265,10 @@ export {
|
|
|
245
265
|
signKeyProof,
|
|
246
266
|
signPayloadEd25519,
|
|
247
267
|
signRevocation,
|
|
268
|
+
unsafeKeyProofSubject,
|
|
248
269
|
unverifiableProof,
|
|
249
270
|
verifyArtifact,
|
|
271
|
+
verifyChainKeyProof,
|
|
250
272
|
verifyContentChain,
|
|
251
273
|
verifyContentExtensionFromTrustedState,
|
|
252
274
|
verifyCountersignature,
|
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLOSED role set. Membership in an identity operation's `authKeys`,
|
|
3
|
+
* `assertKeys`, and `controllerKeys` arrays respectively — the three positions a
|
|
4
|
+
* key can hold in a chain, and the only three a proof can consent to.
|
|
5
|
+
*
|
|
6
|
+
* THIS ORDER IS THE CANONICAL SERIALIZATION ORDER. It is not sorted; it is the
|
|
7
|
+
* order the roles appear in an identity operation.
|
|
8
|
+
*/
|
|
9
|
+
declare const KEY_ROLES: readonly ["auth", "assert", "controller"];
|
|
10
|
+
/** One role a key can hold in an identity chain. */
|
|
11
|
+
type KeyRole = (typeof KEY_ROLES)[number];
|
|
12
|
+
/**
|
|
13
|
+
* Serialize a set of roles to its ONE canonical spelling. Duplicates in the input
|
|
14
|
+
* collapse (a set is a set); an unknown role or an empty result throws, because
|
|
15
|
+
* neither can be signed.
|
|
16
|
+
*
|
|
17
|
+
* This is the producer half. `parseRoleSet` is the verifier half, and the two are
|
|
18
|
+
* inverses on exactly the canonical strings: `parseRoleSet(serializeRoleSet(r))`
|
|
19
|
+
* round-trips, and `serializeRoleSet(parseRoleSet(s)) === s` for every `s` the
|
|
20
|
+
* parse admits.
|
|
21
|
+
*/
|
|
22
|
+
declare const serializeRoleSet: (roles: Iterable<KeyRole>) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Parse a role set from its canonical spelling, or `null` when the bytes are not
|
|
25
|
+
* that spelling. Returns `null` rather than throwing so the caller raises the
|
|
26
|
+
* failure in ITS OWN vocabulary — a `schema` rejection inside key-proof
|
|
27
|
+
* verification, a chain error inside the identity walk.
|
|
28
|
+
*
|
|
29
|
+
* THE PARSE IS THE CANONICALITY CHECK. It is strict in every direction at once:
|
|
30
|
+
* an unknown role, a duplicate, a member out of the fixed order, any whitespace
|
|
31
|
+
* (` auth` is not `auth`), an empty segment, and the empty string all return
|
|
32
|
+
* `null`. There is no lenient mode and no normalization — a producer that meant
|
|
33
|
+
* `auth,assert` must spell it `auth,assert`.
|
|
34
|
+
*/
|
|
35
|
+
declare const parseRoleSet: (value: string) => KeyRole[] | null;
|
|
36
|
+
/** True when `value` is exactly the canonical spelling of the set it names. */
|
|
37
|
+
declare const isCanonicalRoleSet: (value: string) => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Does this role set cover `role`? The question the CHAIN WALK asks: an
|
|
40
|
+
* introduction of key K to role R is proved only by an envelope whose role set
|
|
41
|
+
* includes R. A non-canonical role set covers nothing — it never parsed.
|
|
42
|
+
*/
|
|
43
|
+
declare const roleSetCovers: (value: string, role: KeyRole) => boolean;
|
|
44
|
+
|
|
1
45
|
/**
|
|
2
46
|
* The first registered purpose in KEY-PROOF.md's purpose registry: the candidate
|
|
3
47
|
* key presents for addition to a ceremony-named identity's `authKeys`/
|
|
@@ -17,22 +61,38 @@ declare const MAX_KEY_PROOF_SIZE = 4096;
|
|
|
17
61
|
*/
|
|
18
62
|
declare const DEFAULT_KEY_PROOF_SKEW_SECONDS = 300;
|
|
19
63
|
/**
|
|
20
|
-
* The closed payload. Exactly these
|
|
64
|
+
* The closed payload. Exactly these seven members, each a string, in exactly this
|
|
21
65
|
* order — the member set is EXHAUSTIVE and no amendment may introduce a member
|
|
22
66
|
* that carries intent or content.
|
|
23
67
|
*/
|
|
24
68
|
interface KeyProofPayload {
|
|
25
69
|
/** The verifier-minted, single-use challenge, exactly as the carriage delivered it. */
|
|
26
70
|
nonce: string;
|
|
27
|
-
/**
|
|
71
|
+
/**
|
|
72
|
+
* The completing authority's lowercase authority — `host`, or `host:port` off
|
|
73
|
+
* 443. Held here as an opaque string: a leg whose completing authority IS a
|
|
74
|
+
* chain rather than a host audiences to that chain's DID, byte-equal to `did`,
|
|
75
|
+
* and this module does not special-case the two spellings. The VERIFIER
|
|
76
|
+
* supplies the expectation; the envelope only carries what it was signed for.
|
|
77
|
+
*/
|
|
28
78
|
audience: string;
|
|
79
|
+
/** The chain this key is introduced to. */
|
|
80
|
+
did: string;
|
|
81
|
+
/** The canonical role set (see role-set.ts) this envelope consents to. */
|
|
82
|
+
roleSet: string;
|
|
83
|
+
/**
|
|
84
|
+
* The chain head the introduction builds on — equal to the introducing
|
|
85
|
+
* operation's `previousOperationCID`. The member that forecloses standing
|
|
86
|
+
* consent.
|
|
87
|
+
*/
|
|
88
|
+
prevCID: string;
|
|
29
89
|
/** The candidate key's Multikey — and the key that signs this envelope. */
|
|
30
90
|
publicKeyMultibase: string;
|
|
31
91
|
/** ISO 8601 creation time, floor-normalized to whole seconds (`.000Z`). */
|
|
32
92
|
timestamp: string;
|
|
33
93
|
}
|
|
34
94
|
/** The verification step a failure arose in. Branch on this, never on message text. */
|
|
35
|
-
type KeyProofFailureReason = 'size' | 'header' | 'schema' | 'audience' | 'freshness' | 'signature';
|
|
95
|
+
type KeyProofFailureReason = 'size' | 'header' | 'schema' | 'audience' | 'did' | 'roleSet' | 'prevCID' | 'key' | 'freshness' | 'signature';
|
|
36
96
|
/** Thrown by `verifyKeyProof`. Branch on `reason`, never on message text. */
|
|
37
97
|
declare class KeyProofVerifyError extends Error {
|
|
38
98
|
readonly reason: KeyProofFailureReason;
|
|
@@ -41,7 +101,8 @@ declare class KeyProofVerifyError extends Error {
|
|
|
41
101
|
/**
|
|
42
102
|
* THE BYTE CONTRACT. Serializes a payload to the canonical bytes that ARE the
|
|
43
103
|
* JWS payload segment: minimal UTF-8 JSON, no insignificant whitespace, members
|
|
44
|
-
* in exactly the order `nonce, audience,
|
|
104
|
+
* in exactly the order `nonce, audience, did, roleSet, prevCID,
|
|
105
|
+
* publicKeyMultibase, timestamp`.
|
|
45
106
|
*
|
|
46
107
|
* PURE and clientless: import it in a holder's signing tool and in a ceremony
|
|
47
108
|
* operator's verifier alike. Byte-for-byte identical to Go's
|
|
@@ -53,8 +114,17 @@ interface SignKeyProofInput {
|
|
|
53
114
|
typ: string;
|
|
54
115
|
/** The verifier-minted nonce, exactly as the carriage delivered it. */
|
|
55
116
|
nonce: string;
|
|
56
|
-
/** The
|
|
117
|
+
/** The completing authority — the one the human confirmed. */
|
|
57
118
|
audience: string;
|
|
119
|
+
/** The chain this key is being introduced to. */
|
|
120
|
+
did: string;
|
|
121
|
+
/**
|
|
122
|
+
* The canonical role set — build it with `serializeRoleSet` rather than by
|
|
123
|
+
* hand; a non-canonical spelling is refused here, not silently normalized.
|
|
124
|
+
*/
|
|
125
|
+
roleSet: string;
|
|
126
|
+
/** The chain head the introduction builds on. */
|
|
127
|
+
prevCID: string;
|
|
58
128
|
/**
|
|
59
129
|
* The candidate key's raw 32-byte Ed25519 private key. `publicKeyMultibase` is
|
|
60
130
|
* DERIVED from it rather than accepted as an input: this envelope is
|
|
@@ -77,12 +147,20 @@ interface SignKeyProofInput {
|
|
|
77
147
|
* carry.
|
|
78
148
|
*
|
|
79
149
|
* HOLDER OBLIGATIONS THIS FUNCTION CANNOT DISCHARGE (KEY-PROOF.md, Holder
|
|
80
|
-
* Obligations). A holder MUST show its human
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
150
|
+
* Obligations). A holder MUST show its human — before calling this — the
|
|
151
|
+
* audience, the purpose, the adopting identity, and the roles. A proof is
|
|
152
|
+
* consent, and consent that was never displayed was never given.
|
|
153
|
+
*
|
|
154
|
+
* It SHOULD also refuse to sign for a key some identity's chain has already
|
|
155
|
+
* PROVED, its own included: the `key=` reverse index is has-ever-proved across
|
|
156
|
+
* all three key sets, its rows survive rotation and deletion, and proving one
|
|
157
|
+
* key into two chains publishes an irreversible public link between them. An
|
|
158
|
+
* unproved DECLARATION of the key elsewhere is neither a link nor a burn — it is
|
|
159
|
+
* void, it never indexes, and it never obligates the true holder, which is
|
|
160
|
+
* precisely why the index counts proofs and not claims.
|
|
161
|
+
*
|
|
162
|
+
* Every one of those is a decision about a human and a network, made before
|
|
163
|
+
* there is a signature to make; none belongs to a pure signer.
|
|
86
164
|
*/
|
|
87
165
|
declare const signKeyProof: (input: SignKeyProofInput) => Promise<{
|
|
88
166
|
proof: string;
|
|
@@ -102,6 +180,28 @@ interface VerifyKeyProofOptions {
|
|
|
102
180
|
* defense against challenge relay.
|
|
103
181
|
*/
|
|
104
182
|
expectedAudience: string;
|
|
183
|
+
/**
|
|
184
|
+
* THE CHAIN THIS CEREMONY IS COMPLETING FOR. Like the audience, it is the
|
|
185
|
+
* completing authority's own value — the identity whose ceremony this is — and
|
|
186
|
+
* never a DID read back out of the envelope being checked.
|
|
187
|
+
*/
|
|
188
|
+
expectedDid: string;
|
|
189
|
+
/**
|
|
190
|
+
* THE ROLES THIS CEREMONY GRANTS, in canonical spelling (`serializeRoleSet`).
|
|
191
|
+
* Byte-equality, not coverage: a ceremony that will write `auth,assert` MUST
|
|
192
|
+
* NOT accept an envelope consenting to `auth` alone, and MUST NOT accept one
|
|
193
|
+
* consenting to `auth,assert,controller` either — the second is the holder
|
|
194
|
+
* conceding more than was asked, which a completing authority has no business
|
|
195
|
+
* banking. A non-canonical expectation is a MISCONFIGURATION and throws.
|
|
196
|
+
*/
|
|
197
|
+
expectedRoleSet: string;
|
|
198
|
+
/**
|
|
199
|
+
* THE HEAD THE INTRODUCTION WILL BUILD ON — the `previousOperationCID` the
|
|
200
|
+
* completing authority is about to write. A chain that moved between minting
|
|
201
|
+
* the challenge and completing it invalidates the proof here rather than
|
|
202
|
+
* writing an operation whose embedded envelope no walker will accept.
|
|
203
|
+
*/
|
|
204
|
+
expectedPrevCID: string;
|
|
105
205
|
/** Acceptance window, seconds, EITHER SIDE. Default `DEFAULT_KEY_PROOF_SKEW_SECONDS`. */
|
|
106
206
|
maxSkewSeconds?: number;
|
|
107
207
|
/** Clock injection (unix ms). Default `Date.now()`. */
|
|
@@ -122,10 +222,15 @@ interface VerifiedKeyProof {
|
|
|
122
222
|
now: number;
|
|
123
223
|
}
|
|
124
224
|
/**
|
|
125
|
-
* Verify a key proof — KEY-PROOF.md's verification algorithm
|
|
126
|
-
* size cap, header gates, the closed payload schema over
|
|
127
|
-
*
|
|
128
|
-
* `publicKeyMultibase`.
|
|
225
|
+
* Verify a key proof AT PRESENTATION TIME — KEY-PROOF.md's verification algorithm
|
|
226
|
+
* steps 1–5 and 7: size cap, header gates, the closed payload schema over
|
|
227
|
+
* CANONICAL bytes, the four expectation arms (audience, did, roleSet, prevCID),
|
|
228
|
+
* freshness, and the signature against the payload's OWN `publicKeyMultibase`.
|
|
229
|
+
*
|
|
230
|
+
* EVERY EXPECTATION IS THE DEPLOYMENT'S OWN VALUE. There is no arm here that
|
|
231
|
+
* compares the envelope to itself. `expectedDid`, `expectedRoleSet` and
|
|
232
|
+
* `expectedPrevCID` are the position the completing authority is about to WRITE;
|
|
233
|
+
* if the envelope names a different one, the holder consented to something else.
|
|
129
234
|
*
|
|
130
235
|
* STEP 6 (NONCE) IS THE CALLER'S, and this function cannot stand in for it. The
|
|
131
236
|
* nonce MUST be one this verifier minted, for this ceremony, not yet consumed,
|
|
@@ -134,11 +239,89 @@ interface VerifiedKeyProof {
|
|
|
134
239
|
* `payload.nonce` precisely so the caller can run that step next. Without it a
|
|
135
240
|
* proof is replayable for the length of the freshness window.
|
|
136
241
|
*
|
|
137
|
-
* What the
|
|
138
|
-
*
|
|
139
|
-
* Everything after — appending the key to a chain, custody policy,
|
|
140
|
-
* — is the ceremony operator's.
|
|
242
|
+
* What the steps together establish is exactly one fact: THE NAMED KEY WAS HELD,
|
|
243
|
+
* AND CONSENTED TO THIS POSITION IN THIS CHAIN AT THIS VERIFIER, INSIDE THIS
|
|
244
|
+
* WINDOW. Everything after — appending the key to a chain, custody policy,
|
|
245
|
+
* notification — is the ceremony operator's.
|
|
141
246
|
*/
|
|
142
247
|
declare const verifyKeyProof: (jws: string, options: VerifyKeyProofOptions) => VerifiedKeyProof;
|
|
248
|
+
interface VerifyChainKeyProofOptions {
|
|
249
|
+
/** The registered `typ` the introduction requires — `KEY_ADD_JWS_TYP`. */
|
|
250
|
+
expectedTyp: string;
|
|
251
|
+
/** The DID of the chain being walked. */
|
|
252
|
+
did: string;
|
|
253
|
+
/** The carrying operation's `previousOperationCID`. */
|
|
254
|
+
prevCID: string;
|
|
255
|
+
/** The Multikey of the key this envelope is being read as the proof FOR. */
|
|
256
|
+
publicKeyMultibase: string;
|
|
257
|
+
/** The role the introduction needs covered. Coverage, not equality — see below. */
|
|
258
|
+
role: KeyRole;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Verify a key proof AT CHAIN-WALK TIME — the mode a replayer uses on an envelope
|
|
262
|
+
* embedded in a signed identity operation.
|
|
263
|
+
*
|
|
264
|
+
* WHAT IT CHECKS: the signature, the `typ`, the closed schema over canonical
|
|
265
|
+
* bytes, and the four position arms — `publicKeyMultibase` is the key being
|
|
266
|
+
* introduced, `did` is this chain, `prevCID` is the carrying operation's
|
|
267
|
+
* `previousOperationCID`, and `roleSet` COVERS the role in question.
|
|
268
|
+
*
|
|
269
|
+
* WHAT IT DELIBERATELY DOES NOT CHECK, AND WHY. Neither FRESHNESS nor AUDIENCE.
|
|
270
|
+
* Both are properties of a live ceremony, and the walk is not one: the envelope
|
|
271
|
+
* was fresh when it was presented, against a clock and an authority that belonged
|
|
272
|
+
* to the completing operator and not to whoever replays the chain a year later.
|
|
273
|
+
* Checking freshness at walk time would make every chain expire; checking
|
|
274
|
+
* audience would make a chain verifiable only by the relay that wrote it. The two
|
|
275
|
+
* members still travel, still sign, and are still returned — they are FIXED
|
|
276
|
+
* TRANSPORT the signature covers, evidence of which ceremony this was, not gates
|
|
277
|
+
* a walker is positioned to run.
|
|
278
|
+
*
|
|
279
|
+
* COVERAGE, NOT EQUALITY, ON THE ROLE. Presentation-time takes byte equality
|
|
280
|
+
* because the completing authority knows exactly which roles it is about to
|
|
281
|
+
* write. The walk asks a narrower question, once per (key, role) introduction:
|
|
282
|
+
* did the holder consent to THIS role? One envelope consenting to
|
|
283
|
+
* `auth,assert,controller` therefore proves three introductions in one operation,
|
|
284
|
+
* which is the ordinary rotation case.
|
|
285
|
+
*
|
|
286
|
+
* Returns the validated payload. Throws `KeyProofVerifyError` — a chain walker
|
|
287
|
+
* treats every throw as "this introduction is not proved", never as "this chain
|
|
288
|
+
* is invalid": an unproved introduction voids a key-role membership and nothing
|
|
289
|
+
* more.
|
|
290
|
+
*/
|
|
291
|
+
/**
|
|
292
|
+
* The `publicKeyMultibase` an envelope NAMES, read WITHOUT verifying anything —
|
|
293
|
+
* no signature, no schema, no gates. `null` when the bytes do not decode to an
|
|
294
|
+
* object carrying a string there.
|
|
295
|
+
*
|
|
296
|
+
* UNSAFE IS IN THE NAME BECAUSE THE ANSWER PROVES NOTHING. The only sound use is
|
|
297
|
+
* as an INDEX HINT. An operation carrying several envelopes and introducing
|
|
298
|
+
* several keys would otherwise be a quadratic scan — every envelope gated
|
|
299
|
+
* against every candidate — so the chain walk uses this to pick WHICH candidate
|
|
300
|
+
* an envelope is about, then runs the full `verifyChainKeyProof` against that
|
|
301
|
+
* candidate's real, DECLARED Multikey. The gate's own `publicKeyMultibase` arm
|
|
302
|
+
* is what makes the pairing sound: a wrong or forged hint routes the envelope to
|
|
303
|
+
* a candidate it then fails against, which is exactly the verdict the exhaustive
|
|
304
|
+
* scan would have reached. Never read this value as an assertion about a key.
|
|
305
|
+
*/
|
|
306
|
+
declare const unsafeKeyProofSubject: (jws: string) => string | null;
|
|
307
|
+
declare const verifyChainKeyProof: (jws: string, options: VerifyChainKeyProofOptions) => KeyProofPayload;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* The word fingerprint of a key: six lowercase words, space-joined, from the
|
|
311
|
+
* first six bytes of SHA-256 over the UTF-8 bytes of the key's multikey string.
|
|
312
|
+
*
|
|
313
|
+
* Both surfaces a human compares a key across SHOULD render this, and render it
|
|
314
|
+
* from the same string — the `publicKeyMultibase` as the chain declares it, `z…`
|
|
315
|
+
* form, no `did:key:` prefix and no truncation.
|
|
316
|
+
*
|
|
317
|
+
* The input is not validated: this renders words for eyes, and admission of a
|
|
318
|
+
* multikey happens elsewhere.
|
|
319
|
+
*
|
|
320
|
+
* ```ts
|
|
321
|
+
* keyWordFingerprint('z6MkrzLMNwoJSV4P3YccWcbtk8vd9LtgMKnLeaDLUqLuASjb')
|
|
322
|
+
* // 'ragtime decadence python coherence belfast provincial'
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
declare const keyWordFingerprint: (publicKeyMultibase: string) => string;
|
|
143
326
|
|
|
144
|
-
export { DEFAULT_KEY_PROOF_SKEW_SECONDS, KEY_ADD_JWS_TYP, type KeyProofFailureReason, type KeyProofPayload, KeyProofVerifyError, MAX_KEY_PROOF_SIZE, type SignKeyProofInput, type VerifiedKeyProof, type VerifyKeyProofOptions, keyProofSigningInput, signKeyProof, verifyKeyProof };
|
|
327
|
+
export { DEFAULT_KEY_PROOF_SKEW_SECONDS, KEY_ADD_JWS_TYP, KEY_ROLES, type KeyProofFailureReason, type KeyProofPayload, KeyProofVerifyError, type KeyRole, MAX_KEY_PROOF_SIZE, type SignKeyProofInput, type VerifiedKeyProof, type VerifyChainKeyProofOptions, type VerifyKeyProofOptions, isCanonicalRoleSet, keyProofSigningInput, keyWordFingerprint, parseRoleSet, roleSetCovers, serializeRoleSet, signKeyProof, unsafeKeyProofSubject, verifyChainKeyProof, verifyKeyProof };
|
package/dist/key-proof/index.js
CHANGED
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_KEY_PROOF_SKEW_SECONDS,
|
|
3
3
|
KEY_ADD_JWS_TYP,
|
|
4
|
+
KEY_ROLES,
|
|
4
5
|
KeyProofVerifyError,
|
|
5
6
|
MAX_KEY_PROOF_SIZE,
|
|
7
|
+
isCanonicalRoleSet,
|
|
6
8
|
keyProofSigningInput,
|
|
9
|
+
keyWordFingerprint,
|
|
10
|
+
parseRoleSet,
|
|
11
|
+
roleSetCovers,
|
|
12
|
+
serializeRoleSet,
|
|
7
13
|
signKeyProof,
|
|
14
|
+
unsafeKeyProofSubject,
|
|
15
|
+
verifyChainKeyProof,
|
|
8
16
|
verifyKeyProof
|
|
9
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-JVSC67DC.js";
|
|
10
18
|
import "../chunk-IDVYITX7.js";
|
|
11
19
|
import "../chunk-4LG2GEB2.js";
|
|
12
20
|
export {
|
|
13
21
|
DEFAULT_KEY_PROOF_SKEW_SECONDS,
|
|
14
22
|
KEY_ADD_JWS_TYP,
|
|
23
|
+
KEY_ROLES,
|
|
15
24
|
KeyProofVerifyError,
|
|
16
25
|
MAX_KEY_PROOF_SIZE,
|
|
26
|
+
isCanonicalRoleSet,
|
|
17
27
|
keyProofSigningInput,
|
|
28
|
+
keyWordFingerprint,
|
|
29
|
+
parseRoleSet,
|
|
30
|
+
roleSetCovers,
|
|
31
|
+
serializeRoleSet,
|
|
18
32
|
signKeyProof,
|
|
33
|
+
unsafeKeyProofSubject,
|
|
34
|
+
verifyChainKeyProof,
|
|
19
35
|
verifyKeyProof
|
|
20
36
|
};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"type": "identity",
|
|
4
4
|
"chain": [
|
|
5
5
|
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJjaWQiOiJiYWZ5cmVpY29naHZqem52bGl1bG94eG1iZjU0dHB6cXdhaG5xcGlsazduY3hlcGppbmVkcGtnYTNuZSJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiY3JlYXRlIiwiYXV0aEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImFzc2VydEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImNvbnRyb2xsZXJLZXlzIjpbeyJpZCI6ImtleV9yOWV2MzRmdmMyM3o5OTl2ZWFhZnQ4M25uMjl6dmhlIiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa3J6TE1Od29KU1Y0UDNZY2NXY2J0azh2ZDlMdGdNS25MZWFETFVxTHVBU2piIn1dLCJjcmVhdGVkQXQiOiIyMDI2LTAzLTA3VDAwOjAwOjAwLjAwMFoifQ.TeznHnzrtKOGTr0FzkDL2z-luMWnAbKXrmDbi-Exgw_xMPCnYwGHORMjw-BM28f0RoTirIAeD7d20W5RSuGuBg",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciNrZXlfcjlldjM0ZnZjMjN6OTk5dmVhYWZ0ODNubjI5enZoZSIsImNpZCI6ImJhZnlyZWlhcmM3bXY2ZnZoYW9lMm1tazR1anBza2dxcGVzdjY2cHpkNWp1cWxnNWJ6bXJpZGlra3F5In0.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoidXBkYXRlIiwicHJldmlvdXNPcGVyYXRpb25DSUQiOiJiYWZ5cmVpY29naHZqem52bGl1bG94eG1iZjU0dHB6cXdhaG5xcGlsazduY3hlcGppbmVkcGtnYTNuZSIsImF1dGhLZXlzIjpbeyJpZCI6ImtleV9lejlhODc0dGNrcjNkdjkzM2QzY2tkbjd6NnpyY3Q4IiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa2ZVZDY1SnJBaGZkZ0Z1TUNjY1U5VGhRdmpCMmZKQU1VSGt1dWFqRjk5MmdLIn1dLCJhc3NlcnRLZXlzIjpbeyJpZCI6ImtleV9lejlhODc0dGNrcjNkdjkzM2QzY2tkbjd6NnpyY3Q4IiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa2ZVZDY1SnJBaGZkZ0Z1TUNjY1U5VGhRdmpCMmZKQU1VSGt1dWFqRjk5MmdLIn1dLCJjb250cm9sbGVyS2V5cyI6W3siaWQiOiJrZXlfZXo5YTg3NHRja3IzZHY5MzNkM2NrZG43ejZ6cmN0OCIsInR5cGUiOiJNdWx0aWtleSIsInB1YmxpY0tleU11bHRpYmFzZSI6Ino2TWtmVWQ2NUpyQWhmZGdGdU1DY2NVOVRoUXZqQjJmSkFNVUhrdXVhakY5OTJnSyJ9XSwiY3JlYXRlZEF0IjoiMjAyNi0wMy0wN1QwMDowMTowMC4wMDBaIiwia2V5UHJvb2ZzIjpbImV5SmhiR2NpT2lKRlpFUlRRU0lzSW5SNWNDSTZJbVJwWkRwa1ptOXpPbXRsZVMxaFpHUWlmUS5leUp1YjI1alpTSTZJbVJtYjNNdGNISnZkRzlqYjJ3dGNtVm1aWEpsYm1ObExXNXZibU5sTFRFaUxDSmhkV1JwWlc1alpTSTZJbXRsZVhNdVpHWnZjeTVqYjIwaUxDSmthV1FpT2lKa2FXUTZaR1p2Y3pwamJtNXVablE1WmpoaE1uSnVPVE00WkRadWEzb3pPSEk0TkRkMk1tdHlJaXdpY205c1pWTmxkQ0k2SW1GMWRHZ3NZWE56WlhKMExHTnZiblJ5YjJ4c1pYSWlMQ0p3Y21WMlEwbEVJam9pWW1GbWVYSmxhV052WjJoMmFucHVkbXhwZFd4dmVIaHRZbVkxTkhSd2VuRjNZV2h1Y1hCcGJHczNibU40WlhCcWFXNWxaSEJyWjJFemJtVWlMQ0p3ZFdKc2FXTkxaWGxOZFd4MGFXSmhjMlVpT2lKNk5rMXJabFZrTmpWS2NrRm9abVJuUm5WTlEyTmpWVGxVYUZGMmFrSXlaa3BCVFZWSWEzVjFZV3BHT1RreVowc2lMQ0owYVcxbGMzUmhiWEFpT2lJeU1ESTJMVEF6TFRBM1ZEQXdPakF3T2pNd0xqQXdNRm9pZlEuOG5nMTBIYmJzMkJGQ3NZb1NZTkhTMVQwMDIwLUhYbTRhRDEwUXJIbHB5c08xc3FteTFVX2RqOXlFejBDSlNNQ1lOd2hUWk1iVGlhbmhKOENIMUx0QXciXX0.13or_X7zDOezkSFHdWBLwPcNyIaG3XlHAb9mHpgG8zVDldz0wGP0X8WiVIHPLQ-20ZsCOvsh8Y6BbgxdbIvMBA",
|
|
7
|
+
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciNrZXlfZXo5YTg3NHRja3IzZHY5MzNkM2NrZG43ejZ6cmN0OCIsImNpZCI6ImJhZnlyZWlhaXk1bTRmaXludGRyeWlremZ3enlub2p3aWdsa3Fyd2llZnVsYjRkbDM2ZXFlZWZicHdtIn0.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiZGVsZXRlIiwicHJldmlvdXNPcGVyYXRpb25DSUQiOiJiYWZ5cmVpYXJjN212NmZ2aGFvZTJtbWs0dWpwc2tncXBlc3Y2NnB6ZDVqdXFsZzViem1yaWRpa2txeSIsImNyZWF0ZWRBdCI6IjIwMjYtMDMtMDdUMDA6MDI6MDAuMDAwWiJ9.QIh-HRD-YEV84yg1X3Lwz-tXJEGPCLruTssWC6Igb5j_QG0aGPjJ6sAqFE1VM8KURYlmFkaLgYZV6O2831YBCA",
|
|
8
|
+
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciNrZXlfZXo5YTg3NHRja3IzZHY5MzNkM2NrZG43ejZ6cmN0OCIsImNpZCI6ImJhZnlyZWljZnhwNjVtM2pzNHRlbGxiM29wdHduNTRnaW5xdjdwcDRsZGlmY251dnJ5N2dsdW5oN2FxIn0.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoicmVzdG9yZSIsInByZXZpb3VzT3BlcmF0aW9uQ0lEIjoiYmFmeXJlaWFpeTVtNGZpeW50ZHJ5aWt6Znd6eW5vandpZ2xrcXJ3aWVmdWxiNGRsMzZlcWVlZmJwd20iLCJjcmVhdGVkQXQiOiIyMDI2LTAzLTA3VDAwOjAzOjAwLjAwMFoifQ.JiIAXKZqIZnDpZUrbd4S7F7tEoBEjEeIKcGg3WReYXAFJii960wpZLFfyrc3yAKONsMw9hT5aFRivos4kthuBA"
|
|
9
9
|
],
|
|
10
10
|
"expected": {
|
|
11
11
|
"did": "did:dfos:cnnnft9f8a2rn938d6nkz38r847v2kr",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"type": "identity",
|
|
4
4
|
"chain": [
|
|
5
5
|
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJjaWQiOiJiYWZ5cmVpY29naHZqem52bGl1bG94eG1iZjU0dHB6cXdhaG5xcGlsazduY3hlcGppbmVkcGtnYTNuZSJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiY3JlYXRlIiwiYXV0aEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImFzc2VydEtleXMiOlt7ImlkIjoia2V5X3I5ZXYzNGZ2YzIzejk5OXZlYWFmdDgzbm4yOXp2aGUiLCJ0eXBlIjoiTXVsdGlrZXkiLCJwdWJsaWNLZXlNdWx0aWJhc2UiOiJ6Nk1rcnpMTU53b0pTVjRQM1ljY1djYnRrOHZkOUx0Z01LbkxlYURMVXFMdUFTamIifV0sImNvbnRyb2xsZXJLZXlzIjpbeyJpZCI6ImtleV9yOWV2MzRmdmMyM3o5OTl2ZWFhZnQ4M25uMjl6dmhlIiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa3J6TE1Od29KU1Y0UDNZY2NXY2J0azh2ZDlMdGdNS25MZWFETFVxTHVBU2piIn1dLCJjcmVhdGVkQXQiOiIyMDI2LTAzLTA3VDAwOjAwOjAwLjAwMFoifQ.TeznHnzrtKOGTr0FzkDL2z-luMWnAbKXrmDbi-Exgw_xMPCnYwGHORMjw-BM28f0RoTirIAeD7d20W5RSuGuBg",
|
|
6
|
-
"
|
|
6
|
+
"eyJhbGciOiJFZERTQSIsInR5cCI6ImRpZDpkZm9zOmlkZW50aXR5LW9wIiwia2lkIjoiZGlkOmRmb3M6Y25ubmZ0OWY4YTJybjkzOGQ2bmt6MzhyODQ3djJrciNrZXlfcjlldjM0ZnZjMjN6OTk5dmVhYWZ0ODNubjI5enZoZSIsImNpZCI6ImJhZnlyZWlhcmM3bXY2ZnZoYW9lMm1tazR1anBza2dxcGVzdjY2cHpkNWp1cWxnNWJ6bXJpZGlra3F5In0.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoidXBkYXRlIiwicHJldmlvdXNPcGVyYXRpb25DSUQiOiJiYWZ5cmVpY29naHZqem52bGl1bG94eG1iZjU0dHB6cXdhaG5xcGlsazduY3hlcGppbmVkcGtnYTNuZSIsImF1dGhLZXlzIjpbeyJpZCI6ImtleV9lejlhODc0dGNrcjNkdjkzM2QzY2tkbjd6NnpyY3Q4IiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa2ZVZDY1SnJBaGZkZ0Z1TUNjY1U5VGhRdmpCMmZKQU1VSGt1dWFqRjk5MmdLIn1dLCJhc3NlcnRLZXlzIjpbeyJpZCI6ImtleV9lejlhODc0dGNrcjNkdjkzM2QzY2tkbjd6NnpyY3Q4IiwidHlwZSI6Ik11bHRpa2V5IiwicHVibGljS2V5TXVsdGliYXNlIjoiejZNa2ZVZDY1SnJBaGZkZ0Z1TUNjY1U5VGhRdmpCMmZKQU1VSGt1dWFqRjk5MmdLIn1dLCJjb250cm9sbGVyS2V5cyI6W3siaWQiOiJrZXlfZXo5YTg3NHRja3IzZHY5MzNkM2NrZG43ejZ6cmN0OCIsInR5cGUiOiJNdWx0aWtleSIsInB1YmxpY0tleU11bHRpYmFzZSI6Ino2TWtmVWQ2NUpyQWhmZGdGdU1DY2NVOVRoUXZqQjJmSkFNVUhrdXVhakY5OTJnSyJ9XSwiY3JlYXRlZEF0IjoiMjAyNi0wMy0wN1QwMDowMTowMC4wMDBaIiwia2V5UHJvb2ZzIjpbImV5SmhiR2NpT2lKRlpFUlRRU0lzSW5SNWNDSTZJbVJwWkRwa1ptOXpPbXRsZVMxaFpHUWlmUS5leUp1YjI1alpTSTZJbVJtYjNNdGNISnZkRzlqYjJ3dGNtVm1aWEpsYm1ObExXNXZibU5sTFRFaUxDSmhkV1JwWlc1alpTSTZJbXRsZVhNdVpHWnZjeTVqYjIwaUxDSmthV1FpT2lKa2FXUTZaR1p2Y3pwamJtNXVablE1WmpoaE1uSnVPVE00WkRadWEzb3pPSEk0TkRkMk1tdHlJaXdpY205c1pWTmxkQ0k2SW1GMWRHZ3NZWE56WlhKMExHTnZiblJ5YjJ4c1pYSWlMQ0p3Y21WMlEwbEVJam9pWW1GbWVYSmxhV052WjJoMmFucHVkbXhwZFd4dmVIaHRZbVkxTkhSd2VuRjNZV2h1Y1hCcGJHczNibU40WlhCcWFXNWxaSEJyWjJFemJtVWlMQ0p3ZFdKc2FXTkxaWGxOZFd4MGFXSmhjMlVpT2lKNk5rMXJabFZrTmpWS2NrRm9abVJuUm5WTlEyTmpWVGxVYUZGMmFrSXlaa3BCVFZWSWEzVjFZV3BHT1RreVowc2lMQ0owYVcxbGMzUmhiWEFpT2lJeU1ESTJMVEF6TFRBM1ZEQXdPakF3T2pNd0xqQXdNRm9pZlEuOG5nMTBIYmJzMkJGQ3NZb1NZTkhTMVQwMDIwLUhYbTRhRDEwUXJIbHB5c08xc3FteTFVX2RqOXlFejBDSlNNQ1lOd2hUWk1iVGlhbmhKOENIMUx0QXciXX0.13or_X7zDOezkSFHdWBLwPcNyIaG3XlHAb9mHpgG8zVDldz0wGP0X8WiVIHPLQ-20ZsCOvsh8Y6BbgxdbIvMBA"
|
|
7
7
|
],
|
|
8
8
|
"expected": {
|
|
9
9
|
"did": "did:dfos:cnnnft9f8a2rn938d6nkz38r847v2kr",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metalabel/dfos-protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DFOS Protocol — Ed25519 signed chain primitives, services, credentials, and verification",
|
|
6
6
|
"license": "MIT",
|
|
@@ -72,13 +72,14 @@
|
|
|
72
72
|
"ajv-formats": "^3.0.1",
|
|
73
73
|
"tsup": "^8.5.1",
|
|
74
74
|
"tsx": "^4.22.4",
|
|
75
|
+
"typescript": "^5.9.3",
|
|
75
76
|
"vitest": "^4.1.8",
|
|
76
77
|
"zod": "^4.4.3"
|
|
77
78
|
},
|
|
78
79
|
"scripts": {
|
|
79
80
|
"build": "tsup",
|
|
80
81
|
"clean": "rm -rf dist",
|
|
81
|
-
"typecheck": "tsc --noEmit",
|
|
82
|
+
"typecheck": "node ../../node_modules/typescript7/bin/tsc --noEmit",
|
|
82
83
|
"test": "vitest run",
|
|
83
84
|
"generate-examples": "tsx scripts/generate-examples.ts"
|
|
84
85
|
}
|