@ixo/ucan 1.1.0 → 1.2.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/.turbo/turbo-build.log +1 -1
- package/README.md +72 -11
- package/dist/client/create-client.d.ts +4 -2
- package/dist/client/create-client.d.ts.map +1 -1
- package/dist/client/create-client.js +2 -0
- package/dist/client/create-client.js.map +1 -1
- package/dist/did/web-resolver.d.ts +7 -0
- package/dist/did/web-resolver.d.ts.map +1 -0
- package/dist/did/web-resolver.js +78 -0
- package/dist/did/web-resolver.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/validator/validator.d.ts +2 -0
- package/dist/validator/validator.d.ts.map +1 -1
- package/dist/validator/validator.js +152 -6
- package/dist/validator/validator.js.map +1 -1
- package/package.json +18 -7
- package/src/client/create-client.ts +8 -1
- package/src/did/web-resolver.ts +140 -0
- package/src/index.ts +6 -0
- package/src/validator/validator.test.ts +502 -0
- package/src/validator/validator.ts +253 -12
package/.turbo/turbo-build.log
CHANGED
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ UCAN is a decentralized authorization system using cryptographically signed toke
|
|
|
11
11
|
- **Capabilities**: What actions can be performed on which resources
|
|
12
12
|
- **Delegations**: Granting capabilities to others (can be chained)
|
|
13
13
|
- **Invocations**: Requests to use a capability
|
|
14
|
+
- **Facts**: Verifiable claims attached to a delegation or invocation (scoped per-UCAN, not inherited)
|
|
14
15
|
- **Attenuation**: Permissions can only be narrowed, never expanded
|
|
15
16
|
|
|
16
17
|
📖 **[See the visual flow diagram →](./docs/FLOW.md)**
|
|
@@ -73,7 +74,7 @@ const validator = await createUCANValidator({
|
|
|
73
74
|
});
|
|
74
75
|
```
|
|
75
76
|
|
|
76
|
-
### 3. Protect a Route
|
|
77
|
+
### 3. Protect a Route (Invocation)
|
|
77
78
|
|
|
78
79
|
```typescript
|
|
79
80
|
app.post('/employees', async (req, res) => {
|
|
@@ -91,12 +92,44 @@ app.post('/employees', async (req, res) => {
|
|
|
91
92
|
// result.capability — validated capability with caveats (nb)
|
|
92
93
|
// result.expiration — earliest expiration across the delegation chain (undefined = never)
|
|
93
94
|
// result.proofChain — delegation path from root to invoker, e.g. ["did:key:root", "did:key:user"]
|
|
95
|
+
// result.facts — facts attached to the invocation (undefined if none)
|
|
94
96
|
|
|
95
97
|
const limit = result.capability?.nb?.limit ?? 10;
|
|
96
98
|
res.json({ employees: getEmployees(limit) });
|
|
97
99
|
});
|
|
98
100
|
```
|
|
99
101
|
|
|
102
|
+
### 3b. Validate a Delegation
|
|
103
|
+
|
|
104
|
+
Use `validateDelegation()` to verify a standalone delegation token — e.g. when a client sends a delegation in a header alongside a traditional auth mechanism. This verifies the cryptographic signature chain, audience, and expiration without requiring a capability definition.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
app.use(async (req, res, next) => {
|
|
108
|
+
const delegationHeader = req.headers['x-ucan-delegation'];
|
|
109
|
+
if (!delegationHeader) return next();
|
|
110
|
+
|
|
111
|
+
const result = await validator.validateDelegation(delegationHeader);
|
|
112
|
+
|
|
113
|
+
if (!result.ok) {
|
|
114
|
+
console.warn(`Delegation invalid: [${result.error?.code}] ${result.error?.message}`);
|
|
115
|
+
return next();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// result.invoker — issuer DID (who granted the delegation)
|
|
119
|
+
// result.capability — first capability in the delegation
|
|
120
|
+
// result.expiration — effective expiration across the proof chain
|
|
121
|
+
// result.proofChain — e.g. ["did:ixo:root", "did:ixo:user"]
|
|
122
|
+
|
|
123
|
+
req.ucanDelegation = {
|
|
124
|
+
issuer: result.invoker,
|
|
125
|
+
capability: result.capability,
|
|
126
|
+
expiration: result.expiration,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
next();
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
100
133
|
### 4. Create & Use a Delegation (Client)
|
|
101
134
|
|
|
102
135
|
```typescript
|
|
@@ -181,18 +214,30 @@ Create a framework-agnostic validator.
|
|
|
181
214
|
| `didResolver` | `DIDKeyResolver` | Resolver for non-`did:key` DIDs |
|
|
182
215
|
| `invocationStore` | `InvocationStore` | Custom store for replay protection |
|
|
183
216
|
|
|
217
|
+
#### Methods
|
|
218
|
+
|
|
219
|
+
| Method | Description |
|
|
220
|
+
| ------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
221
|
+
| `validate(invocationBase64, capabilityDef, resource)` | Validate an invocation against a capability definition |
|
|
222
|
+
| `validateDelegation(delegationBase64)` | Validate a standalone delegation (signature, audience, chain) |
|
|
223
|
+
|
|
224
|
+
**`validate()`** validates a full invocation — checks signature, capability matching, caveats, replay protection, and resource authorization.
|
|
225
|
+
|
|
226
|
+
**`validateDelegation()`** validates a standalone delegation token — verifies the cryptographic signature of every delegation in the proof chain, checks audience matches `serverDid`, validates expiration, and ensures chain consistency (each proof's audience matches the child delegation's issuer). Supports `did:key` issuers natively and non-`did:key` issuers (e.g. `did:ixo`) via the configured `didResolver`.
|
|
227
|
+
|
|
184
228
|
#### `ValidateResult`
|
|
185
229
|
|
|
186
|
-
|
|
230
|
+
Both methods return a `ValidateResult`:
|
|
187
231
|
|
|
188
|
-
| Field | Type
|
|
189
|
-
| ------------ |
|
|
190
|
-
| `ok` | `boolean`
|
|
191
|
-
| `invoker` | `string`
|
|
192
|
-
| `capability` | `object`
|
|
193
|
-
| `expiration` | `number \| undefined`
|
|
194
|
-
| `proofChain` | `string[] \| undefined`
|
|
195
|
-
| `
|
|
232
|
+
| Field | Type | Description |
|
|
233
|
+
| ------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
234
|
+
| `ok` | `boolean` | Whether validation succeeded |
|
|
235
|
+
| `invoker` | `string` | DID of the invoker/issuer (on success) |
|
|
236
|
+
| `capability` | `object` | Validated capability with `can`, `with`, and optional `nb` caveats (on success) |
|
|
237
|
+
| `expiration` | `number \| undefined` | Effective expiration (Unix seconds) — the earliest across the delegation chain. Undefined = never. |
|
|
238
|
+
| `proofChain` | `string[] \| undefined` | Delegation path from root issuer to invoker, e.g. `["did:key:root", "did:key:alice", "did:key:bob"]` |
|
|
239
|
+
| `facts` | `Record<string, unknown>[] \| undefined` | Facts attached to the invocation/delegation. Undefined if none. |
|
|
240
|
+
| `error` | `object` | Error with `code` and `message` (on failure) |
|
|
196
241
|
|
|
197
242
|
Error codes: `INVALID_FORMAT`, `INVALID_SIGNATURE`, `UNAUTHORIZED`, `REPLAY`, `EXPIRED`, `CAVEAT_VIOLATION`.
|
|
198
243
|
|
|
@@ -211,6 +256,22 @@ Error codes: `INVALID_FORMAT`, `INVALID_SIGNATURE`, `UNAUTHORIZED`, `REPLAY`, `E
|
|
|
211
256
|
|
|
212
257
|
> **Note:** Both `createDelegation` and `createInvocation` default to `expiration: Infinity` (never expires) when no expiration is specified. Pass an explicit Unix timestamp (seconds) to set an expiration.
|
|
213
258
|
|
|
259
|
+
#### Facts
|
|
260
|
+
|
|
261
|
+
Both `createDelegation` and `createInvocation` accept an optional `facts` parameter — an array of `Record<string, unknown>` objects representing verifiable claims or proofs of knowledge ([UCAN spec §3.2.4](https://github.com/ucan-wg/spec/#324-facts)).
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
const invocation = await createInvocation({
|
|
265
|
+
issuer: signer,
|
|
266
|
+
audience: serverDid,
|
|
267
|
+
capability: { can: 'oracle/call', with: 'ixo:oracle:123' },
|
|
268
|
+
proofs: [delegation],
|
|
269
|
+
facts: [{ requestId: 'abc-123', origin: 'portal' }],
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
> **Important:** Facts are scoped per-UCAN. Each delegation and invocation carries its own independent `fct` field. Facts on a delegation do **not** propagate to invocations that use it as a proof. The `facts` field in `ValidateResult` contains only the facts from the invocation itself.
|
|
274
|
+
|
|
214
275
|
### DID Resolution
|
|
215
276
|
|
|
216
277
|
```typescript
|
|
@@ -274,7 +335,7 @@ pnpm test # Run unit tests (vitest)
|
|
|
274
335
|
pnpm test:ucan # Run interactive test script with full UCAN flow
|
|
275
336
|
```
|
|
276
337
|
|
|
277
|
-
The unit tests cover proof chain construction, expiration computation, validation failures, caveat enforcement, and
|
|
338
|
+
The unit tests cover proof chain construction, expiration computation, facts pass-through, validation failures, caveat enforcement, replay protection, and delegation validation (signature verification, audience checks, expiration, tampered signatures, proof chain consistency, and `did:ixo` support).
|
|
278
339
|
|
|
279
340
|
## License
|
|
280
341
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Client from '@ucanto/client';
|
|
2
|
-
import type { Signer, Delegation, Capability } from '@ucanto/interface';
|
|
2
|
+
import type { Signer, Delegation, Capability, Fact } from '@ucanto/interface';
|
|
3
3
|
import type { SupportedDID } from '../types.js';
|
|
4
4
|
export declare function generateKeypair(): Promise<{
|
|
5
5
|
signer: Signer;
|
|
@@ -19,6 +19,7 @@ export declare function createDelegation(options: {
|
|
|
19
19
|
expiration?: number;
|
|
20
20
|
notBefore?: number;
|
|
21
21
|
proofs?: Delegation[];
|
|
22
|
+
facts?: Fact[];
|
|
22
23
|
}): Promise<Delegation>;
|
|
23
24
|
export declare function createInvocation(options: {
|
|
24
25
|
issuer: Signer;
|
|
@@ -26,9 +27,10 @@ export declare function createInvocation(options: {
|
|
|
26
27
|
capability: Capability;
|
|
27
28
|
proofs?: Delegation[];
|
|
28
29
|
expiration?: number;
|
|
30
|
+
facts?: Fact[];
|
|
29
31
|
}): Promise<Client.IssuedInvocationView<Client.Capability<Client.Ability, `${string}:${string}`, unknown>>>;
|
|
30
32
|
export declare function serializeInvocation(invocation: Awaited<ReturnType<typeof createInvocation>>): Promise<string>;
|
|
31
33
|
export declare function serializeDelegation(delegation: Delegation): Promise<string>;
|
|
32
34
|
export declare function parseDelegation(serialized: string): Promise<Delegation>;
|
|
33
|
-
export type { Signer, Delegation, Capability };
|
|
35
|
+
export type { Signer, Delegation, Capability, Fact };
|
|
34
36
|
//# sourceMappingURL=create-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,UAAU,
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,UAAU,EAEV,IAAI,EACL,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmChD,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAOD;AASD,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,MAAM,CAM1E;AAqBD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAuDD;AA2BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAE9C,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,UAAU,EAAE,CAAC;IAE3B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,UAAU,CAAC,CActB;AA6BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAE9C,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,EAAE,UAAU,CAAC;IAEvB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;CAChB,2GAYA;AAQD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,GACvD,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAQD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,CAejB;AAQD,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB7E;AAGD,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC"}
|
|
@@ -59,6 +59,7 @@ export async function createDelegation(options) {
|
|
|
59
59
|
expiration: options.expiration ?? Infinity,
|
|
60
60
|
proofs: options.proofs,
|
|
61
61
|
notBefore: options.notBefore,
|
|
62
|
+
facts: options.facts,
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
export async function createInvocation(options) {
|
|
@@ -69,6 +70,7 @@ export async function createInvocation(options) {
|
|
|
69
70
|
capability: options.capability,
|
|
70
71
|
proofs: options.proofs ?? [],
|
|
71
72
|
expiration: options.expiration ?? Infinity,
|
|
73
|
+
facts: options.facts,
|
|
72
74
|
});
|
|
73
75
|
}
|
|
74
76
|
export async function serializeInvocation(invocation) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DIDKeyResolver } from '../types.js';
|
|
2
|
+
export interface WebDIDResolverConfig {
|
|
3
|
+
fetch?: typeof globalThis.fetch;
|
|
4
|
+
fallbackToHttp?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function createWebDIDResolver(config?: WebDIDResolverConfig): DIDKeyResolver;
|
|
7
|
+
//# sourceMappingURL=web-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-resolver.d.ts","sourceRoot":"","sources":["../../src/did/web-resolver.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAU,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAEhC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAwBD,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,oBAAoB,GAC5B,cAAc,CAiGhB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function createWebDIDResolver(config) {
|
|
2
|
+
const fetchFn = config?.fetch ?? globalThis.fetch;
|
|
3
|
+
return async (did) => {
|
|
4
|
+
if (!did.startsWith('did:web:')) {
|
|
5
|
+
return {
|
|
6
|
+
error: {
|
|
7
|
+
name: 'DIDKeyResolutionError',
|
|
8
|
+
did,
|
|
9
|
+
message: `Cannot resolve ${did}: not a did:web identifier`,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const parts = did.slice('did:web:'.length).split(':');
|
|
15
|
+
const domain = decodeURIComponent(parts[0]);
|
|
16
|
+
const pathSegments = parts.slice(1).map(decodeURIComponent);
|
|
17
|
+
const path = pathSegments.length > 0
|
|
18
|
+
? `/${pathSegments.join('/')}/did.json`
|
|
19
|
+
: '/.well-known/did.json';
|
|
20
|
+
const httpsUrl = `https://${domain}${path}`;
|
|
21
|
+
let response = null;
|
|
22
|
+
let fetchUrl = httpsUrl;
|
|
23
|
+
try {
|
|
24
|
+
response = await fetchFn(httpsUrl);
|
|
25
|
+
}
|
|
26
|
+
catch (httpsError) {
|
|
27
|
+
if (config?.fallbackToHttp) {
|
|
28
|
+
fetchUrl = `http://${domain}${path}`;
|
|
29
|
+
response = await fetchFn(fetchUrl);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw httpsError;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!response.ok && config?.fallbackToHttp && fetchUrl === httpsUrl) {
|
|
36
|
+
fetchUrl = `http://${domain}${path}`;
|
|
37
|
+
response = await fetchFn(fetchUrl);
|
|
38
|
+
}
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
return {
|
|
41
|
+
error: {
|
|
42
|
+
name: 'DIDKeyResolutionError',
|
|
43
|
+
did,
|
|
44
|
+
message: `Failed to fetch DID document from ${fetchUrl}: HTTP ${response.status}`,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const doc = (await response.json());
|
|
49
|
+
const keys = [];
|
|
50
|
+
for (const vm of doc.verificationMethod ?? []) {
|
|
51
|
+
if (vm.type.includes('Ed25519') &&
|
|
52
|
+
vm.publicKeyMultibase?.startsWith('z')) {
|
|
53
|
+
keys.push(`did:key:${vm.publicKeyMultibase}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (keys.length === 0) {
|
|
57
|
+
return {
|
|
58
|
+
error: {
|
|
59
|
+
name: 'DIDKeyResolutionError',
|
|
60
|
+
did,
|
|
61
|
+
message: `No valid Ed25519 verification methods found in DID document for ${did}`,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { ok: keys };
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
return {
|
|
69
|
+
error: {
|
|
70
|
+
name: 'DIDKeyResolutionError',
|
|
71
|
+
did,
|
|
72
|
+
message: `Failed to resolve ${did}: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=web-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-resolver.js","sourceRoot":"","sources":["../../src/did/web-resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,9 @@ export { ed25519, Verifier } from '@ucanto/principal';
|
|
|
6
6
|
export type { IxoDID, KeyDID, SupportedDID, DIDKeyResolutionResult, DIDKeyResolver, InvocationStore, ValidationResult, SerializedInvocation, } from './types.js';
|
|
7
7
|
export { defineCapability, Schema, type DefineCapabilityOptions, } from './capabilities/capability.js';
|
|
8
8
|
export { createUCANValidator, type CreateValidatorOptions, type ValidateResult, type UCANValidator, } from './validator/validator.js';
|
|
9
|
-
export { generateKeypair, parseSigner, signerFromMnemonic, createDelegation, createInvocation, serializeInvocation, serializeDelegation, parseDelegation, type Signer, type Delegation, type Capability, } from './client/create-client.js';
|
|
9
|
+
export { generateKeypair, parseSigner, signerFromMnemonic, createDelegation, createInvocation, serializeInvocation, serializeDelegation, parseDelegation, type Signer, type Delegation, type Capability, type Fact, } from './client/create-client.js';
|
|
10
10
|
export { createIxoDIDResolver, createCompositeDIDResolver, type IxoDIDResolverConfig, } from './did/ixo-resolver.js';
|
|
11
|
+
export { createWebDIDResolver, type WebDIDResolverConfig, } from './did/web-resolver.js';
|
|
11
12
|
export { InMemoryInvocationStore, createInvocationStore, } from './store/memory.js';
|
|
12
13
|
export declare const VERSION = "1.0.0";
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAMtD,YAAY,EACV,MAAM,EACN,MAAM,EACN,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAMpB,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,KAAK,uBAAuB,GAC7B,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,0BAA0B,CAAC;AAMlC,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAMtD,YAAY,EACV,MAAM,EACN,MAAM,EACN,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAMpB,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,KAAK,uBAAuB,GAC7B,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,0BAA0B,CAAC;AAMlC,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,IAAI,GACV,MAAM,2BAA2B,CAAC;AAMnC,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,oBAAoB,EACpB,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAM3B,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { defineCapability, Schema, } from './capabilities/capability.js';
|
|
|
7
7
|
export { createUCANValidator, } from './validator/validator.js';
|
|
8
8
|
export { generateKeypair, parseSigner, signerFromMnemonic, createDelegation, createInvocation, serializeInvocation, serializeDelegation, parseDelegation, } from './client/create-client.js';
|
|
9
9
|
export { createIxoDIDResolver, createCompositeDIDResolver, } from './did/ixo-resolver.js';
|
|
10
|
+
export { createWebDIDResolver, } from './did/web-resolver.js';
|
|
10
11
|
export { InMemoryInvocationStore, createInvocationStore, } from './store/memory.js';
|
|
11
12
|
export const VERSION = '1.0.0';
|
|
12
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAqBtD,OAAO,EACL,gBAAgB,EAChB,MAAM,GAEP,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACL,mBAAmB,GAIpB,MAAM,0BAA0B,CAAC;AAMlC,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAqBtD,OAAO,EACL,gBAAgB,EAChB,MAAM,GAEP,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACL,mBAAmB,GAIpB,MAAM,0BAA0B,CAAC;AAMlC,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,GAKhB,MAAM,2BAA2B,CAAC;AAMnC,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAE3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,oBAAoB,GAErB,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAM3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|