@openlfcp/shared-objects 0.3.1 → 0.5.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/README.md +1 -1
- package/dist/data-profile.d.ts +20 -0
- package/dist/data-profile.js +26 -10
- package/dist/identity/index.d.ts +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/identity/replica.d.ts +45 -2
- package/dist/identity/replica.js +65 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sections/data-profile.d.ts +17 -0
- package/dist/sections/data-profile.js +23 -7
- package/dist/sections/index.d.ts +1 -1
- package/dist/sections/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ without notice until the profile is in a baseline.
|
|
|
40
40
|
## Identity profile (MVP 0.4 Working Draft)
|
|
41
41
|
|
|
42
42
|
`@openlfcp/shared-objects/identity` implements IDENTITY-PROFILE-01 §§2–4
|
|
43
|
-
(`org.openlfcp.identity.v1`, `mvp-0.4-baseline.
|
|
43
|
+
(`org.openlfcp.identity.v1`, `mvp-0.4-baseline.4`, LFCP-04-409 and 409b).
|
|
44
44
|
`IdentityReplica` admits changes with AI0–AI5, validates every concurrent
|
|
45
45
|
field value and exposes `roster()`, `devices()` and `requests()`. Invalid
|
|
46
46
|
entries are omitted; an invalid root makes all three readers empty.
|
package/dist/data-profile.d.ts
CHANGED
|
@@ -184,4 +184,24 @@ export declare class SharedObjectsDataProfile {
|
|
|
184
184
|
*/
|
|
185
185
|
exclude(unitIds: readonly DataUnitId[]): SharedObjectsExcludeResult;
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* The codec of one unit of this profile, bound to its Resource and signer
|
|
189
|
+
* (§8, §11, SO-SEC1): a unit carries only changes of its signer's §8 actor,
|
|
190
|
+
* so no Principal can write into another Principal's Automerge history.
|
|
191
|
+
* Anything else is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH. The same check
|
|
192
|
+
* whether a receiver merges the unit or a rotation judges it.
|
|
193
|
+
*/
|
|
194
|
+
export declare function sharedObjectsCodecFor(unit: {
|
|
195
|
+
readonly resourceId: ResourceId;
|
|
196
|
+
readonly actor: PrincipalId;
|
|
197
|
+
}): SharedObjectsCodec;
|
|
198
|
+
/**
|
|
199
|
+
* This profile's per-unit check without a replica (structurally the client's
|
|
200
|
+
* UnitProfile): for the identity flows' rotation frontier
|
|
201
|
+
* (FlowOptions.profiles), which judges units as recipients do.
|
|
202
|
+
*/
|
|
203
|
+
export declare const sharedObjectsUnitProfile: Readonly<{
|
|
204
|
+
dataProfile: "org.openlfcp.shared-objects.v1";
|
|
205
|
+
codecFor: typeof sharedObjectsCodecFor;
|
|
206
|
+
}>;
|
|
187
207
|
//# sourceMappingURL=data-profile.d.ts.map
|
package/dist/data-profile.js
CHANGED
|
@@ -155,16 +155,7 @@ export class SharedObjectsDataProfile {
|
|
|
155
155
|
return [...this.#pending.values()].map((b) => b.unitId);
|
|
156
156
|
}
|
|
157
157
|
codecFor(unit) {
|
|
158
|
-
|
|
159
|
-
// §8, §11 (SO-SEC1): a unit carries only changes of its signer's §8
|
|
160
|
-
// actor, so no Principal can write into another Principal's Automerge
|
|
161
|
-
// history. Anything else is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH.
|
|
162
|
-
const bound = (change) => checkChangeActor(change, actor);
|
|
163
|
-
return {
|
|
164
|
-
dataProfile: PROFILE_ID,
|
|
165
|
-
encode: (change) => frameChange(bound(change).bytes),
|
|
166
|
-
decode: (plaintext) => bound(unframeChange(plaintext)),
|
|
167
|
-
};
|
|
158
|
+
return sharedObjectsCodecFor(unit);
|
|
168
159
|
}
|
|
169
160
|
apply(unit, change) {
|
|
170
161
|
const key = toHex(unit.unitId);
|
|
@@ -362,4 +353,29 @@ function rebuildChanges(before, after) {
|
|
|
362
353
|
}
|
|
363
354
|
return out;
|
|
364
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* The codec of one unit of this profile, bound to its Resource and signer
|
|
358
|
+
* (§8, §11, SO-SEC1): a unit carries only changes of its signer's §8 actor,
|
|
359
|
+
* so no Principal can write into another Principal's Automerge history.
|
|
360
|
+
* Anything else is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH. The same check
|
|
361
|
+
* whether a receiver merges the unit or a rotation judges it.
|
|
362
|
+
*/
|
|
363
|
+
export function sharedObjectsCodecFor(unit) {
|
|
364
|
+
const actor = toHex(deriveActorId(unit.resourceId, unit.actor));
|
|
365
|
+
const bound = (change) => checkChangeActor(change, actor);
|
|
366
|
+
return {
|
|
367
|
+
dataProfile: PROFILE_ID,
|
|
368
|
+
encode: (change) => frameChange(bound(change).bytes),
|
|
369
|
+
decode: (plaintext) => bound(unframeChange(plaintext)),
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* This profile's per-unit check without a replica (structurally the client's
|
|
374
|
+
* UnitProfile): for the identity flows' rotation frontier
|
|
375
|
+
* (FlowOptions.profiles), which judges units as recipients do.
|
|
376
|
+
*/
|
|
377
|
+
export const sharedObjectsUnitProfile = Object.freeze({
|
|
378
|
+
dataProfile: PROFILE_ID,
|
|
379
|
+
codecFor: sharedObjectsCodecFor,
|
|
380
|
+
});
|
|
365
381
|
//# sourceMappingURL=data-profile.js.map
|
package/dist/identity/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** IDENTITY-PROFILE-01 §§2–4. No authority is inferred from document metadata. */
|
|
2
2
|
export { checkIdentityUnit, IDENTITY_ADMISSION_ORDER, IdentityAdmission, type IdentityAdmissionDiagnostic, IdentityAdmissionError, } from "./admission.js";
|
|
3
|
-
export { type IdentityIntent, type IdentityOptions, type IdentityReceiveResult, type IdentityRefusal, IdentityReplica, type IdentityUnit, identityCodec, identitySnapshotCodec, } from "./replica.js";
|
|
3
|
+
export { type IdentityIntent, type IdentityOptions, type IdentityReceiveResult, type IdentityRefusal, IdentityReplica, type IdentityUnit, type IdentityWriteOptions, identityCodec, identityCodecFor, identitySnapshotCodec, identityUnitProfile, } from "./replica.js";
|
|
4
4
|
export { IDENTITY_DIAGNOSTIC_ORDER, type IdentityDiagnostic, type IdentityProblem, type IdentityValidation, validateIdentity, } from "./schema.js";
|
|
5
5
|
export { type DeviceEntry, deriveIdentityActorId, IDENTITY_PROFILE_ID, type IdentityDocument, type IdentityEpoch, type IdentityWriter, type IdentityWriterClass, isResourceRef, type PairingRequest, type ResourceRef, type RosterEntry, } from "./values.js";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/identity/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** IDENTITY-PROFILE-01 §§2–4. No authority is inferred from document metadata. */
|
|
2
2
|
export { checkIdentityUnit, IDENTITY_ADMISSION_ORDER, IdentityAdmission, IdentityAdmissionError, } from "./admission.js";
|
|
3
|
-
export { IdentityReplica, identityCodec, identitySnapshotCodec, } from "./replica.js";
|
|
3
|
+
export { IdentityReplica, identityCodec, identityCodecFor, identitySnapshotCodec, identityUnitProfile, } from "./replica.js";
|
|
4
4
|
export { IDENTITY_DIAGNOSTIC_ORDER, validateIdentity, } from "./schema.js";
|
|
5
5
|
export { deriveIdentityActorId, IDENTITY_PROFILE_ID, isResourceRef, } from "./values.js";
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -25,6 +25,15 @@ export interface IdentityReceiveResult {
|
|
|
25
25
|
readonly waiting: readonly string[];
|
|
26
26
|
readonly refused: readonly IdentityRefusal[];
|
|
27
27
|
}
|
|
28
|
+
/** Options of IdentityReplica.write. */
|
|
29
|
+
export interface IdentityWriteOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Device entries (PrincipalRefs) whose `revoked` flag the change sets to
|
|
32
|
+
* `true` after the intents, writing no other field of them: a retired
|
|
33
|
+
* entry (IDENTITY-PROFILE-01 §7.1 step 4, §8.2). Each entry must exist.
|
|
34
|
+
*/
|
|
35
|
+
readonly retire?: readonly string[];
|
|
36
|
+
}
|
|
28
37
|
export type IdentityIntent = {
|
|
29
38
|
readonly intent: "identity.initialize";
|
|
30
39
|
} | {
|
|
@@ -91,19 +100,53 @@ export declare class IdentityReplica {
|
|
|
91
100
|
readonly hash: string;
|
|
92
101
|
readonly signer: PrincipalId;
|
|
93
102
|
}[];
|
|
103
|
+
/**
|
|
104
|
+
* Every value the scalar field `table[key].field` holds now: one, or
|
|
105
|
+
* several under concurrent writes (identical values once, SOP §45); none
|
|
106
|
+
* when the field is absent or `table[key]` is not one map. Strings, uints
|
|
107
|
+
* and booleans as JavaScript values. `devices()` shows one of them; this
|
|
108
|
+
* is what IDENTITY-PROFILE-01 §7.1 step 4 reads of a retired entry's
|
|
109
|
+
* `revoked` ("some value is not true").
|
|
110
|
+
*/
|
|
111
|
+
fieldValues(table: "roster" | "devices" | "requests", key: string, field: string): readonly unknown[];
|
|
94
112
|
/**
|
|
95
113
|
* One transaction (one change) for the intent, or for several intents in
|
|
96
114
|
* order, e.g. the fill change of IDENTITY-PROFILE-01 §5.1 or the devices
|
|
97
115
|
* entry and the request deletion of §5.3 step 6; scalar strings/uints,
|
|
98
|
-
* unknown fields preserved on updates.
|
|
116
|
+
* unknown fields preserved on updates. `options.retire` adds the
|
|
117
|
+
* `revoked = true` flag of retired entries, field by field.
|
|
99
118
|
*/
|
|
100
|
-
write(writer: IdentityWriter, intent: IdentityIntent | readonly IdentityIntent[]): CheckedChange;
|
|
119
|
+
write(writer: IdentityWriter, intent: IdentityIntent | readonly IdentityIntent[], options?: IdentityWriteOptions): CheckedChange;
|
|
101
120
|
}
|
|
102
121
|
export declare const identityCodec: Readonly<{
|
|
103
122
|
dataProfile: "org.openlfcp.identity.v1";
|
|
104
123
|
encode: (change: CheckedChange) => Uint8Array;
|
|
105
124
|
decode: typeof unframeChange;
|
|
106
125
|
}>;
|
|
126
|
+
/**
|
|
127
|
+
* The codec of one unit of the Identity Profile, bound to its Resource and
|
|
128
|
+
* signer (§3: a change in another actor's sequence is CHANGE_ACTOR_MISMATCH).
|
|
129
|
+
* The writer-class rules (AI0–AI4) need the Control state at the unit's
|
|
130
|
+
* control_ref and stay with the document's admission (IdentityReplica.receive).
|
|
131
|
+
*/
|
|
132
|
+
export declare function identityCodecFor(unit: {
|
|
133
|
+
readonly resourceId: ResourceId;
|
|
134
|
+
readonly actor: PrincipalId;
|
|
135
|
+
}): Readonly<{
|
|
136
|
+
dataProfile: "org.openlfcp.identity.v1";
|
|
137
|
+
encode: (change: CheckedChange) => Uint8Array;
|
|
138
|
+
decode: (plaintext: Uint8Array) => CheckedChange;
|
|
139
|
+
}>;
|
|
140
|
+
/**
|
|
141
|
+
* The Identity Profile's per-unit check without a replica (structurally the
|
|
142
|
+
* client's UnitProfile): for the identity flows' rotation frontier
|
|
143
|
+
* (FlowOptions.profiles), so a rotation of the Identity Resource judges its
|
|
144
|
+
* units as recipients do.
|
|
145
|
+
*/
|
|
146
|
+
export declare const identityUnitProfile: Readonly<{
|
|
147
|
+
dataProfile: "org.openlfcp.identity.v1";
|
|
148
|
+
codecFor: typeof identityCodecFor;
|
|
149
|
+
}>;
|
|
107
150
|
export declare const identitySnapshotCodec: Readonly<{
|
|
108
151
|
dataProfile: "org.openlfcp.identity.v1";
|
|
109
152
|
encode: typeof frameSnapshot;
|
package/dist/identity/replica.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as A from "@automerge/automerge";
|
|
2
2
|
import { bytesEqual, dataEpoch, LfcpError, toHex, } from "@openlfcp/core";
|
|
3
|
+
import { checkChangeActor } from "../admission/actor.js";
|
|
3
4
|
import { checkChange, checkSaveHeader, frameChange, frameSnapshot, parsedOf, refusedChangeHash, unframeChange, unframeSnapshot, } from "../admission/framing.js";
|
|
4
5
|
import { checkSnapshotExpansion, SNAPSHOT_LIMITS_FLOOR, } from "../admission/limits.js";
|
|
5
6
|
import { ReferenceHistory } from "../admission/references.js";
|
|
@@ -7,6 +8,7 @@ import { admitBatch, admitChange } from "../admission/sequence.js";
|
|
|
7
8
|
import { isWasmTrap } from "../replica.js";
|
|
8
9
|
import { principalRef } from "../values.js";
|
|
9
10
|
import { checkIdentityUnit, IdentityAdmission, refuseIdentity } from "./admission.js";
|
|
11
|
+
import { IdentityReader } from "./reader.js";
|
|
10
12
|
import { validateIdentity } from "./schema.js";
|
|
11
13
|
import { deriveIdentityActorId, IDENTITY_PROFILE_ID, } from "./values.js";
|
|
12
14
|
const refusal = (hash, error, held = false) => ({
|
|
@@ -244,17 +246,35 @@ export class IdentityReplica {
|
|
|
244
246
|
}
|
|
245
247
|
return Object.freeze(out);
|
|
246
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Every value the scalar field `table[key].field` holds now: one, or
|
|
251
|
+
* several under concurrent writes (identical values once, SOP §45); none
|
|
252
|
+
* when the field is absent or `table[key]` is not one map. Strings, uints
|
|
253
|
+
* and booleans as JavaScript values. `devices()` shows one of them; this
|
|
254
|
+
* is what IDENTITY-PROFILE-01 §7.1 step 4 reads of a retired entry's
|
|
255
|
+
* `revoked` ("some value is not true").
|
|
256
|
+
*/
|
|
257
|
+
fieldValues(table, key, field) {
|
|
258
|
+
const reader = new IdentityReader(this.#doc);
|
|
259
|
+
const container = reader.map("_root", table);
|
|
260
|
+
const entry = container === undefined ? undefined : reader.map(container, key);
|
|
261
|
+
if (entry === undefined)
|
|
262
|
+
return Object.freeze([]);
|
|
263
|
+
return Object.freeze(reader.all(entry, field).map(([, value]) => value));
|
|
264
|
+
}
|
|
247
265
|
/**
|
|
248
266
|
* One transaction (one change) for the intent, or for several intents in
|
|
249
267
|
* order, e.g. the fill change of IDENTITY-PROFILE-01 §5.1 or the devices
|
|
250
268
|
* entry and the request deletion of §5.3 step 6; scalar strings/uints,
|
|
251
|
-
* unknown fields preserved on updates.
|
|
269
|
+
* unknown fields preserved on updates. `options.retire` adds the
|
|
270
|
+
* `revoked = true` flag of retired entries, field by field.
|
|
252
271
|
*/
|
|
253
|
-
write(writer, intent) {
|
|
272
|
+
write(writer, intent, options = {}) {
|
|
254
273
|
const intents = Array.isArray(intent)
|
|
255
274
|
? intent
|
|
256
275
|
: [intent];
|
|
257
|
-
|
|
276
|
+
const retire = options.retire ?? [];
|
|
277
|
+
if (intents.length === 0 && retire.length === 0)
|
|
258
278
|
throw new LfcpError("PROFILE_INVALID", "no intent to write");
|
|
259
279
|
// AI5 (§3) refuses the change anyway; say why before building it.
|
|
260
280
|
for (const i of intents)
|
|
@@ -269,14 +289,19 @@ export class IdentityReplica {
|
|
|
269
289
|
const doc = A.change(fork, { time: 0 }, (d) => {
|
|
270
290
|
for (const i of intents)
|
|
271
291
|
applyIntent(d, i, this.#options.root, A.getBackend(d));
|
|
292
|
+
for (const key of retire)
|
|
293
|
+
retireEntry(d, key);
|
|
272
294
|
});
|
|
273
295
|
const last = A.getLastLocalChange(doc);
|
|
274
296
|
if (last === null || last === undefined)
|
|
275
297
|
throw new LfcpError("PROFILE_INVALID", "the intent did not create a change");
|
|
276
298
|
bytes = last;
|
|
277
299
|
const validation = validateIdentity(doc, this.#options.root);
|
|
278
|
-
|
|
279
|
-
|
|
300
|
+
const written = [
|
|
301
|
+
...intents.map((i) => ("key" in i ? `/${tableOf(i)}/${i.key}` : "")),
|
|
302
|
+
...retire.map((key) => `/devices/${key}`),
|
|
303
|
+
];
|
|
304
|
+
for (const base of written) {
|
|
280
305
|
const problem = validation.problems.find((p) => p.diagnostic === "INVALID_ROOT" ||
|
|
281
306
|
p.pointer === base ||
|
|
282
307
|
p.pointer.startsWith(`${base}/`));
|
|
@@ -342,6 +367,16 @@ function applyIntent(d, intent, root, backend) {
|
|
|
342
367
|
if (value !== undefined)
|
|
343
368
|
putValue(entry, key, value, backend);
|
|
344
369
|
}
|
|
370
|
+
/** `devices[key].revoked = true`, and nothing else of the entry (§7.1 step 4, §8.2). */
|
|
371
|
+
function retireEntry(d, key) {
|
|
372
|
+
const devices = d.devices;
|
|
373
|
+
if (devices === undefined)
|
|
374
|
+
refuseIdentity("INVALID_ROOT", "initialize the identity first");
|
|
375
|
+
const entry = Object.hasOwn(devices, key) ? devices[key] : undefined;
|
|
376
|
+
if (entry === null || typeof entry !== "object")
|
|
377
|
+
throw new LfcpError("PROFILE_INVALID", `no device entry ${key} to retire`);
|
|
378
|
+
entry.revoked = true;
|
|
379
|
+
}
|
|
345
380
|
function putValue(target, key, value, backend) {
|
|
346
381
|
const map = target;
|
|
347
382
|
if (typeof value === "string")
|
|
@@ -376,6 +411,31 @@ export const identityCodec = Object.freeze({
|
|
|
376
411
|
encode: (change) => frameChange(change.bytes),
|
|
377
412
|
decode: unframeChange,
|
|
378
413
|
});
|
|
414
|
+
/**
|
|
415
|
+
* The codec of one unit of the Identity Profile, bound to its Resource and
|
|
416
|
+
* signer (§3: a change in another actor's sequence is CHANGE_ACTOR_MISMATCH).
|
|
417
|
+
* The writer-class rules (AI0–AI4) need the Control state at the unit's
|
|
418
|
+
* control_ref and stay with the document's admission (IdentityReplica.receive).
|
|
419
|
+
*/
|
|
420
|
+
export function identityCodecFor(unit) {
|
|
421
|
+
const actor = toHex(deriveIdentityActorId(unit.resourceId, unit.actor));
|
|
422
|
+
const bound = (change) => checkChangeActor(change, actor);
|
|
423
|
+
return Object.freeze({
|
|
424
|
+
dataProfile: IDENTITY_PROFILE_ID,
|
|
425
|
+
encode: (change) => frameChange(bound(change).bytes),
|
|
426
|
+
decode: (plaintext) => bound(unframeChange(plaintext)),
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* The Identity Profile's per-unit check without a replica (structurally the
|
|
431
|
+
* client's UnitProfile): for the identity flows' rotation frontier
|
|
432
|
+
* (FlowOptions.profiles), so a rotation of the Identity Resource judges its
|
|
433
|
+
* units as recipients do.
|
|
434
|
+
*/
|
|
435
|
+
export const identityUnitProfile = Object.freeze({
|
|
436
|
+
dataProfile: IDENTITY_PROFILE_ID,
|
|
437
|
+
codecFor: identityCodecFor,
|
|
438
|
+
});
|
|
379
439
|
export const identitySnapshotCodec = Object.freeze({
|
|
380
440
|
dataProfile: IDENTITY_PROFILE_ID,
|
|
381
441
|
encode: frameSnapshot,
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
export declare const PACKAGE = "@openlfcp/shared-objects";
|
|
7
7
|
export { type CheckedChange, checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./admission/framing.js";
|
|
8
8
|
export { CHANGE_LIMITS, type ChunkExpansion, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, type SnapshotLimits, } from "./admission/limits.js";
|
|
9
|
-
export { type SharedObjectsApplyResult, type SharedObjectsBatchResult, type SharedObjectsCheckpoint, type SharedObjectsCodec, SharedObjectsDataProfile, type SharedObjectsDiagnostic, type SharedObjectsExcludeResult, type SharedObjectsListenerFailure, type SharedObjectsSnapshotCodec, type SharedObjectsUnit, } from "./data-profile.js";
|
|
9
|
+
export { type SharedObjectsApplyResult, type SharedObjectsBatchResult, type SharedObjectsCheckpoint, type SharedObjectsCodec, SharedObjectsDataProfile, type SharedObjectsDiagnostic, type SharedObjectsExcludeResult, type SharedObjectsListenerFailure, type SharedObjectsSnapshotCodec, type SharedObjectsUnit, sharedObjectsCodecFor, sharedObjectsUnitProfile, } from "./data-profile.js";
|
|
10
10
|
export { applyBatchChecked, applyChecked, type BatchReceiveResult, type BuiltReplica, isWasmTrap, type LocalChange, type ObjectChange, ObjectIdCollisionError, type ObjectStatus, type ReceiveResult, type ReplicaIntent, type ReplicaOptions, type ReplicaValidation, type ResolveFieldConflict, resolveFieldConflict, SCALAR_FIELDS, type ScalarField, type ScalarView, SharedObjectsReplica, type TaskView, } from "./replica.js";
|
|
11
11
|
export { addTag, assign, cancel, clearDue, clearScheduled, complete, createTask, deleteTask, type NewTask, type ParsedTask, ProfileError, parseTask, removeTag, reopen, restoreTask, setDue, setPriority, setScheduled, setStatus, setTitle, type Task, type TaskChange, type TaskIntent, type TaskPriority, type TaskStatus, taskToJson, unassign, } from "./task.js";
|
|
12
12
|
export { DIAGNOSTIC_ORDER, firstPerField, isMap, type Json, objectProblems, type ProfileDiagnostic, ProfileInvalidError, type ProfileProblem, pointerToken, type RootValidation, validateRoot, validateTransition, } from "./validate.js";
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
export const PACKAGE = "@openlfcp/shared-objects";
|
|
7
7
|
export { checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./admission/framing.js";
|
|
8
8
|
export { CHANGE_LIMITS, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, } from "./admission/limits.js";
|
|
9
|
-
export { SharedObjectsDataProfile, } from "./data-profile.js";
|
|
9
|
+
export { SharedObjectsDataProfile, sharedObjectsCodecFor, sharedObjectsUnitProfile, } from "./data-profile.js";
|
|
10
10
|
export { applyBatchChecked, applyChecked, isWasmTrap, ObjectIdCollisionError, resolveFieldConflict, SCALAR_FIELDS, SharedObjectsReplica, } from "./replica.js";
|
|
11
11
|
export { addTag, assign, cancel, clearDue, clearScheduled, complete, createTask, deleteTask, ProfileError, parseTask, removeTag, reopen, restoreTask, setDue, setPriority, setScheduled, setStatus, setTitle, taskToJson, unassign, } from "./task.js";
|
|
12
12
|
export { DIAGNOSTIC_ORDER, firstPerField, isMap, objectProblems, ProfileInvalidError, pointerToken, validateRoot, validateTransition, } from "./validate.js";
|
|
@@ -209,4 +209,21 @@ export declare class SharedSectionsDataProfile {
|
|
|
209
209
|
readonly principal: PrincipalId;
|
|
210
210
|
}): SharedSectionsDataProfile;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* The codec of one unit of this profile, bound to its signer's section actor
|
|
214
|
+
* (§2): a change of another actor is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH.
|
|
215
|
+
* The same check whether a receiver merges the unit or a rotation judges it.
|
|
216
|
+
*/
|
|
217
|
+
export declare function sectionsCodecFor(unit: {
|
|
218
|
+
readonly resourceId: ResourceId;
|
|
219
|
+
readonly actor: PrincipalId;
|
|
220
|
+
}): SectionsCodec;
|
|
221
|
+
/**
|
|
222
|
+
* This profile's per-unit check without a replica (structurally the client's
|
|
223
|
+
* UnitProfile): for the identity flows' rotation frontier (FlowOptions.profiles).
|
|
224
|
+
*/
|
|
225
|
+
export declare const sectionsUnitProfile: Readonly<{
|
|
226
|
+
dataProfile: "org.openlfcp.shared-sections.v1";
|
|
227
|
+
codecFor: typeof sectionsCodecFor;
|
|
228
|
+
}>;
|
|
212
229
|
//# sourceMappingURL=data-profile.d.ts.map
|
|
@@ -105,13 +105,7 @@ export class SharedSectionsDataProfile {
|
|
|
105
105
|
}
|
|
106
106
|
/** The codec of one unit, bound to its signer's section actor (§2). */
|
|
107
107
|
codecFor(unit) {
|
|
108
|
-
|
|
109
|
-
const bound = (c) => checkChangeActor(c, actor);
|
|
110
|
-
return {
|
|
111
|
-
dataProfile: SECTIONS_PROFILE_ID,
|
|
112
|
-
encode: (change) => frameChange(bound(change).bytes),
|
|
113
|
-
decode: (plaintext) => bound(unframeChange(plaintext)),
|
|
114
|
-
};
|
|
108
|
+
return sectionsCodecFor(unit);
|
|
115
109
|
}
|
|
116
110
|
/**
|
|
117
111
|
* SDK-SECTIONS-INTEGRATION-01 §3.1: the binding through which a sync
|
|
@@ -401,4 +395,26 @@ export class SharedSectionsDataProfile {
|
|
|
401
395
|
return profile;
|
|
402
396
|
}
|
|
403
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* The codec of one unit of this profile, bound to its signer's section actor
|
|
400
|
+
* (§2): a change of another actor is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH.
|
|
401
|
+
* The same check whether a receiver merges the unit or a rotation judges it.
|
|
402
|
+
*/
|
|
403
|
+
export function sectionsCodecFor(unit) {
|
|
404
|
+
const actor = toHex(deriveSectionActorId(unit.resourceId, unit.actor));
|
|
405
|
+
const bound = (c) => checkChangeActor(c, actor);
|
|
406
|
+
return {
|
|
407
|
+
dataProfile: SECTIONS_PROFILE_ID,
|
|
408
|
+
encode: (change) => frameChange(bound(change).bytes),
|
|
409
|
+
decode: (plaintext) => bound(unframeChange(plaintext)),
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* This profile's per-unit check without a replica (structurally the client's
|
|
414
|
+
* UnitProfile): for the identity flows' rotation frontier (FlowOptions.profiles).
|
|
415
|
+
*/
|
|
416
|
+
export const sectionsUnitProfile = Object.freeze({
|
|
417
|
+
dataProfile: SECTIONS_PROFILE_ID,
|
|
418
|
+
codecFor: sectionsCodecFor,
|
|
419
|
+
});
|
|
404
420
|
//# sourceMappingURL=data-profile.js.map
|
package/dist/sections/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* shared `@openlfcp/shared-objects/admission` with SECTIONS_ACTOR_DOMAIN.
|
|
9
9
|
*/
|
|
10
10
|
export { ADMISSION_ORDER, type AdmissionDiagnostic, SectionAdmissionError, } from "./admission.js";
|
|
11
|
-
export { type SectionsApplyResult, type SectionsBatchResult, type SectionsCheckpoint, type SectionsCodec, type SectionsCommitBinding, type SectionsExcludeResult, type SectionsListenerFailure, type SectionsNodesChanged, type SectionsSnapshotBinding, type SectionsSnapshotCodec, type SectionsStagedOperation, type SectionsUnit, SharedSectionsDataProfile, } from "./data-profile.js";
|
|
11
|
+
export { type SectionsApplyResult, type SectionsBatchResult, type SectionsCheckpoint, type SectionsCodec, type SectionsCommitBinding, type SectionsExcludeResult, type SectionsListenerFailure, type SectionsNodesChanged, type SectionsSnapshotBinding, type SectionsSnapshotCodec, type SectionsStagedOperation, type SectionsUnit, SharedSectionsDataProfile, sectionsCodecFor, sectionsUnitProfile, } from "./data-profile.js";
|
|
12
12
|
export { type ProfileModel, profileModel, SUPPORTED_DATA_PROFILES, taskRefModel, } from "./dispatch.js";
|
|
13
13
|
export { SectionDocument, type ValueType } from "./document.js";
|
|
14
14
|
export { AUTHORING_BUDGET, type SectionIntent, type SectionIntentCode, SectionIntentError, type SectionLocalChange, type SectionReceiveResult, type SectionRefusal, SectionReplica, type SectionReplicaOptions, type SectionSnapshot, type SectionSnapshotNode, type SectionUnit, type StagedSectionChange, type TextEdit, } from "./replica.js";
|
package/dist/sections/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* shared `@openlfcp/shared-objects/admission` with SECTIONS_ACTOR_DOMAIN.
|
|
9
9
|
*/
|
|
10
10
|
export { ADMISSION_ORDER, SectionAdmissionError, } from "./admission.js";
|
|
11
|
-
export { SharedSectionsDataProfile, } from "./data-profile.js";
|
|
11
|
+
export { SharedSectionsDataProfile, sectionsCodecFor, sectionsUnitProfile, } from "./data-profile.js";
|
|
12
12
|
export { profileModel, SUPPORTED_DATA_PROFILES, taskRefModel, } from "./dispatch.js";
|
|
13
13
|
export { SectionDocument } from "./document.js";
|
|
14
14
|
export { AUTHORING_BUDGET, SectionIntentError, SectionReplica, } from "./replica.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlfcp/shared-objects",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "SHARED-OBJECTS-PROFILE-01 (org.openlfcp.shared-objects.v1) implementation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openlfcp",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@automerge/automerge": "3.5.0",
|
|
59
59
|
"fflate": "0.8.3",
|
|
60
|
-
"@openlfcp/core": "^0.
|
|
61
|
-
"@openlfcp/crypto": "^0.
|
|
60
|
+
"@openlfcp/core": "^0.5.0",
|
|
61
|
+
"@openlfcp/crypto": "^0.5.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"fast-check": "4.10.2"
|