@vess-id/ai-identity 0.0.0-dev-20260902121045
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 +265 -0
- package/dist/agent/agent-did-manager.d.ts +97 -0
- package/dist/agent/agent-did-manager.d.ts.map +1 -0
- package/dist/auth/auth-provider.d.ts +51 -0
- package/dist/auth/auth-provider.d.ts.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/client.d.ts +63 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/config/index.d.ts +84 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/constraint/constraint-evaluator.d.ts +103 -0
- package/dist/constraint/constraint-evaluator.d.ts.map +1 -0
- package/dist/constraint/index.d.ts +5 -0
- package/dist/constraint/index.d.ts.map +1 -0
- package/dist/did/agent.d.ts +58 -0
- package/dist/did/agent.d.ts.map +1 -0
- package/dist/did/did-utils.d.ts +82 -0
- package/dist/did/did-utils.d.ts.map +1 -0
- package/dist/did/key-manager.d.ts +19 -0
- package/dist/did/key-manager.d.ts.map +1 -0
- package/dist/gateway/gateway-client.d.ts +103 -0
- package/dist/gateway/gateway-client.d.ts.map +1 -0
- package/dist/gateway/index.d.ts +2 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/grant/grant-manager.d.ts +140 -0
- package/dist/grant/grant-manager.d.ts.map +1 -0
- package/dist/grant/index.d.ts +2 -0
- package/dist/grant/index.d.ts.map +1 -0
- package/dist/identity/device-enroll-manager.d.ts +117 -0
- package/dist/identity/device-enroll-manager.d.ts.map +1 -0
- package/dist/identity/user-identity-manager.d.ts +123 -0
- package/dist/identity/user-identity-manager.d.ts.map +1 -0
- package/dist/identity/user-key-pair-manager.d.ts +22 -0
- package/dist/identity/user-key-pair-manager.d.ts.map +1 -0
- package/dist/index.d.mts +42685 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19534 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19347 -0
- package/dist/index.mjs.map +1 -0
- package/dist/internal-signature/canonical.d.ts +80 -0
- package/dist/internal-signature/canonical.d.ts.map +1 -0
- package/dist/internal-signature/index.d.ts +17 -0
- package/dist/internal-signature/index.d.ts.map +1 -0
- package/dist/internal-signature/signer.d.ts +76 -0
- package/dist/internal-signature/signer.d.ts.map +1 -0
- package/dist/policy/cedar-engine.d.ts +334 -0
- package/dist/policy/cedar-engine.d.ts.map +1 -0
- package/dist/policy/cedar-entities.d.ts +59 -0
- package/dist/policy/cedar-entities.d.ts.map +1 -0
- package/dist/policy/decision.d.ts +46 -0
- package/dist/policy/decision.d.ts.map +1 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/registry/access-orchestrator.d.ts +184 -0
- package/dist/registry/access-orchestrator.d.ts.map +1 -0
- package/dist/registry/action-aliases.d.ts +37 -0
- package/dist/registry/action-aliases.d.ts.map +1 -0
- package/dist/registry/action-input-validator.d.ts +19 -0
- package/dist/registry/action-input-validator.d.ts.map +1 -0
- package/dist/registry/action-normalizer.d.ts +47 -0
- package/dist/registry/action-normalizer.d.ts.map +1 -0
- package/dist/registry/action-registry-json.d.ts +35897 -0
- package/dist/registry/action-registry-json.d.ts.map +1 -0
- package/dist/registry/action-registry.d.ts +101 -0
- package/dist/registry/action-registry.d.ts.map +1 -0
- package/dist/registry/action-risk.d.ts +109 -0
- package/dist/registry/action-risk.d.ts.map +1 -0
- package/dist/registry/action-summary.d.ts +16 -0
- package/dist/registry/action-summary.d.ts.map +1 -0
- package/dist/registry/index.d.ts +14 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/providers.d.ts +32 -0
- package/dist/registry/providers.d.ts.map +1 -0
- package/dist/registry/reauth-constants.d.ts +56 -0
- package/dist/registry/reauth-constants.d.ts.map +1 -0
- package/dist/registry/resource-type-labels.d.ts +15 -0
- package/dist/registry/resource-type-labels.d.ts.map +1 -0
- package/dist/registry/resource-types.d.ts +47 -0
- package/dist/registry/resource-types.d.ts.map +1 -0
- package/dist/resolver/approval-time-resolution.d.ts +72 -0
- package/dist/resolver/approval-time-resolution.d.ts.map +1 -0
- package/dist/resolver/canonical-resource-id.d.ts +37 -0
- package/dist/resolver/canonical-resource-id.d.ts.map +1 -0
- package/dist/resolver/compare-resource-id.d.ts +37 -0
- package/dist/resolver/compare-resource-id.d.ts.map +1 -0
- package/dist/resolver/salient-digest.d.ts +48 -0
- package/dist/resolver/salient-digest.d.ts.map +1 -0
- package/dist/resolver/target-resolver.d.ts +28 -0
- package/dist/resolver/target-resolver.d.ts.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/json-state-store.d.ts +24 -0
- package/dist/state/json-state-store.d.ts.map +1 -0
- package/dist/state/state-store.interface.d.ts +37 -0
- package/dist/state/state-store.interface.d.ts.map +1 -0
- package/dist/storage/filesystem-key-storage.d.ts +16 -0
- package/dist/storage/filesystem-key-storage.d.ts.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/key-storage.interface.d.ts +42 -0
- package/dist/storage/key-storage.interface.d.ts.map +1 -0
- package/dist/storage/memory-key-storage.d.ts +17 -0
- package/dist/storage/memory-key-storage.d.ts.map +1 -0
- package/dist/tool/tool-manager.d.ts +44 -0
- package/dist/tool/tool-manager.d.ts.map +1 -0
- package/dist/types/agent.d.ts +139 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/audit.d.ts +23 -0
- package/dist/types/audit.d.ts.map +1 -0
- package/dist/types/cedar-policy.d.ts +60 -0
- package/dist/types/cedar-policy.d.ts.map +1 -0
- package/dist/types/connector-plugin.d.ts +252 -0
- package/dist/types/connector-plugin.d.ts.map +1 -0
- package/dist/types/connectors.d.ts +39 -0
- package/dist/types/connectors.d.ts.map +1 -0
- package/dist/types/context.d.ts +152 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/did.d.ts +18 -0
- package/dist/types/did.d.ts.map +1 -0
- package/dist/types/errors.d.ts +24 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/grant.d.ts +522 -0
- package/dist/types/grant.d.ts.map +1 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/intent.d.ts +133 -0
- package/dist/types/intent.d.ts.map +1 -0
- package/dist/types/invitation.d.ts +97 -0
- package/dist/types/invitation.d.ts.map +1 -0
- package/dist/types/jira.d.ts +348 -0
- package/dist/types/jira.d.ts.map +1 -0
- package/dist/types/oauth.d.ts +72 -0
- package/dist/types/oauth.d.ts.map +1 -0
- package/dist/types/organization.d.ts +77 -0
- package/dist/types/organization.d.ts.map +1 -0
- package/dist/types/permission-mode.d.ts +138 -0
- package/dist/types/permission-mode.d.ts.map +1 -0
- package/dist/types/permission-vc.d.ts +800 -0
- package/dist/types/permission-vc.d.ts.map +1 -0
- package/dist/types/receipt.d.ts +133 -0
- package/dist/types/receipt.d.ts.map +1 -0
- package/dist/types/target-binding.d.ts +163 -0
- package/dist/types/target-binding.d.ts.map +1 -0
- package/dist/types/tier.d.ts +13 -0
- package/dist/types/tier.d.ts.map +1 -0
- package/dist/types/vc.d.ts +213 -0
- package/dist/types/vc.d.ts.map +1 -0
- package/dist/types/vp.d.ts +25 -0
- package/dist/types/vp.d.ts.map +1 -0
- package/dist/utils/action-classifier.d.ts +13 -0
- package/dist/utils/action-classifier.d.ts.map +1 -0
- package/dist/utils/crypto.d.ts +22 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/freemail-domains.d.ts +13 -0
- package/dist/utils/freemail-domains.d.ts.map +1 -0
- package/dist/utils/sdjwt-client.d.ts +415 -0
- package/dist/utils/sdjwt-client.d.ts.map +1 -0
- package/dist/utils/sdjwt-disclosure.d.ts +13 -0
- package/dist/utils/sdjwt-disclosure.d.ts.map +1 -0
- package/dist/utils/tier-utils.d.ts +15 -0
- package/dist/utils/tier-utils.d.ts.map +1 -0
- package/dist/vc/api-vc-manager.d.ts +43 -0
- package/dist/vc/api-vc-manager.d.ts.map +1 -0
- package/dist/vc/vc-manager.d.ts +55 -0
- package/dist/vc/vc-manager.d.ts.map +1 -0
- package/dist/vp/kb-jwt-builder.d.ts +89 -0
- package/dist/vp/kb-jwt-builder.d.ts.map +1 -0
- package/dist/vp/vp-manager.d.ts +75 -0
- package/dist/vp/vp-manager.d.ts.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { SDJwtVcInstance } from '@sd-jwt/sd-jwt-vc';
|
|
2
|
+
import { KeyManager } from '../did/key-manager';
|
|
3
|
+
import type { DisclosureFrame } from '@sd-jwt/types';
|
|
4
|
+
import type { JWK } from 'jose';
|
|
5
|
+
export declare class SDJwtClient {
|
|
6
|
+
/**
|
|
7
|
+
* 🔴 Keyed by DID **and** by the identity of the key that was resolved.
|
|
8
|
+
*
|
|
9
|
+
* The instance holds a signer built from a private key the KeyManager
|
|
10
|
+
* handed over, so two stores holding *different* keys for one DID must not
|
|
11
|
+
* share an instance. Keying on the DID alone returned whichever one was
|
|
12
|
+
* built first — and since `setKeyManager` replaces a static field,
|
|
13
|
+
* constructing a second VPManager silently repointed every later lookup at
|
|
14
|
+
* a store that did not have the key. Measured: an agent that generated its
|
|
15
|
+
* DID through one manager could not present with another, failing as
|
|
16
|
+
* `Private key not found for holder` with the key sitting in the first
|
|
17
|
+
* manager's store the whole time.
|
|
18
|
+
*
|
|
19
|
+
* 🔴 The discriminator is the KEY, not the KeyManager object. Keying on
|
|
20
|
+
* object identity (a WeakMap-assigned `km0`/`km1`/…) fixed the mix-up and
|
|
21
|
+
* broke two other things, because the api builds a throwaway KeyManager
|
|
22
|
+
* per request — `new APIVCManager(new KeyManager(ephemeral))` at
|
|
23
|
+
* grant/services/remote-vc-issuer.service.ts:2234, which runs on every
|
|
24
|
+
* tool-invoke auto-issue, plus five more sites:
|
|
25
|
+
*
|
|
26
|
+
* 1. Same key material, new object, new id — so a long-lived issuer
|
|
27
|
+
* (user/services/sdjwt-credential.service.ts:69) could not read back
|
|
28
|
+
* its own warm entry once a per-request manager had replaced the
|
|
29
|
+
* static. It failed outright rather than falling back. Measured:
|
|
30
|
+
* `{"resolved":false,"msg":"Private key not found for issuer: … km1"}`
|
|
31
|
+
* where the DID-only key gave `{"resolved":true}` — by accident, by
|
|
32
|
+
* returning the wrong signer on a cache hit.
|
|
33
|
+
*
|
|
34
|
+
* 2. Entries accumulated without bound. `keyManagerIds` is a WeakMap, so
|
|
35
|
+
* a collected manager releases its id — but the Map entry keyed by
|
|
36
|
+
* that id string stays, and a signer closes over a DECRYPTED PRIVATE
|
|
37
|
+
* KEY. Nothing in the api calls `clearIssuerCache`. Measured over 25
|
|
38
|
+
* issuances of one DID: `{"instanceCount":25,"signerCount":25}` where
|
|
39
|
+
* the DID-only key gave 1.
|
|
40
|
+
*
|
|
41
|
+
* A thumbprint (RFC 7638) is the right granularity for both: same key ⇒
|
|
42
|
+
* same entry whoever holds it, different key ⇒ different entry. It is
|
|
43
|
+
* computed over the public members only (`crv`/`kty`/`x`/`y` — `d`, `kid`
|
|
44
|
+
* and `alg` are excluded by the spec), which is what makes two stores
|
|
45
|
+
* holding the same keypair agree. Two *different* private keys sharing a
|
|
46
|
+
* public half is not a case that exists for a valid EC pair, so nothing is
|
|
47
|
+
* conflated that should not be. Measured at ~1.7µs per call, against an
|
|
48
|
+
* ECDSA signature that follows it.
|
|
49
|
+
*/
|
|
50
|
+
private static instances;
|
|
51
|
+
/**
|
|
52
|
+
* 🔴 Only ever read as a fallback — when a call arrives without a KeyManager.
|
|
53
|
+
*
|
|
54
|
+
* `VCManager`, `VPManager` and `APIVCManager` used to assign it in their
|
|
55
|
+
* constructors. They no longer do — every one of them passes its own
|
|
56
|
+
* KeyManager to each call — so within the SDK this field holds whatever an
|
|
57
|
+
* external consumer set via the deprecated {@link setKeyManager}, and
|
|
58
|
+
* otherwise a default `new KeyManager()` that {@link resolveKey} creates the
|
|
59
|
+
* first time it actually has to fall back. Nothing else writes it, and a
|
|
60
|
+
* call that carries its own store never causes that default to exist.
|
|
61
|
+
*
|
|
62
|
+
* It stays because `SDJwtClient` is a public export and a consumer pairing
|
|
63
|
+
* `setKeyManager` with {@link getSDJwtInstance} would otherwise break on a
|
|
64
|
+
* minor release. Removal belongs to the next major.
|
|
65
|
+
*/
|
|
66
|
+
private static keyManager;
|
|
67
|
+
private static signerCache;
|
|
68
|
+
private static verifierCache;
|
|
69
|
+
/**
|
|
70
|
+
* A stable identifier for the key itself, shared by every store holding it.
|
|
71
|
+
*
|
|
72
|
+
* 🔴 Falls back to a per-call unique value rather than to a constant when
|
|
73
|
+
* the thumbprint cannot be computed. A constant would make two unrelated
|
|
74
|
+
* malformed keys collide on one cache entry, which is the mix-up this whole
|
|
75
|
+
* scheme exists to prevent — the safe direction of failure is "cache
|
|
76
|
+
* nothing", never "share an entry". In practice this is unreachable for a
|
|
77
|
+
* key that got through `getKey`; it is here so a future JWK shape degrades
|
|
78
|
+
* into a slow path instead of a wrong one.
|
|
79
|
+
*/
|
|
80
|
+
private static keyId;
|
|
81
|
+
private static nextFallbackKeyId;
|
|
82
|
+
/**
|
|
83
|
+
* 🔴 Cache keys are built here and nowhere else.
|
|
84
|
+
*
|
|
85
|
+
* Three maps, three key shapes. When they were assembled inline at each
|
|
86
|
+
* call site, `clearIssuerCache` wrote its own third version from memory and
|
|
87
|
+
* matched only one of them: it deleted `issuerDid` where the instance was
|
|
88
|
+
* stored as `${did}:issuer:${kmId}`, and `signer:${did}` where the signer
|
|
89
|
+
* was stored as `signer:${did}:${kmId}`. Measured before the fix — one
|
|
90
|
+
* issuer cached, then cleared:
|
|
91
|
+
*
|
|
92
|
+
* BEFORE {"instanceCount":1,"signerCount":1,"verifierCount":1}
|
|
93
|
+
* AFTER {"instanceCount":1,"signerCount":1,"verifierCount":0}
|
|
94
|
+
*
|
|
95
|
+
* The signer closes over a decrypted private key, so the two that survived
|
|
96
|
+
* were the two that mattered. Keeping writers and the eraser on one
|
|
97
|
+
* definition is what stops that from drifting apart again.
|
|
98
|
+
*/
|
|
99
|
+
private static instanceKey;
|
|
100
|
+
private static signerKey;
|
|
101
|
+
/**
|
|
102
|
+
* The part of a key that identifies the DID, up to and including the
|
|
103
|
+
* delimiter before the key-identity segment.
|
|
104
|
+
*
|
|
105
|
+
* 🔴 `clearIssuerCache` matches on these rather than rebuilding prefixes of
|
|
106
|
+
* its own — writing the shape a second time is the mistake being fixed. The
|
|
107
|
+
* trailing `:` is load-bearing: matching a bare DID would make
|
|
108
|
+
* `did:key:abc` also evict `did:key:abcd`.
|
|
109
|
+
*/
|
|
110
|
+
private static instancePrefix;
|
|
111
|
+
private static signerPrefix;
|
|
112
|
+
/**
|
|
113
|
+
* 🔴 Carries the key identity too, symmetrically with {@link signerKey}.
|
|
114
|
+
*
|
|
115
|
+
* It used to be keyed by DID alone, on the reasoning that "a verifier is
|
|
116
|
+
* built from the public half, which is the same value no matter which store
|
|
117
|
+
* the private key came out of". That holds for the case the caches were
|
|
118
|
+
* built for — one keypair, several stores — and fails for the exact case
|
|
119
|
+
* the key segment exists to separate: two stores holding *different* keys
|
|
120
|
+
* under one DID. There the second caller reused the first's verifier and so
|
|
121
|
+
* checked signatures against a public key that was not its own.
|
|
122
|
+
*
|
|
123
|
+
* Costs nothing now that the segment is the key's own thumbprint rather
|
|
124
|
+
* than a per-object id: the same keypair still yields one entry however
|
|
125
|
+
* many managers hold it, which is what the old comment actually wanted.
|
|
126
|
+
*/
|
|
127
|
+
private static verifierKey;
|
|
128
|
+
private static verifierPrefix;
|
|
129
|
+
private constructor();
|
|
130
|
+
/**
|
|
131
|
+
* Initialize with KeyManager for DID-based key management
|
|
132
|
+
*
|
|
133
|
+
* @deprecated Pass the KeyManager to the call instead:
|
|
134
|
+
* {@link getIssuerInstance}`(did, keyManager)`,
|
|
135
|
+
* {@link getHolderInstance}`(did, keyManager)`, {@link issueSDJWT} and
|
|
136
|
+
* {@link verifySDJWT} all take one. This setter writes a **static** field,
|
|
137
|
+
* so every manager an application constructs repoints key resolution for
|
|
138
|
+
* every other one — construction order decides which store is searched.
|
|
139
|
+
*
|
|
140
|
+
* 🔴 Not a style preference; it caused a production failure. A long-lived
|
|
141
|
+
* issuer and a per-request `new APIVCManager(new KeyManager(ephemeral))`
|
|
142
|
+
* coexist in the api, and whichever ran last won: the long-lived one then
|
|
143
|
+
* signed with a store that was not its own or failed outright with
|
|
144
|
+
* `Private key not found for issuer: …`. See PR #1441.
|
|
145
|
+
*
|
|
146
|
+
* Retained for external SDK consumers that pair it with
|
|
147
|
+
* {@link getSDJwtInstance}; scheduled for removal in the next major.
|
|
148
|
+
*/
|
|
149
|
+
static setKeyManager(keyManager: KeyManager): void;
|
|
150
|
+
/**
|
|
151
|
+
* Get SDJwtVcInstance for issuer role (VC issuance)
|
|
152
|
+
*/
|
|
153
|
+
static getIssuerInstance(issuerDid: string, keyManager?: KeyManager): Promise<SDJwtVcInstance>;
|
|
154
|
+
/**
|
|
155
|
+
* Get SDJwtVcInstance for holder role (VP presentation)
|
|
156
|
+
*/
|
|
157
|
+
static getHolderInstance(holderDid: string, keyManager?: KeyManager): Promise<SDJwtVcInstance>;
|
|
158
|
+
/**
|
|
159
|
+
* Resolve the key, then look in the cache — in that order.
|
|
160
|
+
*
|
|
161
|
+
* 🔴 The order is the fix, not an implementation detail. The cache key
|
|
162
|
+
* names the key that was resolved, so it cannot be built before resolving,
|
|
163
|
+
* and the store must therefore be consulted on a hit as well as a miss.
|
|
164
|
+
* That is what makes a warm entry reachable from any manager holding the
|
|
165
|
+
* same key: with the KeyManager object in the key, the caller whose store
|
|
166
|
+
* DID hold the key looked under a name nobody had written to and got
|
|
167
|
+
* `Private key not found` — the store had it the whole time.
|
|
168
|
+
*
|
|
169
|
+
* The extra work on a hit is one `getKey` (an in-memory or DB read the
|
|
170
|
+
* caller would owe anyway on a miss) plus a ~1.7µs thumbprint. What is
|
|
171
|
+
* saved is the SDJwtVcInstance and, more to the point, re-importing the
|
|
172
|
+
* key material into a signer.
|
|
173
|
+
*/
|
|
174
|
+
private static getInstance;
|
|
175
|
+
/**
|
|
176
|
+
* Fetch the DID's private key from the given store (or the static one) and
|
|
177
|
+
* derive the identity the caches key on.
|
|
178
|
+
*/
|
|
179
|
+
private static resolveKey;
|
|
180
|
+
/**
|
|
181
|
+
* Get SDJwtVcInstance with specified role (backward compatibility)
|
|
182
|
+
*
|
|
183
|
+
* @deprecated Call {@link getIssuerInstance}`(did, keyManager)` or
|
|
184
|
+
* {@link getHolderInstance}`(did, keyManager)` directly — this wrapper adds
|
|
185
|
+
* nothing but the role switch, and the role is known at every call site.
|
|
186
|
+
*
|
|
187
|
+
* 🔴 `keyManager` was added here because omitting it was the defect: with no
|
|
188
|
+
* way to name a store, every caller of this wrapper fell through to the
|
|
189
|
+
* static field and so was the one path that could not benefit from the
|
|
190
|
+
* PR #1441 fix. Callers that still omit it keep the old static behaviour, so
|
|
191
|
+
* existing external code is unaffected.
|
|
192
|
+
*/
|
|
193
|
+
static getSDJwtInstance(did: string, options?: {
|
|
194
|
+
role?: 'issuer' | 'holder';
|
|
195
|
+
keyManager?: KeyManager;
|
|
196
|
+
}): Promise<SDJwtVcInstance>;
|
|
197
|
+
/**
|
|
198
|
+
* Create a new SDJwtVcInstance with DID-based keys and role
|
|
199
|
+
*/
|
|
200
|
+
private static createInstance;
|
|
201
|
+
/**
|
|
202
|
+
* Claims that MUST NOT be selectively disclosable.
|
|
203
|
+
*
|
|
204
|
+
* - cnf: Proof of Possession binding (RFC 7800). If disclosable, Holder can
|
|
205
|
+
* hide cnf to bypass PoP verification and transfer VC to another party.
|
|
206
|
+
* - Standard JWT registered claims (iss, sub, exp, iat, nbf, jti) must
|
|
207
|
+
* always be visible for signature verification and expiry checks.
|
|
208
|
+
* - vct: SD-JWT VC credential type discriminator.
|
|
209
|
+
*/
|
|
210
|
+
private static readonly NEVER_DISCLOSE;
|
|
211
|
+
/**
|
|
212
|
+
* Claims that decide whether an action is PERMITTED, and so must not be
|
|
213
|
+
* withholdable by the party they constrain.
|
|
214
|
+
*
|
|
215
|
+
* 🔴 Separate from NEVER_DISCLOSE on purpose. That set is about structural
|
|
216
|
+
* integrity — hide `cnf` and Proof of Possession cannot be checked at all.
|
|
217
|
+
* This set is about authorisation: these fields are readable, they simply
|
|
218
|
+
* must not be OPTIONAL, because SD-JWT makes an undisclosed field
|
|
219
|
+
* physically absent rather than merely hidden. A holder who omits the
|
|
220
|
+
* disclosure presents a credential with no constraints on it.
|
|
221
|
+
*
|
|
222
|
+
* The harm is not theoretical. Gate-2 permits when the delegate list is
|
|
223
|
+
* empty (tool-executor.service.ts) — deliberate backward compatibility for
|
|
224
|
+
* two credential shapes that genuinely carry no `delegates` — and a
|
|
225
|
+
* withheld disclosure lands in that same branch. Cedar Gate-1 backstops
|
|
226
|
+
* high-risk actions, but only where the Cedar default policy is
|
|
227
|
+
* bootstrapped; that early return's own comment records that a non-Cedar
|
|
228
|
+
* deployment's flat-permission fallback does not risk-gate, making the
|
|
229
|
+
* withholding an unconditional allow there.
|
|
230
|
+
*
|
|
231
|
+
* 🔴 Enforced here rather than by curating each caller's field list. Four
|
|
232
|
+
* issuance paths pass their own arrays — remote-vc-issuer.service.ts,
|
|
233
|
+
* user/services/sdjwt-credential.service.ts (a hardcoded switch that
|
|
234
|
+
* duplicates the SDK config), sdk/src/vc/api-vc-manager.ts, and
|
|
235
|
+
* oauth.service.ts in two places — so fixing one leaves three standing,
|
|
236
|
+
* and a fifth added later would inherit the defect. This function is the
|
|
237
|
+
* single point all of them flow through.
|
|
238
|
+
*
|
|
239
|
+
* It is also the only place that can stop the NESTED case: the recursion
|
|
240
|
+
* below passes every key of a nested object as disclosable regardless of
|
|
241
|
+
* what was requested, which no call-site list can reach.
|
|
242
|
+
*
|
|
243
|
+
* What is NOT here: `approval` and `intent_description`. Those are
|
|
244
|
+
* selective for privacy — an approver's identity, free text — and no gate
|
|
245
|
+
* reads them to decide anything. The line being drawn is "authorisation
|
|
246
|
+
* input", not "sensitive".
|
|
247
|
+
*
|
|
248
|
+
* Field-by-field, with where each is read:
|
|
249
|
+
* - delegates: carries actions/effect/resource (tool-auth.service.ts)
|
|
250
|
+
* - actions: what a delegate may do
|
|
251
|
+
* - tool: prefixes bare actions into the permission string that
|
|
252
|
+
* gates the decision; withheld, `message.post` is emitted
|
|
253
|
+
* instead of `slack.message.post` — a different string
|
|
254
|
+
* - resourceScope: gates the scope match (tool-manager.ts)
|
|
255
|
+
* - permissions: the flat-permission path (tool-auth.service.ts)
|
|
256
|
+
* - effect: whether a delegate rule allows or denies
|
|
257
|
+
* - resource: what a rule applies to
|
|
258
|
+
*/
|
|
259
|
+
private static readonly NEVER_SELECTIVE;
|
|
260
|
+
/**
|
|
261
|
+
* Create disclosure frame for selective disclosure
|
|
262
|
+
*/
|
|
263
|
+
static createDisclosureFrame<T extends Record<string, any>>(claims: T, selectivelyDisclosable?: string[]): DisclosureFrame<T>;
|
|
264
|
+
/**
|
|
265
|
+
* Issue an SD-JWT with selective disclosure
|
|
266
|
+
*/
|
|
267
|
+
static issueSDJWT(payload: Record<string, any>, _privateKey: any, // Not used since we get key from KeyManager based on issuer DID
|
|
268
|
+
selectiveDisclosureFields?: string[], keyManager?: KeyManager): Promise<string>;
|
|
269
|
+
/**
|
|
270
|
+
* Verify an SD-JWT
|
|
271
|
+
*/
|
|
272
|
+
static verifySDJWT(credential: string, keyManager?: KeyManager): Promise<{
|
|
273
|
+
valid: boolean;
|
|
274
|
+
payload?: any;
|
|
275
|
+
error?: string;
|
|
276
|
+
}>;
|
|
277
|
+
/**
|
|
278
|
+
* Legacy methods for backward compatibility
|
|
279
|
+
*/
|
|
280
|
+
static createSignerVerifier(): Promise<{
|
|
281
|
+
signer: (data: string) => Promise<string>;
|
|
282
|
+
verifier: (data: string, signatureBase64url: string) => Promise<boolean>;
|
|
283
|
+
}>;
|
|
284
|
+
static generateKeyPair(): Promise<import("./crypto").KeyPair>;
|
|
285
|
+
/**
|
|
286
|
+
* Clear caches for optimization
|
|
287
|
+
*/
|
|
288
|
+
static clearCaches(): void;
|
|
289
|
+
/**
|
|
290
|
+
* Drop every cache entry holding key material for one DID.
|
|
291
|
+
*
|
|
292
|
+
* 🔴 Scans rather than deletes by exact key, because the caller cannot
|
|
293
|
+
* build the exact keys. Both the instance and signer keys carry a
|
|
294
|
+
* `keyManagerId`, which is private and WeakMap-derived, and this method
|
|
295
|
+
* takes only a DID. The same DID legitimately has one entry per KeyManager
|
|
296
|
+
* that ever resolved it, so anything short of "all of them" leaves a live
|
|
297
|
+
* signer — and a signer closes over a decrypted private key. The maps hold
|
|
298
|
+
* a handful of entries; a linear pass is not worth optimizing away.
|
|
299
|
+
*
|
|
300
|
+
* 🔴 Clears the holder instance too, despite the `Issuer` in the name.
|
|
301
|
+
* The unit being freed is the DID's key material, not a role: a holder
|
|
302
|
+
* instance is constructed with `kbSigner` set to the very same signer
|
|
303
|
+
* object as the issuer's, so evicting the signer while leaving the holder
|
|
304
|
+
* instance cached would keep the decrypted key reachable through the map
|
|
305
|
+
* we claimed to have cleaned. Roles are not separable here; the DID is the
|
|
306
|
+
* only safe granularity.
|
|
307
|
+
*
|
|
308
|
+
* 🔴 Matches on a delimiter, not a bare prefix. `did:key:abc` and
|
|
309
|
+
* `did:key:abcd` are different DIDs, and `startsWith(did)` would take the
|
|
310
|
+
* second one down with the first.
|
|
311
|
+
*/
|
|
312
|
+
static clearIssuerCache(issuerDid: string): void;
|
|
313
|
+
/**
|
|
314
|
+
* Get cache statistics
|
|
315
|
+
*/
|
|
316
|
+
static getCacheStats(): {
|
|
317
|
+
instanceCount: number;
|
|
318
|
+
signerCount: number;
|
|
319
|
+
verifierCount: number;
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Create a verifier function from an external public key
|
|
323
|
+
* This is used for verifying SD-JWTs when you don't have the private key
|
|
324
|
+
* (e.g., API side verifying credentials issued by MCP)
|
|
325
|
+
*/
|
|
326
|
+
private static getVerifierFromPublicKey;
|
|
327
|
+
/**
|
|
328
|
+
* Get SDJwtVcInstance for verification with an external public key
|
|
329
|
+
* Used when verifying credentials without having the issuer's private key
|
|
330
|
+
*/
|
|
331
|
+
private static getVerificationInstance;
|
|
332
|
+
/**
|
|
333
|
+
* Get SDJwtVcInstance for decoding without verification
|
|
334
|
+
*/
|
|
335
|
+
private static getDecodingInstance;
|
|
336
|
+
/**
|
|
337
|
+
* Verify an SD-JWT with an external public key
|
|
338
|
+
* Use this when you have the issuer's public key but not their private key
|
|
339
|
+
*
|
|
340
|
+
* @param credential - The SD-JWT credential string
|
|
341
|
+
* @param publicKey - The issuer's public key (JWK format)
|
|
342
|
+
* @returns Verification result with valid flag and payload
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* const publicKey = extractPublicKeyFromDid(issuerDid)
|
|
347
|
+
* const result = await SDJwtClient.verifyWithExternalKey(credential, publicKey)
|
|
348
|
+
* if (result.valid) {
|
|
349
|
+
* console.log('Verified claims:', result.payload.claims)
|
|
350
|
+
* }
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
static verifyWithExternalKey(credential: string, publicKey: JWK): Promise<{
|
|
354
|
+
valid: boolean;
|
|
355
|
+
payload?: any;
|
|
356
|
+
claims?: any;
|
|
357
|
+
error?: string;
|
|
358
|
+
}>;
|
|
359
|
+
/**
|
|
360
|
+
* Verify an SD-JWT by extracting the issuer's public key from the DID
|
|
361
|
+
* Automatically resolves did:jwk DIDs
|
|
362
|
+
*
|
|
363
|
+
* @param credential - The SD-JWT credential string
|
|
364
|
+
* @returns Verification result with valid flag and payload
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```typescript
|
|
368
|
+
* const result = await SDJwtClient.verifyWithIssuerDid(credential)
|
|
369
|
+
* if (result.valid) {
|
|
370
|
+
* console.log('Issuer:', result.payload.iss)
|
|
371
|
+
* }
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
static verifyWithIssuerDid(credential: string): Promise<{
|
|
375
|
+
valid: boolean;
|
|
376
|
+
payload?: any;
|
|
377
|
+
claims?: any;
|
|
378
|
+
issuerDid?: string;
|
|
379
|
+
error?: string;
|
|
380
|
+
}>;
|
|
381
|
+
/**
|
|
382
|
+
* Decode an SD-JWT without verification
|
|
383
|
+
* Use this when you need to inspect the credential before verification
|
|
384
|
+
* or when you don't have the issuer's public key
|
|
385
|
+
*
|
|
386
|
+
* WARNING: The returned payload has not been verified!
|
|
387
|
+
* Only use this for inspection purposes, not for authorization decisions.
|
|
388
|
+
*
|
|
389
|
+
* @param credential - The SD-JWT credential string
|
|
390
|
+
* @returns Decoded JWT payload, header, and disclosures
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* ```typescript
|
|
394
|
+
* const decoded = await SDJwtClient.decodeWithoutVerification(credential)
|
|
395
|
+
* console.log('Issuer (unverified):', decoded.payload?.iss)
|
|
396
|
+
* console.log('Disclosures:', decoded.disclosures?.length)
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
static decodeWithoutVerification(credential: string): Promise<{
|
|
400
|
+
payload?: any;
|
|
401
|
+
header?: any;
|
|
402
|
+
disclosures?: any[];
|
|
403
|
+
claims?: any;
|
|
404
|
+
error?: string;
|
|
405
|
+
}>;
|
|
406
|
+
/**
|
|
407
|
+
* Extract issuer DID from an SD-JWT without verification
|
|
408
|
+
* Useful for determining the issuer before verification
|
|
409
|
+
*
|
|
410
|
+
* @param credential - The SD-JWT credential string
|
|
411
|
+
* @returns The issuer DID or null if not found
|
|
412
|
+
*/
|
|
413
|
+
static extractIssuerDid(credential: string): string | null;
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=sdjwt-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdjwt-client.d.ts","sourceRoot":"","sources":["../../src/utils/sdjwt-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CredentialType } from '../types';
|
|
2
|
+
export interface DisclosureFields {
|
|
3
|
+
selectiveFields: string[];
|
|
4
|
+
mandatoryFields: string[];
|
|
5
|
+
neverDisclose: string[];
|
|
6
|
+
decoyCount: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get selective disclosure fields for a given credential type.
|
|
10
|
+
* If requestedFields is provided, they are filtered against the neverDisclose list.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getDefaultDisclosureFields(credentialType: CredentialType, requestedFields?: string[]): DisclosureFields;
|
|
13
|
+
//# sourceMappingURL=sdjwt-disclosure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdjwt-disclosure.d.ts","sourceRoot":"","sources":["../../src/utils/sdjwt-disclosure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;CACnB;AAqED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,cAAc,EAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,gBAAgB,CAYlB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { UserTier, TierLimits } from '../types/tier';
|
|
2
|
+
/**
|
|
3
|
+
* Check if a tier limit value represents unlimited.
|
|
4
|
+
* In TIER_LIMITS, -1 is used to represent unlimited values.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isUnlimited(value: number): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Safely resolve a tier string to a valid UserTier, defaulting to 'free'.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveUserTier(tier: string | undefined | null): UserTier;
|
|
11
|
+
/**
|
|
12
|
+
* Get tier limits for a user's tier, with safe fallback to free tier.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getTierLimits(tier: string | undefined | null): TierLimits;
|
|
15
|
+
//# sourceMappingURL=tier-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier-utils.d.ts","sourceRoot":"","sources":["../../src/utils/tier-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAe,MAAM,eAAe,CAAA;AAEjE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,QAAQ,CAKzE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,UAAU,CAEzE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { IssueSDJWTVCRequest, IssueSDJWTVCResult, VerifySDJWTVCResult } from '../types';
|
|
2
|
+
import { KeyManager } from '../did/key-manager';
|
|
3
|
+
/**
|
|
4
|
+
* API-focused VC Manager for server-side operations
|
|
5
|
+
* Provides stateless SD-JWT operations without local persistence
|
|
6
|
+
*/
|
|
7
|
+
export declare class APIVCManager {
|
|
8
|
+
private keyManager;
|
|
9
|
+
/**
|
|
10
|
+
* 🔴 Deliberately does NOT call `SDJwtClient.setKeyManager` — that assigned a
|
|
11
|
+
* static, so constructing one of these repointed every other manager's key
|
|
12
|
+
* resolution. Every call below passes `this.keyManager` instead (#1449).
|
|
13
|
+
*/
|
|
14
|
+
constructor(keyManager?: KeyManager);
|
|
15
|
+
/**
|
|
16
|
+
* Issue an SD-JWT VC with selective disclosure
|
|
17
|
+
*/
|
|
18
|
+
issueSDJWTVC(request: IssueSDJWTVCRequest): Promise<IssueSDJWTVCResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Verify an SD-JWT VC
|
|
21
|
+
*/
|
|
22
|
+
verifySDJWTVC(credential: string): Promise<VerifySDJWTVCResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Issue a project access credential
|
|
25
|
+
*/
|
|
26
|
+
issueProjectAccessCredential(agentDid: string, projectId: string, permissions: string[], issuerDid: string, expirationHours?: number): Promise<IssueSDJWTVCResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Issue a tool access credential
|
|
29
|
+
*/
|
|
30
|
+
issueToolAccessCredential(agentDid: string, toolName: string, actions: string[], projectId: string, issuerDid: string, expirationHours?: number): Promise<IssueSDJWTVCResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Issue a multi-tool access credential
|
|
33
|
+
*/
|
|
34
|
+
issueMultiToolCredential(agentDid: string, toolPermissions: Array<{
|
|
35
|
+
tool: string;
|
|
36
|
+
actions: string[];
|
|
37
|
+
}>, projectId: string, issuerDid: string, expirationHours?: number): Promise<IssueSDJWTVCResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Issue an admin credential
|
|
40
|
+
*/
|
|
41
|
+
issueAdminCredential(agentDid: string, scope: 'project' | 'global', projectId: string | undefined, issuerDid: string, expirationHours?: number): Promise<IssueSDJWTVCResult>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=api-vc-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-vc-manager.d.ts","sourceRoot":"","sources":["../../src/vc/api-vc-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EAEpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAI/C;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAY;IAE9B;;;;OAIG;gBACS,UAAU,CAAC,EAAE,UAAU;IAInC;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgE7E;;OAEG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA6CrE;;OAEG;IACG,4BAA4B,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,EACjB,eAAe,SAAK,GACnB,OAAO,CAAC,kBAAkB,CAAC;IAkB9B;;OAEG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,eAAe,SAAK,GACnB,OAAO,CAAC,kBAAkB,CAAC;IAkB9B;;OAEG;IACG,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAC3D,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,eAAe,SAAK,GACnB,OAAO,CAAC,kBAAkB,CAAC;IAiB9B;;OAEG;IACG,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,GAAG,QAAQ,EAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,SAAS,EAAE,MAAM,EACjB,eAAe,SAAI,GAClB,OAAO,CAAC,kBAAkB,CAAC;CAiB/B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { VCTemplate } from '../types';
|
|
2
|
+
import { KeyManager } from '../did/key-manager';
|
|
3
|
+
import { AgentManager } from '../did/agent';
|
|
4
|
+
import { UserIdentityManager } from '../identity/user-identity-manager';
|
|
5
|
+
export declare class VCManager {
|
|
6
|
+
private keyManager;
|
|
7
|
+
private templates;
|
|
8
|
+
private agentManager;
|
|
9
|
+
private userIdentityManager;
|
|
10
|
+
constructor(keyManager?: KeyManager, agentManager?: AgentManager, userIdentityManager?: UserIdentityManager);
|
|
11
|
+
/**
|
|
12
|
+
* Get fields that should be selectively disclosable based on VC type
|
|
13
|
+
*/
|
|
14
|
+
private getSelectivelyDisclosableFields;
|
|
15
|
+
/**
|
|
16
|
+
* Issue a Verifiable Credential as SD-JWT VC
|
|
17
|
+
* Enhanced to support User/Agent DID separation
|
|
18
|
+
*/
|
|
19
|
+
issue(template: string, claims: any, options: {
|
|
20
|
+
issuerDid?: string;
|
|
21
|
+
subjectDid?: string;
|
|
22
|
+
agentId?: string;
|
|
23
|
+
expiresIn?: string;
|
|
24
|
+
}): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Get subject's public key for cnf claim
|
|
27
|
+
*/
|
|
28
|
+
private getSubjectPublicKey;
|
|
29
|
+
/**
|
|
30
|
+
* Issue using existing Issuer API (OID4VCI)
|
|
31
|
+
*/
|
|
32
|
+
issueViaAPI(credentialType: string, claims: any, options: {
|
|
33
|
+
issuerDid: string;
|
|
34
|
+
subjectDid: string;
|
|
35
|
+
}): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Verify a SD-JWT VC
|
|
38
|
+
*/
|
|
39
|
+
verify(sdjwtVc: string, options?: {
|
|
40
|
+
expectedIssuer?: string;
|
|
41
|
+
expectedSubject?: string;
|
|
42
|
+
requiredClaims?: string[];
|
|
43
|
+
}): Promise<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Revoke a Verifiable Credential
|
|
46
|
+
*/
|
|
47
|
+
revoke(_vcId: string, _issuerDid: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Register a custom VC template
|
|
50
|
+
*/
|
|
51
|
+
registerTemplate(template: VCTemplate): void;
|
|
52
|
+
private registerDefaultTemplates;
|
|
53
|
+
private calculateExpirationDate;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=vc-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vc-manager.d.ts","sourceRoot":"","sources":["../../src/vc/vc-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,UAAU,EAAE,MAAM,UAAU,CAAA;AAEnF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AAGvE,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,mBAAmB,CAAqB;gBAG9C,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE,YAAY,EAC3B,mBAAmB,CAAC,EAAE,mBAAmB;IAiB3C;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAavC;;;OAGG;IACG,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,GACA,OAAO,CAAC,MAAM,CAAC;IAqGlB;;OAEG;YACW,mBAAmB;IAgCjC;;OAEG;IACG,WAAW,CACf,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KACnB,GACA,OAAO,CAAC,MAAM,CAAC;IAoClB;;OAEG;IACG,MAAM,CACV,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;KAC1B,GACA,OAAO,CAAC,GAAG,CAAC;IAgDf;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAI5C,OAAO,CAAC,wBAAwB;IA4BhC,OAAO,CAAC,uBAAuB;CA2BhC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for Key Binding JWT (KB-JWT) issuance shared across
|
|
3
|
+
* the AIdentity stack. Four production code paths build KB-JWTs and they
|
|
4
|
+
* MUST stay byte-for-byte equivalent so a presentation built on one side is
|
|
5
|
+
* accepted by the verifier on the other:
|
|
6
|
+
*
|
|
7
|
+
* - SDK clients via `VPManager.create()` (this package)
|
|
8
|
+
* - API service via `packages/api/src/vp/vp-creation.service.ts`
|
|
9
|
+
* - Remote MCP via `packages/remote-mcp/src/services/vp-creation.service.ts`
|
|
10
|
+
* - agentd (`@vess-id/vess`) via `VPBuilder.buildVP()`
|
|
11
|
+
* (`packages/agentd/src/wallet/vp-builder.ts`)
|
|
12
|
+
*
|
|
13
|
+
* Historically each path had its own copy of this logic. PR #391 (the
|
|
14
|
+
* commit that made `exp` REQUIRED on the verifier side) updated only two of
|
|
15
|
+
* the three issuer paths known at the time; the SDK was missed and every
|
|
16
|
+
* SDK-built VP started failing at verification time. The follow-up
|
|
17
|
+
* consolidation (commit 02b169aa) brought the SDK in line, but agentd —
|
|
18
|
+
* which had its own KB-JWT literal in `wallet/vp-builder.ts` — was not
|
|
19
|
+
* recognized as a fourth issuer. Staging then rejected every VP from
|
|
20
|
+
* `@vess-id/vess` agentd alpha builds with `KB-JWT missing exp` until the
|
|
21
|
+
* agentd hotfix (this commit's cohort) wired its VPBuilder through
|
|
22
|
+
* `buildKbJwtPayload()`. This module exists so that a future verifier
|
|
23
|
+
* change cannot drift from the issuer side: any update lands in one place
|
|
24
|
+
* and all four paths inherit it.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Default KB-JWT lifetime in seconds. Mirrors the cap enforced by the API's
|
|
28
|
+
* `KeyBindingVerifierService.MAX_KB_JWT_LIFETIME_SECONDS` (also 300).
|
|
29
|
+
*
|
|
30
|
+
* The KB-JWT `exp` is the smaller of:
|
|
31
|
+
* - `iat + KB_JWT_DEFAULT_LIFETIME_SECONDS`
|
|
32
|
+
* - the parent VC's `exp` (so the bearer's freshness window cannot outlive
|
|
33
|
+
* the underlying credential's validity, which is itself bounded by
|
|
34
|
+
* `grant.expiresAt` at issuance time).
|
|
35
|
+
*/
|
|
36
|
+
export declare const KB_JWT_DEFAULT_LIFETIME_SECONDS = 300;
|
|
37
|
+
export interface KbJwtPayload {
|
|
38
|
+
iss: string;
|
|
39
|
+
aud: string;
|
|
40
|
+
nonce: string;
|
|
41
|
+
iat: number;
|
|
42
|
+
exp: number;
|
|
43
|
+
}
|
|
44
|
+
export interface BuildKbJwtPayloadArgs {
|
|
45
|
+
/** Holder DID — becomes the KB-JWT `iss` claim. */
|
|
46
|
+
holderDid: string;
|
|
47
|
+
/** Verifier audience (URL or hostname). Will be normalized via {@link normalizeDomain}. */
|
|
48
|
+
audience: string;
|
|
49
|
+
/** Verifier-supplied nonce / challenge. */
|
|
50
|
+
nonce: string;
|
|
51
|
+
/** The parent SD-JWT VC string. Its `exp` (if any) caps the KB-JWT lifetime. */
|
|
52
|
+
vcCredential: string;
|
|
53
|
+
}
|
|
54
|
+
export interface BuildKbJwtPayloadDeps {
|
|
55
|
+
/** Returns the current time in milliseconds. Defaults to `Date.now`. */
|
|
56
|
+
now?: () => number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build a Key Binding JWT payload for an SD-JWT VC presentation.
|
|
60
|
+
*
|
|
61
|
+
* Throws when the parent VC is already expired (`vc.exp <= now`). The error
|
|
62
|
+
* message intentionally contains the substring `"VC has expired"` so that
|
|
63
|
+
* downstream catchers (notably remote-mcp's `isCredentialInvalidError`) can
|
|
64
|
+
* detect a stale-credential condition and trigger a re-approval flow rather
|
|
65
|
+
* than surface an opaque issuance failure to the user.
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildKbJwtPayload(args: BuildKbJwtPayloadArgs, deps?: BuildKbJwtPayloadDeps): KbJwtPayload;
|
|
68
|
+
/**
|
|
69
|
+
* Best-effort read of the VC's `exp` claim from the SD-JWT outer payload.
|
|
70
|
+
* Returns undefined when the VC is malformed, missing exp, or the field is
|
|
71
|
+
* not a number — callers fall back to {@link KB_JWT_DEFAULT_LIFETIME_SECONDS}
|
|
72
|
+
* in that case so issuance does not break for VCs without an explicit expiry.
|
|
73
|
+
*/
|
|
74
|
+
export declare function readVcExpSeconds(sdJwtVc: string): number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Normalize a domain string for consistent use as a JWT `aud` claim.
|
|
77
|
+
*
|
|
78
|
+
* The API verifier compares the KB-JWT `aud` against the expected domain by
|
|
79
|
+
* exact string match, so issuer and verifier must agree on the canonical
|
|
80
|
+
* form. We delegate to the URL parser, which strips paths and lowercases
|
|
81
|
+
* the host, then return the resulting `origin`.
|
|
82
|
+
*
|
|
83
|
+
* Inputs without a scheme are assumed to be hostnames; `localhost` (with or
|
|
84
|
+
* without a port) defaults to `http://`, everything else to `https://`. If
|
|
85
|
+
* URL parsing fails, the input is returned unchanged so a caller can still
|
|
86
|
+
* detect the mismatch downstream rather than silently swallowing a typo.
|
|
87
|
+
*/
|
|
88
|
+
export declare function normalizeDomain(domain: string): string;
|
|
89
|
+
//# sourceMappingURL=kb-jwt-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-jwt-builder.d.ts","sourceRoot":"","sources":["../../src/vp/kb-jwt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,qBAAqB,EAC3B,IAAI,GAAE,qBAA0B,GAC/B,YAAY,CAqBd;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAgBtD"}
|