@kubun/plugin-credential 0.17.5 → 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/context.d.ts CHANGED
@@ -58,12 +58,12 @@ export type PutCredentialEntryInput = {
58
58
  };
59
59
  export type CredentialQueryContext = {
60
60
  getKey(keyID: string): Promise<CredentialKeyResult>;
61
- getEntry(entryID: string): Promise<CredentialEntryResult>;
61
+ getEntry(entryID: string, ownerDID: string): Promise<CredentialEntryResult>;
62
62
  listEntries(keyID: string): Promise<Array<string>>;
63
63
  putKey(input: PutCredentialKeyInput): Promise<CredentialKeyResult>;
64
64
  putEntry(input: PutCredentialEntryInput): Promise<CredentialEntryResult>;
65
65
  deleteKey(keyID: string): Promise<boolean>;
66
- deleteEntry(entryID: string): Promise<boolean>;
66
+ deleteEntry(entryID: string, ownerDID: string): Promise<boolean>;
67
67
  };
68
68
  export declare function createCredentialQueryContext(params: {
69
69
  getStore: () => Promise<CredentialStoreAPI>;
package/lib/context.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { normalizeDID } from '@kokuin/token';
1
2
  import { entryProvenanceFields } from '@kubun/credential';
2
3
  import { HLC } from '@kubun/hlc';
3
4
  import { CredentialEntryID, CredentialKeyID } from '@kubun/id';
@@ -69,7 +70,7 @@ export function createCredentialQueryContext(params) {
69
70
  return await requireAuthorized(store, await store.getKey(keyID), keyID, authorization);
70
71
  }
71
72
  async function keyResult(store, key) {
72
- const wrappings = await store.listWrappings(key.key_id);
73
+ const wrappings = await store.listWrappings(key.key_id, undefined, key.owner_did);
73
74
  return {
74
75
  keyID: key.key_id,
75
76
  ownerDID: key.owner_did,
@@ -86,15 +87,15 @@ export function createCredentialQueryContext(params) {
86
87
  const store = await getStore();
87
88
  return await keyResult(store, await loadKey(store, keyID, 'read'));
88
89
  },
89
- async getEntry (entryID) {
90
+ async getEntry (entryID, ownerDID) {
90
91
  const store = await getStore();
91
- const entry = await store.getEntryWithProvenance(entryID);
92
+ const entry = await store.getEntryWithProvenance(entryID, normalizeDID(ownerDID));
92
93
  if (entry == null) {
93
94
  throw notFound('Credential entry', entryID);
94
95
  }
95
96
  // An entry carries no authorization of its own. Its key does, and that is
96
97
  // the only thing that decides who may read the ciphertext.
97
- await loadKey(store, entry.key_id, 'read');
98
+ await requireAuthorized(store, await store.getKey(entry.key_id, entry.owner_did), entry.key_id, 'read');
98
99
  return toEntryResult(entry);
99
100
  },
100
101
  async listEntries (keyID) {
@@ -133,7 +134,7 @@ export function createCredentialQueryContext(params) {
133
134
  suite: input.suite,
134
135
  version: input.version,
135
136
  state: 'active'
136
- }, null);
137
+ });
137
138
  for (const wrapping of input.wrappings){
138
139
  await store.putWrapping({
139
140
  wrappingID: wrapping.wrappingID,
@@ -143,7 +144,7 @@ export function createCredentialQueryContext(params) {
143
144
  iv: fromB64(wrapping.iv),
144
145
  wrappedKey: fromB64(wrapping.wrappedKey),
145
146
  recipientDID: wrapping.recipientDID ?? null
146
- }, null);
147
+ });
147
148
  }
148
149
  return await keyResult(store, await loadKey(store, input.keyID, 'administer'));
149
150
  },
@@ -156,7 +157,7 @@ export function createCredentialQueryContext(params) {
156
157
  const store = await getStore();
157
158
  // Administrative, not read: a recipient can decrypt this key's entries,
158
159
  // which is not a reason to let it write into someone else's vault.
159
- await loadKey(store, input.keyID, 'administer');
160
+ const key = await loadKey(store, input.keyID, 'administer');
160
161
  await store.putEntry({
161
162
  entryID: input.entryID,
162
163
  keyID: input.keyID,
@@ -164,8 +165,8 @@ export function createCredentialQueryContext(params) {
164
165
  iv: fromB64(input.iv),
165
166
  ciphertext: fromB64(input.ciphertext),
166
167
  hlc: HLC.serialize(params.hlc.now())
167
- }, null);
168
- const written = await store.getEntryWithProvenance(input.entryID);
168
+ });
169
+ const written = await store.getEntryWithProvenance(input.entryID, key.owner_did);
169
170
  if (written == null) {
170
171
  throw notFound('Credential entry', input.entryID);
171
172
  }
@@ -174,17 +175,17 @@ export function createCredentialQueryContext(params) {
174
175
  async deleteKey (keyID) {
175
176
  const store = await getStore();
176
177
  await loadKey(store, keyID, 'administer');
177
- await store.deleteKey(keyID, null);
178
+ await store.deleteKey(keyID);
178
179
  return true;
179
180
  },
180
- async deleteEntry (entryID) {
181
+ async deleteEntry (entryID, ownerDID) {
181
182
  const store = await getStore();
182
- const entry = await store.getEntry(entryID);
183
+ const entry = await store.getEntry(entryID, normalizeDID(ownerDID));
183
184
  if (entry == null) {
184
185
  throw notFound('Credential entry', entryID);
185
186
  }
186
187
  await loadKey(store, entry.key_id, 'administer');
187
- await store.deleteEntry(entryID, null);
188
+ await store.deleteEntry(entryID, entry.owner_did);
188
189
  return true;
189
190
  }
190
191
  };
package/lib/schema.js CHANGED
@@ -61,7 +61,7 @@ input CredentialEntryInput {
61
61
 
62
62
  extend type Query {
63
63
  credentialKey(keyID: String!): CredentialKey!
64
- credentialEntry(entryID: String!): CredentialEntry!
64
+ credentialEntry(entryID: String!, ownerDID: String!): CredentialEntry!
65
65
  credentialEntries(keyID: String!): [String!]!
66
66
  }
67
67
 
@@ -69,7 +69,7 @@ extend type Mutation {
69
69
  putCredentialKey(input: CredentialKeyInput!): CredentialKey!
70
70
  putCredentialEntry(input: CredentialEntryInput!): CredentialEntry!
71
71
  deleteCredentialKey(keyID: String!): Boolean!
72
- deleteCredentialEntry(entryID: String!): Boolean!
72
+ deleteCredentialEntry(entryID: String!, ownerDID: String!): Boolean!
73
73
  }
74
74
  `;
75
75
  function requireCredential(ctx) {
@@ -97,14 +97,14 @@ function requireCredential(ctx) {
97
97
  resolvers: {
98
98
  queryFields: {
99
99
  credentialKey: (_source, args, context)=>requireCredential(context).getKey(args.keyID),
100
- credentialEntry: (_source, args, context)=>requireCredential(context).getEntry(args.entryID),
100
+ credentialEntry: (_source, args, context)=>requireCredential(context).getEntry(args.entryID, args.ownerDID),
101
101
  credentialEntries: (_source, args, context)=>requireCredential(context).listEntries(args.keyID)
102
102
  },
103
103
  mutationFields: {
104
104
  putCredentialKey: (_source, args, context)=>requireCredential(context).putKey(args.input),
105
105
  putCredentialEntry: (_source, args, context)=>requireCredential(context).putEntry(args.input),
106
106
  deleteCredentialKey: (_source, args, context)=>requireCredential(context).deleteKey(args.keyID),
107
- deleteCredentialEntry: (_source, args, context)=>requireCredential(context).deleteEntry(args.entryID)
107
+ deleteCredentialEntry: (_source, args, context)=>requireCredential(context).deleteEntry(args.entryID, args.ownerDID)
108
108
  }
109
109
  }
110
110
  };
package/lib/service.d.ts CHANGED
@@ -1,4 +1,10 @@
1
+ import type { CreateCredentialManagerParams } from '@kubun/credential';
1
2
  import type { KubunPlugin, PluginFactoryParams } from '@kubun/engine';
3
+ /** Bind the service's recovery preflight and current removal set to each manager. */
4
+ export declare function createServiceCredentialManager(params: Pick<CreateCredentialManagerParams, 'store' | 'identity' | 'runtime' | 'hlc' | 'authority'> & {
5
+ ensure(): Promise<void>;
6
+ removedDevices(ownerDID: string): Promise<ReadonlySet<string>>;
7
+ }): import("@kubun/credential").CredentialManager;
2
8
  /**
3
9
  * The credential service provider. Unlike {@link createCredentialPlugin}
4
10
  * (graph-schema-only, for an engine that consumes credentials), this registers a
package/lib/service.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { isSigningIdentity, normalizeDID } from '@kokuin/token';
2
- import { CredentialAliasAlreadyBound, CredentialBindNotAuthorized, CredentialEntryAlreadyAliased, CredentialInvalidEntry, CredentialKeyVersionMismatch, CredentialNotFound, CredentialSupersededBranch, createCredentialAPI, createCredentialManager, wrappableDID } from '@kubun/credential';
2
+ import { CredentialAliasAlreadyBound, CredentialBindNotAuthorized, CredentialEntryAlreadyAliased, CredentialGrantCopyUnavailable, CredentialGrantOwnerAmbiguous, CredentialGrantRehomeNotAuthorized, CredentialInvalidEntry, CredentialKeyVersionMismatch, CredentialNotFound, CredentialSupersededBranch, createCredentialAPI, createCredentialManager, wrappableDID } from '@kubun/credential';
3
+ import { controllerHeadVersion, resolveCurrentControllerOfDevice } from '@kubun/engine';
3
4
  import { authorizeRead, authorizeWrite, ServiceAuthorizationError } from '@kubun/plugin-service-server';
5
+ import { credentialServiceProtocol } from '@kubun/service-credential-api';
4
6
  import { credentialStoreDefinition, getCredentialStore } from '@kubun/store-credential';
5
7
  // The service boundary has no CREDENTIAL_* → KB* mapping; toHandlerError forwards
6
8
  // a thrown error's `code` only when it is already a registered KubunErrorCode,
@@ -22,6 +24,18 @@ function translateCredentialError(err) {
22
24
  if (err instanceof CredentialNotFound) {
23
25
  return withCode(err, 'KB02', 'CREDENTIAL_NOT_FOUND');
24
26
  }
27
+ if (err instanceof CredentialGrantCopyUnavailable) {
28
+ return withCode(err, 'KB02', 'CREDENTIAL_GRANT_COPY_UNAVAILABLE');
29
+ }
30
+ if (err instanceof CredentialGrantOwnerAmbiguous) {
31
+ return withCode(err, 'KB04', 'CREDENTIAL_GRANT_OWNER_AMBIGUOUS');
32
+ }
33
+ if (err instanceof CredentialGrantRehomeNotAuthorized) {
34
+ return withCode(err, 'KB07', 'CREDENTIAL_GRANT_REHOME_NOT_AUTHORIZED');
35
+ }
36
+ if (err instanceof Error && 'code' in err && err.code === 'CREDENTIAL_GRANT_ACCOUNT_MISMATCH') {
37
+ return withCode(err, 'KB07', 'CREDENTIAL_GRANT_ACCOUNT_MISMATCH');
38
+ }
25
39
  if (err instanceof CredentialInvalidEntry) {
26
40
  return withCode(err, 'KB01', 'CREDENTIAL_INVALID_ENTRY');
27
41
  }
@@ -66,6 +80,19 @@ function readAccountPeek(raw) {
66
80
  providerAccount
67
81
  };
68
82
  }
83
+ /** Bind the service's recovery preflight and current removal set to each manager. */ export function createServiceCredentialManager(params) {
84
+ return createCredentialManager({
85
+ store: params.store,
86
+ identity: params.identity,
87
+ runtime: params.runtime,
88
+ hlc: params.hlc,
89
+ authority: params.authority,
90
+ removalRecovery: {
91
+ ensure: params.ensure,
92
+ removedDevices: params.removedDevices
93
+ }
94
+ });
95
+ }
69
96
  /**
70
97
  * The credential service provider. Unlike {@link createCredentialPlugin}
71
98
  * (graph-schema-only, for an engine that consumes credentials), this registers a
@@ -90,12 +117,45 @@ function readAccountPeek(raw) {
90
117
  }
91
118
  const identity = params.identity;
92
119
  const logger = params.getLogger('credential-service');
93
- const getCredentialManager = async (stores)=>createCredentialManager({
120
+ const recoveryResolver = params.controllerResolverFor(params.db);
121
+ const resolveRecoveryController = (did)=>resolveCurrentControllerOfDevice(params.db, did, recoveryResolver);
122
+ const recoveryOptions = {
123
+ resolveController: resolveRecoveryController,
124
+ removedDevices: async (ownerDID)=>await recoveryResolver.resolveDenySet?.(ownerDID) ?? new Set(),
125
+ methods: [
126
+ recoveryResolver
127
+ ],
128
+ headVersion: async (ownerDID)=>controllerHeadVersion(await params.controllerHead(params.db, ownerDID))
129
+ };
130
+ const getCredentialManager = async (stores, recoveryChecked = false)=>createServiceCredentialManager({
94
131
  store: await getCredentialStore(stores),
95
132
  identity,
96
133
  runtime: params.runtime,
97
- hlc: params.hlc
134
+ hlc: params.hlc,
135
+ ensure: recoveryChecked ? async ()=>{} : checkRemovalRecovery,
136
+ removedDevices: recoveryOptions.removedDevices
98
137
  });
138
+ const recoveryManager = getCredentialStore(params.db).then((store)=>createCredentialManager({
139
+ store,
140
+ identity,
141
+ runtime: params.runtime,
142
+ hlc: params.hlc,
143
+ removalRecovery: recoveryOptions,
144
+ authority: {
145
+ ownerForNewKey: async ()=>await resolveRecoveryController(identity.id) ?? identity.id,
146
+ authorize: async (_action, { key })=>normalizeDID(key.owner_did) === await resolveRecoveryController(identity.id),
147
+ authorizeRevocation: async ({ key })=>normalizeDID(key.owner_did) === await resolveRecoveryController(identity.id)
148
+ }
149
+ }));
150
+ let completedRecoveryHead;
151
+ const checkRemovalRecovery = async ()=>{
152
+ const owner = await resolveRecoveryController(identity.id);
153
+ if (owner === null) return;
154
+ const version = await recoveryOptions.headVersion(owner);
155
+ if (version === completedRecoveryHead) return;
156
+ await (await recoveryManager).recoverRemovedDevices(recoveryOptions);
157
+ completedRecoveryHead = version;
158
+ };
99
159
  // The mint folds inside its own write tx (`writeInTx`), so its resolver is
100
160
  // local-only: a recipient miss must fail closed, never pull a controller log
101
161
  // through `consultProviders` while the write lock is held. The pre-warm below
@@ -108,19 +168,42 @@ function readAccountPeek(raw) {
108
168
  // The seam is bound to whatever provider it is built over: reads run against
109
169
  // the root, writes against a transaction (below). A manager, alias store and
110
170
  // controller resolver all read from that same provider.
111
- const makeSeam = (stores)=>createCredentialAPI({
171
+ const makeSeam = (stores, recoveryChecked = false)=>createCredentialAPI({
112
172
  stores,
113
173
  logger,
114
- getCredentialManager,
174
+ getCredentialManager: (provider, checked)=>getCredentialManager(provider, recoveryChecked || checked === true),
115
175
  serverWrappableDID: wrappableDID(params.identity),
116
- getControllerMethods
176
+ getControllerMethods,
177
+ wrappingRecipientsPrewarmed: true,
178
+ resolveControllerOfOwner: (ownerDID, provider)=>resolveCurrentControllerOfDevice(provider, ownerDID, params.controllerResolverFor(provider, {
179
+ localOnly: true
180
+ }))
117
181
  });
118
182
  const readSeam = makeSeam(params.db);
183
+ const localDeviceDID = normalizeDID(identity.id);
184
+ const requireLocalGrantAddress = (param)=>{
185
+ if (param.deviceDID === undefined) return;
186
+ try {
187
+ if (normalizeDID(param.deviceDID) === localDeviceDID) return;
188
+ } catch {
189
+ // Invalid device addresses are refused by the same named credential error.
190
+ }
191
+ throw translateCredentialError(new CredentialBindNotAuthorized(param.providerName, param.ownerDID));
192
+ };
193
+ const localRead = async (context, empty, proceed)=>context.iss != null && normalizeDID(context.iss) === localDeviceDID || await context.authorize(localDeviceDID) ? proceed() : empty;
194
+ const localWrite = async (context)=>{
195
+ if ((context.iss == null || normalizeDID(context.iss) !== localDeviceDID) && !await context.authorize(localDeviceDID)) {
196
+ throw new ServiceAuthorizationError('The caller cannot spend this device grant');
197
+ }
198
+ };
119
199
  // A mint/refresh/delete is multi-statement (key + wrappings + entry + alias
120
200
  // pointer). Outside a graph mutation there is no ambient transaction, so run
121
201
  // each write in its own: a mid-mint failure would otherwise leave an
122
202
  // orphan key with no alias pointer in the vault.
123
- const writeInTx = (fn)=>params.db.withTransaction((tx)=>fn(makeSeam(tx)));
203
+ const writeInTx = async (fn)=>{
204
+ await checkRemovalRecovery();
205
+ return await params.db.withTransaction((tx)=>fn(makeSeam(tx, true)));
206
+ };
124
207
  // A first-time `did:kokuin:` owner (or recovery controller) may hold no log in
125
208
  // this engine's controller store yet. Resolve it through the pull-allowed ROOT
126
209
  // resolver before the mint tx opens: on a store miss this pulls via the
@@ -148,7 +231,7 @@ function readAccountPeek(raw) {
148
231
  context,
149
232
  subject: param.ownerDID,
150
233
  emptyResult: null,
151
- proceed: ()=>readSeam.getCredential(param.providerName, param.ownerDID)
234
+ proceed: ()=>localRead(context, null, ()=>readSeam.getCredential(param.providerName, param.ownerDID))
152
235
  });
153
236
  },
154
237
  'credential/get-ref': (context)=>{
@@ -157,7 +240,10 @@ function readAccountPeek(raw) {
157
240
  context,
158
241
  subject: param.ownerDID,
159
242
  emptyResult: null,
160
- proceed: ()=>readSeam.getCredentialRef(param.providerName, param.ownerDID)
243
+ proceed: ()=>localRead(context, null, ()=>{
244
+ requireLocalGrantAddress(param);
245
+ return readSeam.getVersionedCredentialRef(param.providerName, param.ownerDID);
246
+ })
161
247
  });
162
248
  },
163
249
  // The same vault read as `credential/get` — the DB credential API, which
@@ -169,11 +255,11 @@ function readAccountPeek(raw) {
169
255
  context,
170
256
  subject: param.ownerDID,
171
257
  emptyResult: null,
172
- proceed: async ()=>{
173
- const raw = await readSeam.getCredential(param.providerName, param.ownerDID);
174
- if (raw == null) return null;
175
- return readAccountPeek(raw);
176
- }
258
+ proceed: ()=>localRead(context, null, async ()=>{
259
+ const raw = await readSeam.getCredential(param.providerName, param.ownerDID);
260
+ if (raw == null) return null;
261
+ return readAccountPeek(raw);
262
+ })
177
263
  });
178
264
  },
179
265
  'credential/provenance': (context)=>{
@@ -182,7 +268,7 @@ function readAccountPeek(raw) {
182
268
  context,
183
269
  subject: param.ownerDID,
184
270
  emptyResult: null,
185
- proceed: ()=>readSeam.getCredentialProvenance(param.providerName, param.ownerDID)
271
+ proceed: ()=>localRead(context, null, ()=>readSeam.getCredentialProvenance(param.providerName, param.ownerDID))
186
272
  });
187
273
  },
188
274
  'credential/create': async (context)=>{
@@ -191,6 +277,7 @@ function readAccountPeek(raw) {
191
277
  context,
192
278
  subject: param.ownerDID
193
279
  });
280
+ await localWrite(context);
194
281
  // `ownerWrappableDID` is the wrappable spelling of the SAME identity the
195
282
  // authorizer just cleared (`ownerDID`). Nothing downstream re-checks that,
196
283
  // so without this a caller authorized for the owner could wrap the token to
@@ -202,13 +289,24 @@ function readAccountPeek(raw) {
202
289
  param.ownerWrappableDID,
203
290
  param.controllerWrappableDID
204
291
  ]);
205
- await writeInTx((seam)=>seam.createCredential({
206
- providerName: param.providerName,
207
- ownerDID: param.ownerDID,
208
- ownerWrappableDID: param.ownerWrappableDID,
209
- controllerWrappableDID: param.controllerWrappableDID,
210
- credential: param.credential
211
- }));
292
+ try {
293
+ await writeInTx((seam)=>seam.createCredential({
294
+ providerName: param.providerName,
295
+ ownerDID: param.ownerDID,
296
+ ownerWrappableDID: param.ownerWrappableDID,
297
+ controllerWrappableDID: param.controllerWrappableDID,
298
+ credential: param.credential,
299
+ authorizeKeyOwnerDID: async (ownerDID)=>{
300
+ await authorizeWrite({
301
+ context,
302
+ subject: ownerDID
303
+ });
304
+ return true;
305
+ }
306
+ }));
307
+ } catch (error) {
308
+ throw translateCredentialError(error);
309
+ }
212
310
  return null;
213
311
  },
214
312
  'credential/refresh': async (context)=>{
@@ -217,6 +315,7 @@ function readAccountPeek(raw) {
217
315
  context,
218
316
  subject: param.ownerDID
219
317
  });
318
+ await localWrite(context);
220
319
  await writeInTx((seam)=>seam.setCredential(param.providerName, param.ownerDID, param.credential));
221
320
  return null;
222
321
  },
@@ -226,13 +325,34 @@ function readAccountPeek(raw) {
226
325
  context,
227
326
  subject: param.ownerDID
228
327
  });
328
+ await localWrite(context);
329
+ requireLocalGrantAddress(param);
229
330
  return writeInTx(async (seam)=>{
230
331
  // The authorized alias must still name the entry being refreshed.
231
- const ref = await seam.getCredentialRef(param.providerName, param.ownerDID);
332
+ const ref = await seam.getVersionedCredentialRef(param.providerName, param.ownerDID);
232
333
  if (ref?.entryID !== param.entryID) return 'absent';
233
- return seam.setCredentialForEntry(param);
334
+ return param.expectedVersion == null ? seam.setCredentialForEntry(param) : seam.setCredentialForEntryIfUnchanged({
335
+ ...param,
336
+ expectedVersion: param.expectedVersion
337
+ });
234
338
  });
235
339
  },
340
+ 'credential/adopt-grant': async (context)=>{
341
+ const param = context.param;
342
+ if (normalizeDID(param.toDeviceDID) !== localDeviceDID) {
343
+ throw new ServiceAuthorizationError('The destination must be this device');
344
+ }
345
+ try {
346
+ const keyOwnerDID = await readSeam.getGrantKeyOwnerDID(param);
347
+ await authorizeWrite({
348
+ context,
349
+ subject: keyOwnerDID
350
+ });
351
+ return await readSeam.adoptCredentialGrant(param, keyOwnerDID);
352
+ } catch (error) {
353
+ throw translateCredentialError(error);
354
+ }
355
+ },
236
356
  'credential/delete': async (context)=>{
237
357
  const param = context.param;
238
358
  await authorizeWrite({
@@ -248,6 +368,7 @@ function readAccountPeek(raw) {
248
368
  context,
249
369
  subject: param.ownerDID
250
370
  }); // Gate A
371
+ await localWrite(context);
251
372
  try {
252
373
  await writeInTx((seam)=>seam.bindAlias(param.providerName, param.ownerDID, param.entryID));
253
374
  } catch (err) {
@@ -259,6 +380,7 @@ function readAccountPeek(raw) {
259
380
  params.registerProvider('service', {
260
381
  name: 'credential',
261
382
  handlers,
383
+ protocol: credentialServiceProtocol,
262
384
  accessRules: {
263
385
  'credential/get': {
264
386
  allow: true
@@ -281,6 +403,9 @@ function readAccountPeek(raw) {
281
403
  'credential/refresh-entry': {
282
404
  allow: true
283
405
  },
406
+ 'credential/adopt-grant': {
407
+ allow: true
408
+ },
284
409
  'credential/delete': {
285
410
  allow: true
286
411
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/plugin-credential",
3
- "version": "0.17.5",
3
+ "version": "0.18.0",
4
4
  "license": "see LICENSE.md",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -14,30 +14,30 @@
14
14
  "LICENSE.md"
15
15
  ],
16
16
  "dependencies": {
17
- "@kokuin/token": "^0.5.0",
18
- "@kubun/credential": "^0.17.4",
19
- "@kubun/db": "^0.17.0",
20
- "@kubun/engine": "^0.17.3",
21
- "@kubun/graphql": "^0.17.2",
22
- "@kubun/hlc": "^0.17.0",
23
- "@kubun/id": "^0.17.0",
24
- "@kubun/plugin-service-api": "^0.17.1",
25
- "@kubun/plugin-service-server": "^0.17.1",
26
- "@kubun/protocol": "^0.17.2",
27
- "@kubun/store-credential": "^0.17.4",
28
- "@sozai/codec": "^0.4.0",
17
+ "@kokuin/token": "^0.5.1",
18
+ "@kubun/credential": "^0.18.0",
19
+ "@kubun/db": "^0.18.0",
20
+ "@kubun/engine": "^0.18.0",
21
+ "@kubun/graphql": "^0.18.0",
22
+ "@kubun/hlc": "^0.18.0",
23
+ "@kubun/id": "^0.18.0",
24
+ "@kubun/plugin-service-api": "^0.18.0",
25
+ "@kubun/plugin-service-server": "^0.18.0",
26
+ "@kubun/protocol": "^0.18.0",
27
+ "@kubun/service-credential-api": "^0.18.0",
28
+ "@kubun/store-credential": "^0.18.0",
29
+ "@sozai/codec": "^0.4.3",
29
30
  "@sozai/runtime": "^0.1.0",
30
31
  "graphql": "^17.0.2"
31
32
  },
32
33
  "devDependencies": {
33
- "@enkaku/client": "^0.21.2",
34
- "@enkaku/transport": "^0.21.0",
35
- "@kokuin/capability": "^0.3.0",
34
+ "@enkaku/client": "^0.21.5",
35
+ "@enkaku/transport": "^0.21.5",
36
+ "@kokuin/capability": "^0.4.2",
36
37
  "@kokuin/controller": "^0.1.0",
37
- "@kubun/db-better-sqlite": "^0.17.0",
38
- "@kubun/service-credential-api": "^0.17.3",
39
- "@kubun/store-controller": "^0.17.0",
40
- "@kubun/store-graph": "^0.17.1",
38
+ "@kubun/db-better-sqlite": "^0.18.0",
39
+ "@kubun/store-controller": "^0.18.0",
40
+ "@kubun/store-graph": "^0.18.0",
41
41
  "@kubun/test-utils": "^0.0.0"
42
42
  },
43
43
  "publishConfig": {