@kubun/store-credential 0.16.0 → 0.17.1

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.
Files changed (3) hide show
  1. package/lib/api.d.ts +19 -3
  2. package/lib/api.js +10 -4
  3. package/package.json +7 -7
package/lib/api.d.ts CHANGED
@@ -299,7 +299,7 @@ export type CredentialStoreAPI = {
299
299
  beginProvisioningAttempt(params: {
300
300
  ownerDID: string;
301
301
  grantorDID: string;
302
- attemptId: string;
302
+ attemptID: string;
303
303
  }): Promise<void>;
304
304
  /**
305
305
  * Record a provisioning attempt's outcome, atomically. If `epoch > heldEpoch`,
@@ -309,7 +309,7 @@ export type CredentialStoreAPI = {
309
309
  recordProvisioningAttempt(params: {
310
310
  ownerDID: string;
311
311
  grantorDID: string;
312
- attemptId: string;
312
+ attemptID: string;
313
313
  epoch: number;
314
314
  heldEpoch: number;
315
315
  }): Promise<{
@@ -325,7 +325,23 @@ export type CredentialStoreAPI = {
325
325
  abandonProvisioningAttempt(params: {
326
326
  ownerDID: string;
327
327
  grantorDID: string;
328
- attemptId: string;
328
+ attemptID: string;
329
+ }): Promise<void>;
330
+ /**
331
+ * Abandon ALL outstanding provisioning attempts for one (owner, grantor)
332
+ * scope. Deletes every attempt row for the pair, never touches the
333
+ * expectation floor. The recovery escape hatch when the attempt id is lost.
334
+ *
335
+ * Exclusive-recovery contract: this also clears any OTHER live coordinator's
336
+ * attempt on the same scope (whose later `recordProvisioningAttempt` would
337
+ * then hit the phantom-attempt guard and not raise the floor). Callers must
338
+ * ensure no other live attempt exists for the scope before calling. When the
339
+ * id is known, prefer `abandonProvisioningAttempt`, which is safe under
340
+ * concurrency.
341
+ */
342
+ abandonProvisioningAttempts(params: {
343
+ ownerDID: string;
344
+ grantorDID: string;
329
345
  }): Promise<void>;
330
346
  /**
331
347
  * List provisioning expectations for one owner: one row per (owner, grantor)
package/lib/api.js CHANGED
@@ -623,7 +623,7 @@ export function createCredentialStore(db, adapter) {
623
623
  await tx.insertInto('kubun_credential_provisioning_attempts').values({
624
624
  owner_did: ownerDid,
625
625
  grantor_did: grantorDid,
626
- attempt_id: params.attemptId
626
+ attempt_id: params.attemptID
627
627
  }).onConflict((oc)=>oc.doNothing()).execute();
628
628
  });
629
629
  },
@@ -639,12 +639,12 @@ export function createCredentialStore(db, adapter) {
639
639
  if (params.epoch > params.heldEpoch) {
640
640
  // Phantom-attempt guard: if the id names no live attempt, move
641
641
  // nothing — raising the floor for it would wedge readiness forever.
642
- const existing = await tx.selectFrom('kubun_credential_provisioning_attempts').select('attempt_id').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptId).executeTakeFirst();
642
+ const existing = await tx.selectFrom('kubun_credential_provisioning_attempts').select('attempt_id').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptID).executeTakeFirst();
643
643
  if (existing == null) {
644
644
  return;
645
645
  }
646
646
  // Delete the attempt row.
647
- await tx.deleteFrom('kubun_credential_provisioning_attempts').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptId).execute();
647
+ await tx.deleteFrom('kubun_credential_provisioning_attempts').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptID).execute();
648
648
  // Raise the floor to max(stored, epoch).
649
649
  await tx.updateTable('kubun_credential_provisioning_expectations').set((eb)=>({
650
650
  epoch_floor: eb.case().when('epoch_floor', '<', params.epoch).then(params.epoch).else(eb.ref('epoch_floor')).end()
@@ -660,7 +660,13 @@ export function createCredentialStore(db, adapter) {
660
660
  const ownerDid = normalizeDID(params.ownerDID);
661
661
  const grantorDid = normalizeDID(params.grantorDID);
662
662
  // Delete ONLY the attempt row, never the floor.
663
- await db.deleteFrom('kubun_credential_provisioning_attempts').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptId).execute();
663
+ await db.deleteFrom('kubun_credential_provisioning_attempts').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).where('attempt_id', '=', params.attemptID).execute();
664
+ },
665
+ async abandonProvisioningAttempts (params) {
666
+ const ownerDid = normalizeDID(params.ownerDID);
667
+ const grantorDid = normalizeDID(params.grantorDID);
668
+ // Delete every attempt row for the scope, never the floor.
669
+ await db.deleteFrom('kubun_credential_provisioning_attempts').where('owner_did', '=', ownerDid).where('grantor_did', '=', grantorDid).execute();
664
670
  },
665
671
  async listProvisioningExpectations (params) {
666
672
  const ownerDid = normalizeDID(params.ownerDID);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/store-credential",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -16,13 +16,13 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@kokuin/token": "^0.5.0",
19
- "@kubun/db": "^0.16.0",
20
- "@kubun/db-adapter": "^0.16.0",
19
+ "@kubun/db": "^0.17.0",
20
+ "@kubun/db-adapter": "^0.17.0",
21
21
  "kysely": "^0.29.5"
22
22
  },
23
23
  "devDependencies": {
24
- "@kubun/db-better-sqlite": "^0.16.0",
25
- "@kubun/db-postgres": "^0.16.0",
24
+ "@kubun/db-better-sqlite": "^0.17.0",
25
+ "@kubun/db-postgres": "^0.17.0",
26
26
  "@testcontainers/postgresql": "^12.1.0"
27
27
  },
28
28
  "publishConfig": {
@@ -31,8 +31,8 @@
31
31
  "scripts": {
32
32
  "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
33
33
  "build:clean": "del lib",
34
- "build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
35
- "build:types": "tsc --emitDeclarationOnly --skipLibCheck",
34
+ "build:js": "del 'lib/**/*.js' && swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
35
+ "build:types": "del 'lib/**/*.d.ts' 'lib/**/*.d.ts.map' && tsc --emitDeclarationOnly --skipLibCheck",
36
36
  "build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
37
37
  "test": "pnpm run test:types && pnpm run test:unit",
38
38
  "test:types": "tsc --noEmit -p tsconfig.test.json",