@openlfcp/client 0.2.1 → 0.2.2

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/dist/invite.d.ts CHANGED
@@ -77,7 +77,9 @@ export interface CreatedInvitation {
77
77
  /**
78
78
  * The inviter's side (§18, §73). The grant must validate on the stored
79
79
  * chain and the package must pass §25.2 at the grant's head, both checked
80
- * before anything is queued; the grant is queued before the package.
80
+ * before anything is queued, and so is the link. The grant and the package
81
+ * are queued in one atomic commit, the grant first: a refused or failed
82
+ * commit queues neither, and a retry starts afresh.
81
83
  * Share the link once both are ACKed: until then the grant is not on the
82
84
  * coordinator's chain.
83
85
  */
package/dist/invite.js CHANGED
@@ -4,7 +4,7 @@ import { dekSecretRef } from "@openlfcp/storage";
4
4
  import { ABILITY, assembleInviteUri, createMessage, ERROR_CODE, invitationPrincipal, isGrantActive, parseControlRecord, parseInviteUri, parseKeyPackage, receiveKeyPackage, sealKeyPackage, signControlRecord, validateControlChain, verifyInvitationSecret, verifyKeyPackage, } from "@openlfcp/wire";
5
5
  import { clearClaimJournal, journaledDeks, readClaimJournal, writeClaimJournal, } from "./claim-journal.js";
6
6
  import { LfcpConnection } from "./connection.js";
7
- import { queueControlRecord, queueKeyPackage } from "./queue.js";
7
+ import { controlRecordWrites, keyPackageWrites } from "./queue.js";
8
8
  import { loadControlChain, localControlChain, saveControlChain } from "./storage.js";
9
9
  /**
10
10
  * Link invitations and the one-time capability claim (LFCP-WIRE-01 §18,
@@ -94,7 +94,9 @@ function resolveInvitationGrant(state, linkGrantId, secret) {
94
94
  /**
95
95
  * The inviter's side (§18, §73). The grant must validate on the stored
96
96
  * chain and the package must pass §25.2 at the grant's head, both checked
97
- * before anything is queued; the grant is queued before the package.
97
+ * before anything is queued, and so is the link. The grant and the package
98
+ * are queued in one atomic commit, the grant first: a refused or failed
99
+ * commit queues neither, and a retry starts afresh.
98
100
  * Share the link once both are ACKed: until then the grant is not on the
99
101
  * coordinator's chain.
100
102
  */
@@ -141,16 +143,27 @@ export async function createInvitation(options) {
141
143
  const check = verifyKeyPackage(next, parseKeyPackage(sealed.bytes));
142
144
  if (check.kind !== "authorized")
143
145
  fail("AUTHORIZATION_FAILED", `the invitation Key Package is refused: ${check.message}`);
144
- await queueControlRecord(options.storage, grant.bytes);
145
- const keyPackageId = await queueKeyPackage(options.storage, sealed.bytes);
146
+ // The link is built (and its endpoints checked) before storage changes, so
147
+ // a refused link leaves nothing queued; then the grant and its Key Package
148
+ // go into ONE commit, grant first, so either both are queued, in sending
149
+ // order, or neither is (no grant without its package).
146
150
  const uri = assembleInviteUri({
147
151
  resourceId: R,
148
152
  endpoints: options.endpoints,
149
153
  grantId: grant.recordId,
150
154
  secret,
151
155
  });
156
+ const link = new InvitationLink(uri);
157
+ const keyPackageId = hash32(parseKeyPackage(sealed.bytes).signed.id);
158
+ const r = await options.storage.commit([
159
+ ...controlRecordWrites(grant.bytes),
160
+ ...keyPackageWrites(sealed.bytes),
161
+ ]);
162
+ // The same refusal as the queue helpers (queue.ts): a plain Error.
163
+ if (!r.ok)
164
+ throw new Error(`the object was not queued: ${r.reason}`);
152
165
  return Object.freeze({
153
- link: new InvitationLink(uri),
166
+ link,
154
167
  grantId: grant.recordId,
155
168
  invitationPrincipal: invitee,
156
169
  keyPackageId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlfcp/client",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "LFCP client: session, Control Plane and Data Plane synchronization.",
5
5
  "keywords": [
6
6
  "openlfcp",
@@ -42,9 +42,9 @@
42
42
  "tag": "latest"
43
43
  },
44
44
  "dependencies": {
45
- "@openlfcp/core": "^0.2.1",
46
- "@openlfcp/storage": "^0.2.1",
47
- "@openlfcp/wire": "^0.2.1",
48
- "@openlfcp/crypto": "^0.2.1"
45
+ "@openlfcp/crypto": "^0.2.2",
46
+ "@openlfcp/storage": "^0.2.2",
47
+ "@openlfcp/wire": "^0.2.2",
48
+ "@openlfcp/core": "^0.2.2"
49
49
  }
50
50
  }