@openlfcp/client 0.2.0-beta.7 → 0.2.0-beta.8

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/data-unit.js CHANGED
@@ -23,10 +23,12 @@ export async function createDataUnit(options) {
23
23
  const plaintext = options.profile.encode(options.value);
24
24
  const seq = await options.sequences.reserveNext(atHead.resourceId, actor);
25
25
  options.guard?.claim(atHead.resourceId, actor, seq);
26
- if ((seq === 1n) !== (options.previousUnitId === null))
27
- throw new LfcpError("INVALID_STRUCTURE", seq === 1n
28
- ? "the actor's first unit (sequence 1) must have a null previous unit (§26.2)"
29
- : `sequence ${seq} needs the actor's unit at sequence ${seq - 1n} as its previous unit (§26.2)`);
26
+ // §26.2: sequence 1 names no previous unit. A later one names the writer's
27
+ // latest own unit still accepted, or none: after a first unit that went
28
+ // stale (a Key Epoch cut it off) or was abandoned, the unit at 2 has a null
29
+ // previous, and a receiver that accepted nothing of the actor links it.
30
+ if (seq === 1n && options.previousUnitId !== null)
31
+ throw new LfcpError("INVALID_STRUCTURE", "the actor's first unit (sequence 1) must have a null previous unit (§26.2)");
30
32
  const sealed = sealDataUnit({
31
33
  resourceId: atHead.resourceId,
32
34
  dataEpoch: epoch,
package/dist/storage.js CHANGED
@@ -283,9 +283,13 @@ export async function createQueuedDataUnit(storage, options, also = []) {
283
283
  }
284
284
  async function createQueuedDataUnitNow(storage, options, also, resource, actor) {
285
285
  const { onCreated, previousUnitId, ...create } = options;
286
- const previous = previousUnitId !== undefined
287
- ? previousUnitId
288
- : await latestAcceptedOwnUnit(storage, resource, actor);
286
+ const latest = await latestAcceptedOwnUnit(storage, resource, actor);
287
+ // §26.2: a null previous only when the writer holds no own unit as
288
+ // accepted (before its first, or after a first that went stale); while it
289
+ // holds one, a receiver that accepted it would hold this unit for good.
290
+ if (previousUnitId === null && latest !== null)
291
+ throw new LfcpError("INVALID_STRUCTURE", "the writer still holds an accepted own unit: its next unit names it as previous (§26.2)");
292
+ const previous = previousUnitId !== undefined ? previousUnitId : latest;
289
293
  const created = await createDataUnit({
290
294
  ...create,
291
295
  previousUnitId: previous,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlfcp/client",
3
- "version": "0.2.0-beta.7",
3
+ "version": "0.2.0-beta.8",
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": "beta"
43
43
  },
44
44
  "dependencies": {
45
- "@openlfcp/core": "^0.2.0-beta.7",
46
- "@openlfcp/crypto": "^0.2.0-beta.7",
47
- "@openlfcp/storage": "^0.2.0-beta.7",
48
- "@openlfcp/wire": "^0.2.0-beta.7"
45
+ "@openlfcp/core": "^0.2.0-beta.8",
46
+ "@openlfcp/storage": "^0.2.0-beta.8",
47
+ "@openlfcp/crypto": "^0.2.0-beta.8",
48
+ "@openlfcp/wire": "^0.2.0-beta.8"
49
49
  }
50
50
  }