@kubun/service-credential-api 0.17.3 → 0.18.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/lib/adapter.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Client } from '@enkaku/client';
2
- import type { AliasBindingCredentialProvider, CredentialProvider, EntryPairedCredentialProvider, ProviderAccount } from '@kubun/credential-types';
2
+ import type { AdoptGrantAPI, AliasBindingCredentialProvider, CredentialProvider, EntryPairedCredentialProvider, ProviderAccount, VersionedEntryCredentialProvider } from '@kubun/credential-types';
3
3
  import type { CredentialServiceProtocol } from './index.js';
4
4
  /**
5
5
  * What a storage-only account peek discloses: the provider account and the
@@ -22,4 +22,4 @@ export type CredentialProviderWithProvenance = CredentialProvider & {
22
22
  writerDID: string | null;
23
23
  } | null>;
24
24
  };
25
- export declare function toCredentialProvider(client: Client<CredentialServiceProtocol>): CredentialProviderWithProvenance & AliasBindingCredentialProvider & EntryPairedCredentialProvider & Required<Pick<CredentialProviderWithProvenance, 'peekAccount'>>;
25
+ export declare function toCredentialProvider(client: Client<CredentialServiceProtocol>): CredentialProviderWithProvenance & AliasBindingCredentialProvider & EntryPairedCredentialProvider & VersionedEntryCredentialProvider & AdoptGrantAPI & Required<Pick<CredentialProviderWithProvenance, 'peekAccount'>>;
package/lib/adapter.js CHANGED
@@ -6,7 +6,8 @@
6
6
  import { RequestError } from '@enkaku/client';
7
7
  import { ErrorCodes } from '@enkaku/protocol';
8
8
  import { deserializeCredential, serializeCredential } from '@kubun/credential';
9
- import { CredentialPeekUnsupportedError } from './errors.js';
9
+ import { CredentialUpdateUnavailableError } from '@kubun/credential-types';
10
+ import { CredentialPeekUnsupportedError, CredentialUnexpectedSupersededError } from './errors.js';
10
11
  export function toCredentialProvider(client) {
11
12
  return {
12
13
  async get (providerName, ownerDID) {
@@ -30,8 +31,58 @@ export function toCredentialProvider(client) {
30
31
  entryID: ref.entryID
31
32
  };
32
33
  },
33
- setCredentialForEntry ({ providerName, ownerDID, entryID, credential }) {
34
+ async getVersionedCredentialRef (providerName, ownerDID) {
35
+ const ref = await client.request('credential/get-ref', {
36
+ param: {
37
+ providerName,
38
+ ownerDID
39
+ }
40
+ });
41
+ return ref == null ? null : {
42
+ credential: deserializeCredential(ref.credential),
43
+ entryID: ref.entryID,
44
+ ...ref.version == null ? {} : {
45
+ version: ref.version
46
+ }
47
+ };
48
+ },
49
+ setCredentialForEntryIfUnchanged ({ providerName, ownerDID, entryID, credential, expectedVersion }) {
34
50
  return client.request('credential/refresh-entry', {
51
+ param: {
52
+ providerName,
53
+ ownerDID,
54
+ entryID,
55
+ credential: serializeCredential(credential),
56
+ expectedVersion
57
+ }
58
+ });
59
+ },
60
+ async update (address, change) {
61
+ for(;;){
62
+ const ref = await client.request('credential/get-ref', {
63
+ param: {
64
+ providerName: address.providerName,
65
+ ownerDID: address.ownerDID,
66
+ deviceDID: address.deviceDID
67
+ }
68
+ });
69
+ if (ref == null || ref.version == null) throw new CredentialUpdateUnavailableError();
70
+ const result = await client.request('credential/refresh-entry', {
71
+ param: {
72
+ providerName: address.providerName,
73
+ ownerDID: address.ownerDID,
74
+ deviceDID: address.deviceDID,
75
+ entryID: ref.entryID,
76
+ credential: serializeCredential(change(deserializeCredential(ref.credential))),
77
+ expectedVersion: ref.version
78
+ }
79
+ });
80
+ if (result === 'updated') return;
81
+ if (result === 'absent') throw new CredentialUpdateUnavailableError();
82
+ }
83
+ },
84
+ async setCredentialForEntry ({ providerName, ownerDID, entryID, credential }) {
85
+ const result = await client.request('credential/refresh-entry', {
35
86
  param: {
36
87
  providerName,
37
88
  ownerDID,
@@ -39,6 +90,8 @@ export function toCredentialProvider(client) {
39
90
  credential: serializeCredential(credential)
40
91
  }
41
92
  });
93
+ if (result === 'superseded') throw new CredentialUnexpectedSupersededError();
94
+ return result;
42
95
  },
43
96
  async peekAccount (providerName, ownerDID) {
44
97
  let peeked;
@@ -119,6 +172,11 @@ export function toCredentialProvider(client) {
119
172
  entryID
120
173
  }
121
174
  });
175
+ },
176
+ async adoptCredentialGrant (params) {
177
+ await client.request('credential/adopt-grant', {
178
+ param: params
179
+ });
122
180
  }
123
181
  };
124
182
  }
package/lib/errors.d.ts CHANGED
@@ -16,3 +16,10 @@ export declare class CredentialPeekUnsupportedError extends Error {
16
16
  constructor(options?: ErrorOptions);
17
17
  get code(): typeof CREDENTIAL_PEEK_UNSUPPORTED;
18
18
  }
19
+ /** An unconditional entry write received a result reserved for versioned writes. */
20
+ export declare const CREDENTIAL_UNEXPECTED_SUPERSEDED = "CREDENTIAL_UNEXPECTED_SUPERSEDED";
21
+ export declare class CredentialUnexpectedSupersededError extends Error {
22
+ #private;
23
+ constructor();
24
+ get code(): typeof CREDENTIAL_UNEXPECTED_SUPERSEDED;
25
+ }
package/lib/errors.js CHANGED
@@ -20,3 +20,15 @@
20
20
  return this.#code;
