@openlfcp/shared-objects 0.3.1 → 0.4.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.
@@ -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
@@ -155,16 +155,7 @@ export class SharedObjectsDataProfile {
155
155
  return [...this.#pending.values()].map((b) => b.unitId);
156
156
  }
157
157
  codecFor(unit) {
158
- const actor = toHex(deriveActorId(unit.resourceId, unit.actor));
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
@@ -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, 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
@@ -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
@@ -104,6 +104,30 @@ export declare const identityCodec: Readonly<{
104
104
  encode: (change: CheckedChange) => Uint8Array;
105
105
  decode: typeof unframeChange;
106
106
  }>;
107
+ /**
108
+ * The codec of one unit of the Identity Profile, bound to its Resource and
109
+ * signer (§3: a change in another actor's sequence is CHANGE_ACTOR_MISMATCH).
110
+ * The writer-class rules (AI0–AI4) need the Control state at the unit's
111
+ * control_ref and stay with the document's admission (IdentityReplica.receive).
112
+ */
113
+ export declare function identityCodecFor(unit: {
114
+ readonly resourceId: ResourceId;
115
+ readonly actor: PrincipalId;
116
+ }): Readonly<{
117
+ dataProfile: "org.openlfcp.identity.v1";
118
+ encode: (change: CheckedChange) => Uint8Array;
119
+ decode: (plaintext: Uint8Array) => CheckedChange;
120
+ }>;
121
+ /**
122
+ * The Identity Profile's per-unit check without a replica (structurally the
123
+ * client's UnitProfile): for the identity flows' rotation frontier
124
+ * (FlowOptions.profiles), so a rotation of the Identity Resource judges its
125
+ * units as recipients do.
126
+ */
127
+ export declare const identityUnitProfile: Readonly<{
128
+ dataProfile: "org.openlfcp.identity.v1";
129
+ codecFor: typeof identityCodecFor;
130
+ }>;
107
131
  export declare const identitySnapshotCodec: Readonly<{
108
132
  dataProfile: "org.openlfcp.identity.v1";
109
133
  encode: typeof frameSnapshot;
@@ -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";
@@ -376,6 +377,31 @@ export const identityCodec = Object.freeze({
376
377
  encode: (change) => frameChange(change.bytes),
377
378
  decode: unframeChange,
378
379
  });
380
+ /**
381
+ * The codec of one unit of the Identity Profile, bound to its Resource and
382
+ * signer (§3: a change in another actor's sequence is CHANGE_ACTOR_MISMATCH).
383
+ * The writer-class rules (AI0–AI4) need the Control state at the unit's
384
+ * control_ref and stay with the document's admission (IdentityReplica.receive).
385
+ */
386
+ export function identityCodecFor(unit) {
387
+ const actor = toHex(deriveIdentityActorId(unit.resourceId, unit.actor));
388
+ const bound = (change) => checkChangeActor(change, actor);
389
+ return Object.freeze({
390
+ dataProfile: IDENTITY_PROFILE_ID,
391
+ encode: (change) => frameChange(bound(change).bytes),
392
+ decode: (plaintext) => bound(unframeChange(plaintext)),
393
+ });
394
+ }
395
+ /**
396
+ * The Identity Profile's per-unit check without a replica (structurally the
397
+ * client's UnitProfile): for the identity flows' rotation frontier
398
+ * (FlowOptions.profiles), so a rotation of the Identity Resource judges its
399
+ * units as recipients do.
400
+ */
401
+ export const identityUnitProfile = Object.freeze({
402
+ dataProfile: IDENTITY_PROFILE_ID,
403
+ codecFor: identityCodecFor,
404
+ });
379
405
  export const identitySnapshotCodec = Object.freeze({
380
406
  dataProfile: IDENTITY_PROFILE_ID,
381
407
  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
- const actor = toHex(deriveSectionActorId(unit.resourceId, unit.actor));
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
@@ -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";
@@ -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.1",
3
+ "version": "0.4.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.3.1",
61
- "@openlfcp/crypto": "^0.3.1"
60
+ "@openlfcp/crypto": "^0.4.0",
61
+ "@openlfcp/core": "^0.4.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "fast-check": "4.10.2"