21
21
  }
22
22
  }
23
+ /** An unconditional entry write received a result reserved for versioned writes. */ export const CREDENTIAL_UNEXPECTED_SUPERSEDED = 'CREDENTIAL_UNEXPECTED_SUPERSEDED';
24
+ export class CredentialUnexpectedSupersededError extends Error {
25
+ #code;
26
+ constructor(){
27
+ super('The credential service superseded an unconditional entry write');
28
+ this.name = 'CredentialUnexpectedSupersededError';
29
+ this.#code = CREDENTIAL_UNEXPECTED_SUPERSEDED;
30
+ }
31
+ get code() {
32
+ return this.#code;
33
+ }
34
+ }
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { type CredentialAccountPeek, type CredentialProviderWithProvenance, toCredentialProvider, } from './adapter.js';
2
- export { CREDENTIAL_PEEK_UNSUPPORTED, CredentialPeekUnsupportedError } from './errors.js';
2
+ export { CREDENTIAL_PEEK_UNSUPPORTED, CREDENTIAL_UNEXPECTED_SUPERSEDED, CredentialPeekUnsupportedError, CredentialUnexpectedSupersededError, } from './errors.js';
3
3
  export declare const credentialServiceProtocol: {
4
4
  readonly 'credential/get': {
5
5
  readonly type: "request";
@@ -35,6 +35,9 @@ export declare const credentialServiceProtocol: {
35
35
  readonly ownerDID: {
36
36
  readonly type: "string";
37
37
  };
38
+ readonly deviceDID: {
39
+ readonly type: "string";
40
+ };
38
41
  };
39
42
  readonly required: readonly ["providerName", "ownerDID"];
40
43
  readonly additionalProperties: false;
@@ -49,6 +52,9 @@ export declare const credentialServiceProtocol: {
49
52
  readonly entryID: {
50
53
  readonly type: "string";
51
54
  };
55
+ readonly version: {
56
+ readonly type: "string";
57
+ };
52
58
  };
53
59
  readonly required: readonly ["credential", "entryID"];
54
60
  readonly additionalProperties: false;
@@ -209,19 +215,60 @@ export declare const credentialServiceProtocol: {
209
215
  readonly ownerDID: {
210
216
  readonly type: "string";
211
217
  };
218
+ readonly deviceDID: {
219
+ readonly type: "string";
220
+ };
212
221
  readonly entryID: {
213
222
  readonly type: "string";
214
223
  };
215
224
  readonly credential: {
216
225
  readonly type: "string";
217
226
  };
227
+ readonly expectedVersion: {
228
+ readonly type: "string";
229
+ };
218
230
  };
219
231
  readonly required: readonly ["providerName", "ownerDID", "entryID", "credential"];
220
232
  readonly additionalProperties: false;
221
233
  };
222
234
  readonly result: {
223
235
  readonly type: "string";
224
- readonly enum: readonly ["updated", "absent"];
236
+ readonly enum: readonly ["updated", "absent", "superseded"];
237
+ };
238
+ };
239
+ readonly 'credential/adopt-grant': {
240
+ readonly type: "request";
241
+ readonly param: {
242
+ readonly type: "object";
243
+ readonly properties: {
244
+ readonly providerName: {
245
+ readonly type: "string";
246
+ };
247
+ readonly ownerDID: {
248
+ readonly type: "string";
249
+ };
250
+ readonly fromDeviceDID: {
251
+ readonly type: "string";
252
+ };
253
+ readonly toDeviceDID: {
254
+ readonly type: "string";
255
+ };
256
+ readonly sourceKeyOwnerDID: {
257
+ readonly type: "string";
258
+ };
259
+ };
260
+ readonly required: readonly ["providerName", "ownerDID", "fromDeviceDID", "toDeviceDID"];
261
+ readonly additionalProperties: false;
262
+ };
263
+ readonly result: {
264
+ readonly type: "object";
265
+ readonly properties: {
266
+ readonly adopted: {
267
+ readonly type: "boolean";
268
+ };
269
+ };
270
+ readonly required: readonly ["adopted"];
271
+ readonly additionalProperties: false;
225
272
  };
226
273
  };
227
274
  readonly 'credential/delete': {
package/lib/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // authenticated client into the `credential-provider` the connector registers, so
6
6
  // this package is no longer type-only.
7
7
  export { toCredentialProvider } from './adapter.js';
8
- export { CREDENTIAL_PEEK_UNSUPPORTED, CredentialPeekUnsupportedError } from './errors.js';
8
+ export { CREDENTIAL_PEEK_UNSUPPORTED, CREDENTIAL_UNEXPECTED_SUPERSEDED, CredentialPeekUnsupportedError, CredentialUnexpectedSupersededError } from './errors.js';
9
9
  // Param↔seam mapping. `providerName`/`ownerDID` are the alias key the seam
10
10
  // resolves. `ownerDID` is ALSO the authorization subject: each handler passes it
11
11
  // to `context.authorize(ownerDID)` (the per-serve `callerMayActFor`), NOT the
@@ -54,6 +54,9 @@ export const credentialServiceProtocol = {
54
54
  },
55
55
  ownerDID: {
56
56
  type: 'string'
57
+ },
58
+ deviceDID: {
59
+ type: 'string'
57
60
  }
58
61
  },
59
62
  required: [
@@ -72,6 +75,9 @@ export const credentialServiceProtocol = {
72
75
  },
73
76
  entryID: {
74
77
  type: 'string'
78
+ },
79
+ version: {
80
+ type: 'string'
75
81
  }
76
82
  },
77
83
  required: [
@@ -288,11 +294,17 @@ export const credentialServiceProtocol = {
288
294
  ownerDID: {
289
295
  type: 'string'
290
296
  },
297
+ deviceDID: {
298
+ type: 'string'
299
+ },
291
300
  entryID: {
292
301
  type: 'string'
293
302
  },
294
303
  credential: {
295
304
  type: 'string'
305
+ },
306
+ expectedVersion: {
307
+ type: 'string'
296
308
  }
297
309
  },
298
310
  required: [
@@ -307,10 +319,53 @@ export const credentialServiceProtocol = {
307
319
  type: 'string',
308
320
  enum: [
309
321
  'updated',
310
- 'absent'
322
+ 'absent',
323
+ 'superseded'
311
324
  ]
312
325
  }
313
326
  },
327
+ 'credential/adopt-grant': {
328
+ type: 'request',
329
+ param: {
330
+ type: 'object',
331
+ properties: {
332
+ providerName: {
333
+ type: 'string'
334
+ },
335
+ ownerDID: {
336
+ type: 'string'
337
+ },
338
+ fromDeviceDID: {
339
+ type: 'string'
340
+ },
341
+ toDeviceDID: {
342
+ type: 'string'
343
+ },
344
+ sourceKeyOwnerDID: {
345
+ type: 'string'
346
+ }
347
+ },
348
+ required: [
349
+ 'providerName',
350
+ 'ownerDID',
351
+ 'fromDeviceDID',
352
+ 'toDeviceDID'
353
+ ],
354
+ additionalProperties: false
355
+ },
356
+ result: {
357
+ type: 'object',
358
+ properties: {
359
+ adopted: {
360
+ type: 'boolean'
361
+ }
362
+ },
363
+ required: [
364
+ 'adopted'
365
+ ],
366
+ additionalProperties: false
367
+ }
368
+ },
314
369
  'credential/delete': {
315
370
  type: 'request',
316
371
  param: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/service-credential-api",
3
- "version": "0.17.3",
3
+ "version": "0.18.0",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -15,10 +15,10 @@
15
15
  "LICENSE.md"
16
16
  ],
17
17
  "dependencies": {
18
- "@enkaku/client": "^0.21.2",
19
- "@enkaku/protocol": "^0.21.1",
20
- "@kubun/credential": "^0.17.4",
21
- "@kubun/credential-types": "^0.17.2"
18
+ "@enkaku/client": "^0.21.5",
19
+ "@enkaku/protocol": "^0.21.5",
20
+ "@kubun/credential": "^0.18.0",
21
+ "@kubun/credential-types": "^0.18.0"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"