@amalgm/live 0.2.26 → 0.2.28
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/PURPOSE.md +52 -29
- package/README.md +1 -2
- package/dist/contracts/index.d.ts +0 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +0 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/detection/record-proposal.d.ts +3 -2
- package/dist/detection/record-proposal.d.ts.map +1 -1
- package/dist/detection/record-proposal.js +9 -7
- package/dist/detection/record-proposal.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/machines/index.d.ts +0 -2
- package/dist/machines/index.d.ts.map +1 -1
- package/dist/machines/index.js +0 -2
- package/dist/machines/index.js.map +1 -1
- package/dist/records/authority.d.ts +23 -0
- package/dist/records/authority.d.ts.map +1 -0
- package/dist/records/authority.js +28 -0
- package/dist/records/authority.js.map +1 -0
- package/dist/records/codec.d.ts +6 -0
- package/dist/records/codec.d.ts.map +1 -0
- package/dist/records/codec.js +42 -0
- package/dist/records/codec.js.map +1 -0
- package/dist/records/contracts.d.ts +46 -0
- package/dist/records/contracts.d.ts.map +1 -0
- package/dist/records/contracts.js +114 -0
- package/dist/records/contracts.js.map +1 -0
- package/dist/records/inbox.d.ts +18 -0
- package/dist/records/inbox.d.ts.map +1 -0
- package/dist/records/inbox.js +34 -0
- package/dist/records/inbox.js.map +1 -0
- package/dist/records/index.d.ts +7 -0
- package/dist/records/index.d.ts.map +1 -0
- package/dist/records/index.js +7 -0
- package/dist/records/index.js.map +1 -0
- package/dist/records/outbox.d.ts +20 -0
- package/dist/records/outbox.d.ts.map +1 -0
- package/dist/records/outbox.js +44 -0
- package/dist/records/outbox.js.map +1 -0
- package/dist/registration/user-ground.d.ts +5 -2
- package/dist/registration/user-ground.d.ts.map +1 -1
- package/dist/registration/user-ground.js +14 -3
- package/dist/registration/user-ground.js.map +1 -1
- package/dist/watching/suspicion.d.ts.map +1 -1
- package/dist/watching/suspicion.js +29 -1
- package/dist/watching/suspicion.js.map +1 -1
- package/dist-cjs/contracts/binding.js +26 -0
- package/dist-cjs/contracts/binding.js.map +1 -0
- package/dist-cjs/contracts/content.js +99 -0
- package/dist-cjs/contracts/content.js.map +1 -0
- package/dist-cjs/contracts/docs.js +56 -0
- package/dist-cjs/contracts/docs.js.map +1 -0
- package/dist-cjs/contracts/events.js +44 -0
- package/dist-cjs/contracts/events.js.map +1 -0
- package/dist-cjs/contracts/frames/gateway.js +39 -0
- package/dist-cjs/contracts/frames/gateway.js.map +1 -0
- package/dist-cjs/contracts/frames/stream.js +20 -0
- package/dist-cjs/contracts/frames/stream.js.map +1 -0
- package/dist-cjs/contracts/frames/tunnel.js +60 -0
- package/dist-cjs/contracts/frames/tunnel.js.map +1 -0
- package/dist-cjs/contracts/index.js +34 -0
- package/dist-cjs/contracts/index.js.map +1 -0
- package/dist-cjs/contracts/presence.js +38 -0
- package/dist-cjs/contracts/presence.js.map +1 -0
- package/dist-cjs/contracts/resources.js +114 -0
- package/dist-cjs/contracts/resources.js.map +1 -0
- package/dist-cjs/contracts/snapshot.js +31 -0
- package/dist-cjs/contracts/snapshot.js.map +1 -0
- package/dist-cjs/contracts/validate.js +34 -0
- package/dist-cjs/contracts/validate.js.map +1 -0
- package/dist-cjs/detection/adapter-contract.js +168 -0
- package/dist-cjs/detection/adapter-contract.js.map +1 -0
- package/dist-cjs/detection/batch.js +71 -0
- package/dist-cjs/detection/batch.js.map +1 -0
- package/dist-cjs/detection/classify.js +48 -0
- package/dist-cjs/detection/classify.js.map +1 -0
- package/dist-cjs/detection/content.js +122 -0
- package/dist-cjs/detection/content.js.map +1 -0
- package/dist-cjs/detection/continuity.js +88 -0
- package/dist-cjs/detection/continuity.js.map +1 -0
- package/dist-cjs/detection/diff.js +193 -0
- package/dist-cjs/detection/diff.js.map +1 -0
- package/dist-cjs/detection/echo.js +25 -0
- package/dist-cjs/detection/echo.js.map +1 -0
- package/dist-cjs/detection/enrollment.js +189 -0
- package/dist-cjs/detection/enrollment.js.map +1 -0
- package/dist-cjs/detection/index.js +57 -0
- package/dist-cjs/detection/index.js.map +1 -0
- package/dist-cjs/detection/record-proposal.js +170 -0
- package/dist-cjs/detection/record-proposal.js.map +1 -0
- package/dist-cjs/detection/refusal.js +44 -0
- package/dist-cjs/detection/refusal.js.map +1 -0
- package/dist-cjs/detection/repository.js +67 -0
- package/dist-cjs/detection/repository.js.map +1 -0
- package/dist-cjs/detection/territory.js +82 -0
- package/dist-cjs/detection/territory.js.map +1 -0
- package/dist-cjs/detection/watch-boundary.js +51 -0
- package/dist-cjs/detection/watch-boundary.js.map +1 -0
- package/dist-cjs/entities/bytes.js +92 -0
- package/dist-cjs/entities/bytes.js.map +1 -0
- package/dist-cjs/entities/cloud.js +171 -0
- package/dist-cjs/entities/cloud.js.map +1 -0
- package/dist-cjs/entities/index.js +39 -0
- package/dist-cjs/entities/index.js.map +1 -0
- package/dist-cjs/entities/moves.js +85 -0
- package/dist-cjs/entities/moves.js.map +1 -0
- package/dist-cjs/entities/repo-states.js +256 -0
- package/dist-cjs/entities/repo-states.js.map +1 -0
- package/dist-cjs/entities/rules.js +216 -0
- package/dist-cjs/entities/rules.js.map +1 -0
- package/dist-cjs/entities/types.js +44 -0
- package/dist-cjs/entities/types.js.map +1 -0
- package/dist-cjs/files/commands.js +120 -0
- package/dist-cjs/files/commands.js.map +1 -0
- package/dist-cjs/files/index.js +19 -0
- package/dist-cjs/files/index.js.map +1 -0
- package/dist-cjs/index.js +39 -0
- package/dist-cjs/index.js.map +1 -0
- package/dist-cjs/machines/arbitration.js +41 -0
- package/dist-cjs/machines/arbitration.js.map +1 -0
- package/dist-cjs/machines/backoff.js +38 -0
- package/dist-cjs/machines/backoff.js.map +1 -0
- package/dist-cjs/machines/bootstrap.js +110 -0
- package/dist-cjs/machines/bootstrap.js.map +1 -0
- package/dist-cjs/machines/chunks.js +72 -0
- package/dist-cjs/machines/chunks.js.map +1 -0
- package/dist-cjs/machines/index.js +28 -0
- package/dist-cjs/machines/index.js.map +1 -0
- package/dist-cjs/machines/presence.js +53 -0
- package/dist-cjs/machines/presence.js.map +1 -0
- package/dist-cjs/merge/index.js +25 -0
- package/dist-cjs/merge/index.js.map +1 -0
- package/dist-cjs/merge/merge3.js +191 -0
- package/dist-cjs/merge/merge3.js.map +1 -0
- package/dist-cjs/package.json +1 -0
- package/dist-cjs/records/authority.js +31 -0
- package/dist-cjs/records/authority.js.map +1 -0
- package/dist-cjs/records/codec.js +48 -0
- package/dist-cjs/records/codec.js.map +1 -0
- package/dist-cjs/records/contracts.js +121 -0
- package/dist-cjs/records/contracts.js.map +1 -0
- package/dist-cjs/records/inbox.js +37 -0
- package/dist-cjs/records/inbox.js.map +1 -0
- package/dist-cjs/records/index.js +23 -0
- package/dist-cjs/records/index.js.map +1 -0
- package/dist-cjs/records/outbox.js +48 -0
- package/dist-cjs/records/outbox.js.map +1 -0
- package/dist-cjs/registration/index.js +19 -0
- package/dist-cjs/registration/index.js.map +1 -0
- package/dist-cjs/registration/user-ground.js +183 -0
- package/dist-cjs/registration/user-ground.js.map +1 -0
- package/dist-cjs/transfer/artifacts.js +75 -0
- package/dist-cjs/transfer/artifacts.js.map +1 -0
- package/dist-cjs/transfer/batches.js +44 -0
- package/dist-cjs/transfer/batches.js.map +1 -0
- package/dist-cjs/transfer/download.js +88 -0
- package/dist-cjs/transfer/download.js.map +1 -0
- package/dist-cjs/transfer/index.js +21 -0
- package/dist-cjs/transfer/index.js.map +1 -0
- package/dist-cjs/transfer/parallel.js +35 -0
- package/dist-cjs/transfer/parallel.js.map +1 -0
- package/dist-cjs/transfer/upload.js +161 -0
- package/dist-cjs/transfer/upload.js.map +1 -0
- package/dist-cjs/watching/coverage.js +54 -0
- package/dist-cjs/watching/coverage.js.map +1 -0
- package/dist-cjs/watching/index.js +24 -0
- package/dist-cjs/watching/index.js.map +1 -0
- package/dist-cjs/watching/suspicion.js +105 -0
- package/dist-cjs/watching/suspicion.js.map +1 -0
- package/dist-cjs/workspace/api.js +66 -0
- package/dist-cjs/workspace/api.js.map +1 -0
- package/dist-cjs/workspace/identity.js +32 -0
- package/dist-cjs/workspace/identity.js.map +1 -0
- package/dist-cjs/workspace/index.js +14 -0
- package/dist-cjs/workspace/index.js.map +1 -0
- package/dist-cjs/workspace/memory-store.js +21 -0
- package/dist-cjs/workspace/memory-store.js.map +1 -0
- package/dist-cjs/workspace/registry.js +98 -0
- package/dist-cjs/workspace/registry.js.map +1 -0
- package/dist-cjs/workspace/types.js +3 -0
- package/dist-cjs/workspace/types.js.map +1 -0
- package/package.json +30 -8
- package/dist/contracts/mutation.d.ts +0 -51
- package/dist/contracts/mutation.d.ts.map +0 -1
- package/dist/contracts/mutation.js +0 -55
- package/dist/contracts/mutation.js.map +0 -1
- package/dist/machines/journal.d.ts +0 -63
- package/dist/machines/journal.d.ts.map +0 -1
- package/dist/machines/journal.js +0 -71
- package/dist/machines/journal.js.map +0 -1
- package/dist/machines/ordering.d.ts +0 -53
- package/dist/machines/ordering.d.ts.map +0 -1
- package/dist/machines/ordering.js +0 -87
- package/dist/machines/ordering.js.map +0 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The exact entity record carried from local Record to cloud acceptance.
|
|
3
|
+
*
|
|
4
|
+
* The entity UUID is the channel. `globalSequence` exists only after the
|
|
5
|
+
* authority accepts the record and is dense independently on that UUID.
|
|
6
|
+
*/
|
|
7
|
+
import { assertRecord } from '../entities/cloud.js';
|
|
8
|
+
import { UUID_PATTERN } from '../entities/types.js';
|
|
9
|
+
import { DETECTED_CHANGE_CONTRACT, } from '../detection/record-proposal.js';
|
|
10
|
+
import { failShape, isNonEmptyString, isRecord, pass } from '../contracts/validate.js';
|
|
11
|
+
export const ENTITY_RECORD_CONTRACT = 'amalgm.entity-record@1';
|
|
12
|
+
const HASH = /^[0-9a-f]{64}$/;
|
|
13
|
+
const FACETS = new Set(['create', 'rename', 'move', 'retype', 'content', 'trash', 'restore']);
|
|
14
|
+
const EXAMPLE = '{ contract: "amalgm.entity-record@1", mutationId: "m1", authorityId: "pvr_...", entityId: "UUID", basedOnState: null, resultState: "64-hex", lastSeenGlobalSequence: 0, change: {...}, createdAt: 1 }';
|
|
15
|
+
const isSequence = (value, positive = false) => typeof value === 'number'
|
|
16
|
+
&& Number.isSafeInteger(value)
|
|
17
|
+
&& value >= (positive ? 1 : 0);
|
|
18
|
+
function checkChange(value) {
|
|
19
|
+
if (!isRecord(value) || value.contract !== DETECTED_CHANGE_CONTRACT) {
|
|
20
|
+
return failShape(EXAMPLE, `change.contract was not ${DETECTED_CHANGE_CONTRACT}`);
|
|
21
|
+
}
|
|
22
|
+
if (typeof value.entityId !== 'string' || !UUID_PATTERN.test(value.entityId)) {
|
|
23
|
+
return failShape(EXAMPLE, 'change.entityId was not an entity UUID');
|
|
24
|
+
}
|
|
25
|
+
if (value.basedOnState !== null
|
|
26
|
+
&& (typeof value.basedOnState !== 'string' || !HASH.test(value.basedOnState))) {
|
|
27
|
+
return failShape(EXAMPLE, 'change.basedOnState was not null or lowercase SHA-256');
|
|
28
|
+
}
|
|
29
|
+
if (!Array.isArray(value.facets) || value.facets.length === 0
|
|
30
|
+
|| value.facets.some((facet) => typeof facet !== 'string' || !FACETS.has(facet))
|
|
31
|
+
|| new Set(value.facets).size !== value.facets.length) {
|
|
32
|
+
return failShape(EXAMPLE, 'change.facets was empty, duplicated, or unknown');
|
|
33
|
+
}
|
|
34
|
+
if (!isRecord(value.replay) || !isNonEmptyString(value.replay.kind)) {
|
|
35
|
+
return failShape(EXAMPLE, 'change.replay was not a replay instruction');
|
|
36
|
+
}
|
|
37
|
+
if (!Array.isArray(value.cargo)) {
|
|
38
|
+
return failShape(EXAMPLE, 'change.cargo was not an array');
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const result = assertRecord(value.result);
|
|
42
|
+
if (result.uuid !== value.entityId) {
|
|
43
|
+
return failShape(EXAMPLE, 'change.entityId did not equal change.result.uuid');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return failShape(EXAMPLE, `change.result was invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
return pass(value);
|
|
50
|
+
}
|
|
51
|
+
export function checkLocalEntityRecord(value) {
|
|
52
|
+
if (!isRecord(value) || value.contract !== ENTITY_RECORD_CONTRACT) {
|
|
53
|
+
return failShape(EXAMPLE, `contract was not ${ENTITY_RECORD_CONTRACT}`);
|
|
54
|
+
}
|
|
55
|
+
for (const field of ['mutationId', 'authorityId']) {
|
|
56
|
+
if (!isNonEmptyString(value[field])) {
|
|
57
|
+
return failShape(EXAMPLE, `${field} was not a non-empty string`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (typeof value.entityId !== 'string' || !UUID_PATTERN.test(value.entityId)) {
|
|
61
|
+
return failShape(EXAMPLE, 'entityId was not an entity UUID');
|
|
62
|
+
}
|
|
63
|
+
if (value.basedOnState !== null
|
|
64
|
+
&& (typeof value.basedOnState !== 'string' || !HASH.test(value.basedOnState))) {
|
|
65
|
+
return failShape(EXAMPLE, 'basedOnState was not null or lowercase SHA-256');
|
|
66
|
+
}
|
|
67
|
+
if (typeof value.resultState !== 'string' || !HASH.test(value.resultState)) {
|
|
68
|
+
return failShape(EXAMPLE, 'resultState was not lowercase SHA-256');
|
|
69
|
+
}
|
|
70
|
+
if (!isSequence(value.lastSeenGlobalSequence) || !isSequence(value.createdAt)) {
|
|
71
|
+
return failShape(EXAMPLE, 'lastSeenGlobalSequence and createdAt must be non-negative safe integers');
|
|
72
|
+
}
|
|
73
|
+
const change = checkChange(value.change);
|
|
74
|
+
if (!change.ok)
|
|
75
|
+
return change;
|
|
76
|
+
if (change.value.entityId !== value.entityId
|
|
77
|
+
|| change.value.basedOnState !== value.basedOnState
|
|
78
|
+
|| change.value.result.version !== value.resultState) {
|
|
79
|
+
return failShape(EXAMPLE, 'record lineage did not exactly match its Detect proposal');
|
|
80
|
+
}
|
|
81
|
+
return pass(value);
|
|
82
|
+
}
|
|
83
|
+
export function checkAcceptedEntityRecord(value) {
|
|
84
|
+
const local = checkLocalEntityRecord(value);
|
|
85
|
+
if (!local.ok)
|
|
86
|
+
return local;
|
|
87
|
+
if (!isRecord(value)
|
|
88
|
+
|| !isSequence(value.globalSequence, true)
|
|
89
|
+
|| !isNonEmptyString(value.actorId)
|
|
90
|
+
|| !isNonEmptyString(value.originDeviceId)
|
|
91
|
+
|| !isSequence(value.acceptedAt)) {
|
|
92
|
+
return failShape(EXAMPLE, 'accepted record lacked a positive sequence or server-derived acceptance fields');
|
|
93
|
+
}
|
|
94
|
+
return pass(value);
|
|
95
|
+
}
|
|
96
|
+
export const entityMutationKey = (record) => `${record.entityId}\u0000${record.mutationId}`;
|
|
97
|
+
export function createLocalEntityRecord(input) {
|
|
98
|
+
const record = Object.freeze({
|
|
99
|
+
contract: ENTITY_RECORD_CONTRACT,
|
|
100
|
+
mutationId: input.mutationId,
|
|
101
|
+
authorityId: input.authorityId,
|
|
102
|
+
entityId: input.change.entityId,
|
|
103
|
+
basedOnState: input.change.basedOnState,
|
|
104
|
+
resultState: input.change.result.version,
|
|
105
|
+
lastSeenGlobalSequence: input.lastSeenGlobalSequence,
|
|
106
|
+
change: input.change,
|
|
107
|
+
createdAt: input.createdAt,
|
|
108
|
+
});
|
|
109
|
+
const checked = checkLocalEntityRecord(record);
|
|
110
|
+
if (!checked.ok)
|
|
111
|
+
throw new Error(checked.error);
|
|
112
|
+
return record;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/records/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Pure per-entity Receive law. Apply is intentionally absent. */
|
|
2
|
+
import type { AcceptedEntityRecord } from './contracts.js';
|
|
3
|
+
export type InboxDecision = {
|
|
4
|
+
readonly kind: 'insert';
|
|
5
|
+
readonly record: AcceptedEntityRecord;
|
|
6
|
+
readonly receivedThrough: number;
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: 'duplicate';
|
|
9
|
+
readonly record: AcceptedEntityRecord;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'gap';
|
|
12
|
+
readonly entityId: string;
|
|
13
|
+
readonly after: number;
|
|
14
|
+
readonly received: number;
|
|
15
|
+
};
|
|
16
|
+
/** Decide one durable inbox transaction against this entity's own cursor. */
|
|
17
|
+
export declare function receiveEntityRecord(receivedThrough: number, record: AcceptedEntityRecord, existing: AcceptedEntityRecord | null): InboxDecision;
|
|
18
|
+
//# sourceMappingURL=inbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/records/inbox.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3D,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACpG;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3G,6EAA6E;AAC7E,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GACpC,aAAa,CA6Bf"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Pure per-entity Receive law. Apply is intentionally absent. */
|
|
2
|
+
import { encodeEntityRecord } from './codec.js';
|
|
3
|
+
/** Decide one durable inbox transaction against this entity's own cursor. */
|
|
4
|
+
export function receiveEntityRecord(receivedThrough, record, existing) {
|
|
5
|
+
if (!Number.isSafeInteger(receivedThrough) || receivedThrough < 0) {
|
|
6
|
+
throw new Error('received-through must be a non-negative safe integer');
|
|
7
|
+
}
|
|
8
|
+
if (record.globalSequence <= receivedThrough) {
|
|
9
|
+
if (existing === null) {
|
|
10
|
+
throw new Error('entity cursor claims a sequence that is absent from the inbox');
|
|
11
|
+
}
|
|
12
|
+
if (encodeEntityRecord(existing) !== encodeEntityRecord(record)) {
|
|
13
|
+
throw new Error('one entity sequence cannot name two accepted record bytes');
|
|
14
|
+
}
|
|
15
|
+
return Object.freeze({ kind: 'duplicate', record: existing });
|
|
16
|
+
}
|
|
17
|
+
if (existing !== null) {
|
|
18
|
+
throw new Error('inbox contains a sequence beyond its entity cursor');
|
|
19
|
+
}
|
|
20
|
+
if (record.globalSequence !== receivedThrough + 1) {
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
kind: 'gap',
|
|
23
|
+
entityId: record.entityId,
|
|
24
|
+
after: receivedThrough,
|
|
25
|
+
received: record.globalSequence,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
kind: 'insert',
|
|
30
|
+
record,
|
|
31
|
+
receivedThrough: record.globalSequence,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/records/inbox.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAGlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAOhD,6EAA6E;AAC7E,MAAM,UAAU,mBAAmB,CACjC,eAAuB,EACvB,MAA4B,EAC5B,QAAqC;IAErC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAK,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,KAAK,eAAe,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,MAAM,CAAC,cAAc;SAChC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,QAAQ;QACd,MAAM;QACN,eAAe,EAAE,MAAM,CAAC,cAAc;KACvC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Entity Record, local Outbox, cloud acceptance, and local Inbox laws. */
|
|
2
|
+
export * from './authority.js';
|
|
3
|
+
export * from './codec.js';
|
|
4
|
+
export * from './contracts.js';
|
|
5
|
+
export * from './inbox.js';
|
|
6
|
+
export * from './outbox.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/records/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAE3E,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Entity Record, local Outbox, cloud acceptance, and local Inbox laws. */
|
|
2
|
+
export * from './authority.js';
|
|
3
|
+
export * from './codec.js';
|
|
4
|
+
export * from './contracts.js';
|
|
5
|
+
export * from './inbox.js';
|
|
6
|
+
export * from './outbox.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/records/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAE3E,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Pure laws for the local-only record outbox. */
|
|
2
|
+
import type { AcceptedEntityRecord, LocalEntityRecord } from './contracts.js';
|
|
3
|
+
export type OutboxRow = {
|
|
4
|
+
readonly record: LocalEntityRecord;
|
|
5
|
+
readonly status: 'pending';
|
|
6
|
+
readonly globalSequence: null;
|
|
7
|
+
} | {
|
|
8
|
+
readonly record: LocalEntityRecord;
|
|
9
|
+
readonly status: 'accepted';
|
|
10
|
+
readonly globalSequence: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Choose at most one pending row per entity. This preserves causality within
|
|
14
|
+
* one UUID channel while allowing unrelated entity channels to send in
|
|
15
|
+
* parallel. Input must be in durable local insertion order.
|
|
16
|
+
*/
|
|
17
|
+
export declare function nextEntitySends(rows: readonly OutboxRow[]): readonly OutboxRow[];
|
|
18
|
+
/** Stamp a retained local receipt from the authority's exact acknowledgement. */
|
|
19
|
+
export declare function acceptOutboxRow(row: OutboxRow, accepted: AcceptedEntityRecord): OutboxRow;
|
|
20
|
+
//# sourceMappingURL=outbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/records/outbox.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAElD,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAA;CAAE,GACjG;IAAE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EAAE,CAUhF;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,GAAG,SAAS,CA2BzF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Pure laws for the local-only record outbox. */
|
|
2
|
+
import { encodeEntityRecord } from './codec.js';
|
|
3
|
+
/**
|
|
4
|
+
* Choose at most one pending row per entity. This preserves causality within
|
|
5
|
+
* one UUID channel while allowing unrelated entity channels to send in
|
|
6
|
+
* parallel. Input must be in durable local insertion order.
|
|
7
|
+
*/
|
|
8
|
+
export function nextEntitySends(rows) {
|
|
9
|
+
const selected = [];
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
for (const row of rows) {
|
|
12
|
+
if (row.status !== 'pending')
|
|
13
|
+
continue;
|
|
14
|
+
if (seen.has(row.record.entityId))
|
|
15
|
+
continue;
|
|
16
|
+
seen.add(row.record.entityId);
|
|
17
|
+
selected.push(row);
|
|
18
|
+
}
|
|
19
|
+
return Object.freeze(selected);
|
|
20
|
+
}
|
|
21
|
+
/** Stamp a retained local receipt from the authority's exact acknowledgement. */
|
|
22
|
+
export function acceptOutboxRow(row, accepted) {
|
|
23
|
+
if (row.record.authorityId !== accepted.authorityId
|
|
24
|
+
|| row.record.entityId !== accepted.entityId
|
|
25
|
+
|| row.record.mutationId !== accepted.mutationId) {
|
|
26
|
+
throw new Error('an acknowledgement cannot stamp a different outbox record');
|
|
27
|
+
}
|
|
28
|
+
const { globalSequence: _globalSequence, actorId: _actorId, originDeviceId: _originDeviceId, acceptedAt: _acceptedAt, ...acceptedLocal } = accepted;
|
|
29
|
+
if (encodeEntityRecord(row.record) !== encodeEntityRecord(acceptedLocal)) {
|
|
30
|
+
throw new Error('an acknowledgement cannot change the outbox record bytes');
|
|
31
|
+
}
|
|
32
|
+
if (row.status === 'accepted') {
|
|
33
|
+
if (row.globalSequence !== accepted.globalSequence) {
|
|
34
|
+
throw new Error('one outbox record cannot have two official entity sequences');
|
|
35
|
+
}
|
|
36
|
+
return row;
|
|
37
|
+
}
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
record: row.record,
|
|
40
|
+
status: 'accepted',
|
|
41
|
+
globalSequence: accepted.globalSequence,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=outbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/records/outbox.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAGlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMhD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAA0B;IACxD,MAAM,QAAQ,GAAgB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,SAAS;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,SAAS;QAC5C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,GAAc,EAAE,QAA8B;IAC5E,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;WAC9C,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ;WACzC,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,EACJ,cAAc,EAAE,eAAe,EAC/B,OAAO,EAAE,QAAQ,EACjB,cAAc,EAAE,eAAe,EAC/B,UAAU,EAAE,WAAW,EACvB,GAAG,aAAa,EACjB,GAAG,QAAQ,CAAC;IACb,IAAI,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,kBAAkB,CAAC,aAAa,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,IAAI,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,cAAc,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,UAAU;QAClB,cAAc,EAAE,QAAQ,CAAC,cAAc;KACxC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -19,7 +19,9 @@ export interface CloudUserGround {
|
|
|
19
19
|
readonly checksum: string;
|
|
20
20
|
readonly snapshot: CloudSnapshot;
|
|
21
21
|
}
|
|
22
|
-
/** The local
|
|
22
|
+
/** The local materialization plus machine-only placement. A cold snapshot may
|
|
23
|
+
* lag durable entity records; recordsBeyondSnapshot prevents login from
|
|
24
|
+
* replacing that newer local truth with the older bootstrap image. */
|
|
23
25
|
export interface LocalUserGround {
|
|
24
26
|
readonly userId: string;
|
|
25
27
|
readonly userEmail: string;
|
|
@@ -27,6 +29,7 @@ export interface LocalUserGround {
|
|
|
27
29
|
readonly localRoot: string;
|
|
28
30
|
readonly sqlitePath: string;
|
|
29
31
|
readonly records: readonly CloudEntityRecord[];
|
|
32
|
+
readonly recordsBeyondSnapshot?: boolean;
|
|
30
33
|
}
|
|
31
34
|
export interface UserGroundWatchEvidence {
|
|
32
35
|
readonly active: true;
|
|
@@ -69,7 +72,7 @@ export interface UserGroundConvergence {
|
|
|
69
72
|
readonly cloudResourceId: string;
|
|
70
73
|
readonly cloudVersion: number;
|
|
71
74
|
readonly cloudHead: string;
|
|
72
|
-
readonly mode: 'initialized' | 'materialized' | 'current';
|
|
75
|
+
readonly mode: 'initialized' | 'materialized' | 'current' | 'syncing';
|
|
73
76
|
readonly entityCount: number;
|
|
74
77
|
readonly watcherRoots: number;
|
|
75
78
|
readonly watching: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-ground.d.ts","sourceRoot":"","sources":["../../src/registration/user-ground.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CAClC;AAED
|
|
1
|
+
{"version":3,"file":"user-ground.d.ts","sourceRoot":"","sources":["../../src/registration/user-ground.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,7 +60,13 @@ function assertLocal(value, identity) {
|
|
|
60
60
|
const snapshot = snapshotFromRecords(local.records || []);
|
|
61
61
|
if (snapshot.records.length === 0)
|
|
62
62
|
throw new Error('local user-ground graph is empty');
|
|
63
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
...identity,
|
|
65
|
+
localRoot,
|
|
66
|
+
sqlitePath,
|
|
67
|
+
records: snapshot.records,
|
|
68
|
+
...(local.recordsBeyondSnapshot === true ? { recordsBeyondSnapshot: true } : {}),
|
|
69
|
+
};
|
|
64
70
|
}
|
|
65
71
|
/** Select the authenticated user's core root without materializing sibling
|
|
66
72
|
* workspace roots. The canonical email is the declared root name. */
|
|
@@ -135,7 +141,11 @@ export async function convergeUserGround(input, ports) {
|
|
|
135
141
|
const current = assertLocal(currentValue, identity);
|
|
136
142
|
if (sameRecords(travelingRecords(userGroundRecords(current.records, identity.userEmail)), userGroundRecords(cloud.snapshot.records, identity.userEmail))) {
|
|
137
143
|
local = current;
|
|
138
|
-
mode = 'current';
|
|
144
|
+
mode = current.recordsBeyondSnapshot === true ? 'syncing' : 'current';
|
|
145
|
+
}
|
|
146
|
+
else if (current.recordsBeyondSnapshot === true) {
|
|
147
|
+
local = current;
|
|
148
|
+
mode = 'syncing';
|
|
139
149
|
}
|
|
140
150
|
else {
|
|
141
151
|
local = assertLocal(await ports.local.install(identity, cloud), identity);
|
|
@@ -151,7 +161,8 @@ export async function convergeUserGround(input, ports) {
|
|
|
151
161
|
}
|
|
152
162
|
const watch = assertWatch(await ports.local.watch(identity, cloud));
|
|
153
163
|
const finalLocal = assertLocal(await ports.local.inspect(identity), identity);
|
|
154
|
-
|
|
164
|
+
if (finalLocal.recordsBeyondSnapshot !== true)
|
|
165
|
+
assertSameGraph(finalLocal, cloud);
|
|
155
166
|
return {
|
|
156
167
|
...identity,
|
|
157
168
|
localRoot: finalLocal.localRoot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-ground.js","sourceRoot":"","sources":["../../src/registration/user-ground.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,gBAAgB,GAIjB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"user-ground.js","sourceRoot":"","sources":["../../src/registration/user-ground.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,gBAAgB,GAIjB,MAAM,sBAAsB,CAAC;AA6E9B,MAAM,IAAI,GAAG,gBAAgB,CAAC;AAE9B,SAAS,QAAQ,CAAC,KAAc,EAAE,IAAY;IAC5C,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,cAAc,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAyB;IAClD,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC;QAC1C,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,WAAW,EAAE;QACjE,QAAQ,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC;KACjD,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,KAAc,EACd,UAAkB,EAClB,SAAoB;IAEpB,MAAM,KAAK,GAAG,KAAwC,CAAC;IACvD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU;WACxC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;WACjE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IACpE,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjD,IAAI,QAAQ,KAAK,KAAK,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACjG,OAAO;QACL,UAAU;QACV,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAC9B,QAAQ;QACR,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,WAAW,CAAC,KAAc,EAAE,QAA4B;IAC/D,MAAM,KAAK,GAAG,KAAwC,CAAC;IACvD,IAAI,CAAC,KAAK;WACL,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;WAChC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,SAAS;WAClE,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;IACtG,CAAC;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC1D,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACvF,OAAO;QACL,GAAG,QAAQ;QACX,SAAS;QACT,UAAU;QACV,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,GAAG,CAAC,KAAK,CAAC,qBAAqB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjF,CAAC;AACJ,CAAC;AAED;qEACqE;AACrE,MAAM,UAAU,iBAAiB,CAC/B,OAAqC,EACrC,SAAiB;IAEjB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IACvE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/C,MAAM,CAAC,MAAM,KAAK,QAAQ;WACvB,MAAM,CAAC,UAAU,KAAK,IAAI;WAC1B,MAAM,CAAC,IAAI,KAAK,WAAW;WAC3B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,OAAO,OAAO,EAAE,CAAC;QACf,OAAO,GAAG,KAAK,CAAC;QAChB,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC1B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,eAAe,CAAC,KAAsB,EAAE,KAAsB;IACrE,IAAI,CAAC,WAAW,CACd,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,EACnE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAC3D,EAAE,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,KAAK,GAAG,KAAgD,CAAC;IAC/D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrG,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAyB,EACzB,KAAiC;IAEjC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,uBAAuB,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,KAAsB,CAAC;IAC3B,IAAI,KAAsB,CAAC;IAC3B,IAAI,IAAmC,CAAC;IAExC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvF,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACpE,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACpC,KAAK,GAAG,WAAW,CAAC;YACpB,IAAI,GAAG,aAAa,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC1E,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9B,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YACxD,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YACpD,IAAI,WAAW,CACb,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EACxE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAC9D,EAAE,CAAC;gBACF,KAAK,GAAG,OAAO,CAAC;gBAChB,IAAI,GAAG,OAAO,CAAC,qBAAqB,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,CAAC;iBAAM,IAAI,OAAO,CAAC,qBAAqB,KAAK,IAAI,EAAE,CAAC;gBAClD,KAAK,GAAG,OAAO,CAAC;gBAChB,IAAI,GAAG,SAAS,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,KAAK,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;gBAC1E,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC9B,IAAI,GAAG,cAAc,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC1E,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9B,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9E,IAAI,UAAU,CAAC,qBAAqB,KAAK,IAAI;QAAE,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAClF,OAAO;QACL,GAAG,QAAQ;QACX,SAAS,EAAE,UAAU,CAAC,SAAS;QAC/B,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,eAAe,EAAE,KAAK,CAAC,UAAU;QACjC,YAAY,EAAE,KAAK,CAAC,OAAO;QAC3B,SAAS,EAAE,KAAK,CAAC,QAAQ;QACzB,IAAI;QACJ,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM;QACjF,YAAY,EAAE,KAAK,CAAC,KAAK;QACzB,QAAQ,EAAE,IAAI;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suspicion.d.ts","sourceRoot":"","sources":["../../src/watching/suspicion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAChC,iFAAiF;IACjF,UAAU,IAAI,IAAI,CAAC;IACnB,uDAAuD;IACvD,QAAQ,IAAI,iBAAiB,CAAC;IAC9B,iEAAiE;IACjE,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"suspicion.d.ts","sourceRoot":"","sources":["../../src/watching/suspicion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAChC,iFAAiF;IACjF,UAAU,IAAI,IAAI,CAAC;IACnB,uDAAuD;IACvD,QAAQ,IAAI,iBAAiB,CAAC;IAC9B,iEAAiE;IACjE,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAsBD,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAGvF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,SAAM,GAAG,cAAc,CA8D9D"}
|
|
@@ -11,6 +11,21 @@ const normalizeHint = (path) => {
|
|
|
11
11
|
return null;
|
|
12
12
|
return path;
|
|
13
13
|
};
|
|
14
|
+
const commonDirectory = (paths) => {
|
|
15
|
+
const split = paths.map((path) => path.split('/'));
|
|
16
|
+
const shortest = Math.min(...split.map((segments) => segments.length));
|
|
17
|
+
const common = [];
|
|
18
|
+
for (let index = 0; index < shortest; index += 1) {
|
|
19
|
+
const segment = split[0]?.[index];
|
|
20
|
+
if (!segment || split.some((candidate) => candidate[index] !== segment))
|
|
21
|
+
break;
|
|
22
|
+
common.push(segment);
|
|
23
|
+
}
|
|
24
|
+
// A common leaf name is not proof that it is a directory. Widen one level.
|
|
25
|
+
if (paths.some((path) => path === common.join('/')))
|
|
26
|
+
common.pop();
|
|
27
|
+
return common.join('/');
|
|
28
|
+
};
|
|
14
29
|
/** A named directory suspects every descendant. Exact files suspect themselves. */
|
|
15
30
|
export function pathIsSuspect(path, suspects) {
|
|
16
31
|
if (suspects === null)
|
|
@@ -40,10 +55,23 @@ export function createSuspicionScope(cap = 512) {
|
|
|
40
55
|
return;
|
|
41
56
|
}
|
|
42
57
|
generation += 1;
|
|
58
|
+
const covering = [...paths.keys()].find((candidate) => normalized === candidate || normalized.startsWith(`${candidate}/`));
|
|
59
|
+
if (covering) {
|
|
60
|
+
paths.set(covering, generation);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
for (const candidate of paths.keys()) {
|
|
64
|
+
if (candidate.startsWith(`${normalized}/`))
|
|
65
|
+
paths.delete(candidate);
|
|
66
|
+
}
|
|
43
67
|
paths.set(normalized, generation);
|
|
44
68
|
if (paths.size > cap) {
|
|
45
|
-
|
|
69
|
+
const ancestor = commonDirectory([...paths.keys()]);
|
|
46
70
|
paths.clear();
|
|
71
|
+
if (ancestor)
|
|
72
|
+
paths.set(ancestor, generation);
|
|
73
|
+
else
|
|
74
|
+
allGeneration = generation;
|
|
47
75
|
}
|
|
48
76
|
},
|
|
49
77
|
suspectAll: suspectEverything,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suspicion.js","sourceRoot":"","sources":["../../src/watching/suspicion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,MAAM,aAAa,GAAG,CAAC,IAAY,EAAiB,EAAE;IACpD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACpG,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAkC;IAC5E,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAG,GAAG,GAAG;IAC5C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACnG,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,UAAU,IAAI,CAAC,CAAC;QAChB,aAAa,GAAG,UAAU,CAAC;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,CAAC,IAAI;YACP,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,iBAAiB,EAAE,CAAC;gBACpB,OAAO;YACT,CAAC;YACD,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,iBAAiB,EAAE,CAAC;gBACpB,OAAO;YACT,CAAC;YACD,UAAU,IAAI,CAAC,CAAC;YAChB,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI,GAAG,GAAG,EAAE,CAAC;gBACrB,
|
|
1
|
+
{"version":3,"file":"suspicion.js","sourceRoot":"","sources":["../../src/watching/suspicion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The binding — `live.bind(surface, channel)` (realtime-sdk.md).
|
|
4
|
+
*
|
|
5
|
+
* The surface knows what the user is looking at and what counts as one
|
|
6
|
+
* edit. The channel identifies the shared thing and its delivery class.
|
|
7
|
+
* The binding moves changes both ways and exposes honest lifecycle state:
|
|
8
|
+
* a socket being open is never `live` (axiom 7).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.BINDING_STATES = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* Connection lifecycle vocabulary (realtime-sdk.md §7). `live` means the
|
|
14
|
+
* snapshot is applied AND ordered delivery is confirmed; `degraded` means
|
|
15
|
+
* delivery works through a slower fallback (e.g. gateway poll).
|
|
16
|
+
*/
|
|
17
|
+
exports.BINDING_STATES = [
|
|
18
|
+
'connecting',
|
|
19
|
+
'hydrating',
|
|
20
|
+
'live',
|
|
21
|
+
'degraded',
|
|
22
|
+
'reconnecting',
|
|
23
|
+
'blocked',
|
|
24
|
+
'revoked',
|
|
25
|
+
];
|
|
26
|
+
//# sourceMappingURL=binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binding.js","sourceRoot":"","sources":["../../src/contracts/binding.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAaH;;;;GAIG;AACU,QAAA,cAAc,GAAG;IAC5B,YAAY;IACZ,WAAW;IACX,MAAM;IACN,UAAU;IACV,cAAc;IACd,SAAS;IACT,SAAS;CACD,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Content manifests — the wire shape of immutable entity bytes.
|
|
4
|
+
*
|
|
5
|
+
* An entity artifact travels as bounded, content-addressed blocks named by a
|
|
6
|
+
* manifest. Every writer derives the same manifest from
|
|
7
|
+
* the same bytes, so manifests are idempotent facts, never negotiations.
|
|
8
|
+
*
|
|
9
|
+
* The chunk rule is `bytes <= CHUNK_BYTES`, never an exact size — older,
|
|
10
|
+
* smaller chunks remain valid forever. Capture, storage, and upload are
|
|
11
|
+
* host effects; this file owns the shape and its laws.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.MAX_CONTENT_BLOCKS = exports.CHUNK_BYTES = exports.MAX_CONTENT_BLOCK_BYTES = exports.MIN_CONTENT_BLOCK_BYTES = exports.CONTENT_CONTRACT = exports.LEGACY_CONTENT_CONTRACT = void 0;
|
|
15
|
+
exports.checkContentManifest = checkContentManifest;
|
|
16
|
+
exports.manifestFromChunks = manifestFromChunks;
|
|
17
|
+
exports.contentBlockSize = contentBlockSize;
|
|
18
|
+
exports.chunkSizes = chunkSizes;
|
|
19
|
+
const validate_js_1 = require("./validate.js");
|
|
20
|
+
/** Version 3 changes only the canonical writer layout: ordinary files begin
|
|
21
|
+
* at Dropbox's stable 4 MiB block size. Version 2 remains readable because
|
|
22
|
+
* immutable cloud heads created by an older writer must still materialize. */
|
|
23
|
+
exports.LEGACY_CONTENT_CONTRACT = 'amalgm-entity-content@2';
|
|
24
|
+
exports.CONTENT_CONTRACT = 'amalgm-entity-content@3';
|
|
25
|
+
exports.MIN_CONTENT_BLOCK_BYTES = 4 * 1024 * 1024;
|
|
26
|
+
exports.MAX_CONTENT_BLOCK_BYTES = 16 * 1024 * 1024;
|
|
27
|
+
/** Maximum accepted block size. Kept as the public manifest-bound name. */
|
|
28
|
+
exports.CHUNK_BYTES = exports.MAX_CONTENT_BLOCK_BYTES;
|
|
29
|
+
exports.MAX_CONTENT_BLOCKS = 2_000;
|
|
30
|
+
const HASH = /^[0-9a-f]{64}$/;
|
|
31
|
+
/**
|
|
32
|
+
* Validate and normalize a manifest. The laws, in conviction order:
|
|
33
|
+
* well-formed hashes; every chunk within the bound; chunk bytes sum to the
|
|
34
|
+
* total; empty content has no chunks. Error phrases match the engine's —
|
|
35
|
+
* they are the ratified refusal text.
|
|
36
|
+
*/
|
|
37
|
+
function checkContentManifest(input, expectedHash = null) {
|
|
38
|
+
if (!(0, validate_js_1.isRecord)(input) ||
|
|
39
|
+
(input.contract !== exports.CONTENT_CONTRACT && input.contract !== exports.LEGACY_CONTENT_CONTRACT) ||
|
|
40
|
+
typeof input.contentHash !== 'string' ||
|
|
41
|
+
!HASH.test(input.contentHash) ||
|
|
42
|
+
(expectedHash !== null && input.contentHash !== expectedHash) ||
|
|
43
|
+
!Number.isSafeInteger(input.bytes) ||
|
|
44
|
+
input.bytes < 0 ||
|
|
45
|
+
!Array.isArray(input.chunks) ||
|
|
46
|
+
input.chunks.length > exports.MAX_CONTENT_BLOCKS ||
|
|
47
|
+
input.chunks.some((chunk) => !(0, validate_js_1.isRecord)(chunk) ||
|
|
48
|
+
!HASH.test(String(chunk.sha256 ?? '')) ||
|
|
49
|
+
!Number.isSafeInteger(chunk.bytes) ||
|
|
50
|
+
chunk.bytes < 1 ||
|
|
51
|
+
chunk.bytes > exports.CHUNK_BYTES)) {
|
|
52
|
+
return (0, validate_js_1.fail)('entity content manifest is invalid');
|
|
53
|
+
}
|
|
54
|
+
const bytes = input.bytes;
|
|
55
|
+
const chunks = input.chunks;
|
|
56
|
+
if (chunks.reduce((total, chunk) => total + chunk.bytes, 0) !== bytes) {
|
|
57
|
+
return (0, validate_js_1.fail)('entity content manifest byte count is invalid');
|
|
58
|
+
}
|
|
59
|
+
if (bytes === 0 && chunks.length !== 0) {
|
|
60
|
+
return (0, validate_js_1.fail)('empty entity content must have no chunks');
|
|
61
|
+
}
|
|
62
|
+
return (0, validate_js_1.pass)({
|
|
63
|
+
contract: input.contract,
|
|
64
|
+
contentHash: input.contentHash,
|
|
65
|
+
bytes,
|
|
66
|
+
chunks: chunks.map((chunk) => ({ sha256: chunk.sha256, bytes: chunk.bytes })),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Derive the manifest for already-chunked bytes. The host reads and hashes
|
|
71
|
+
* (sha256 hex of each part and of the whole); this seals the shape so a
|
|
72
|
+
* hand-built manifest cannot drift from the derivation rule.
|
|
73
|
+
*/
|
|
74
|
+
function manifestFromChunks(contentHash, chunks) {
|
|
75
|
+
return checkContentManifest({ contract: exports.CONTENT_CONTRACT, contentHash, bytes: chunks.reduce((t, c) => t + c.bytes, 0), chunks }, contentHash);
|
|
76
|
+
}
|
|
77
|
+
/** Dropbox-sized cold blocks, widened by Syncthing's adaptive rule only when
|
|
78
|
+
* needed to keep a manifest below 2,000 blocks, capped at 16 MiB. */
|
|
79
|
+
function contentBlockSize(totalBytes) {
|
|
80
|
+
if (!Number.isSafeInteger(totalBytes) || totalBytes < 0)
|
|
81
|
+
return exports.MIN_CONTENT_BLOCK_BYTES;
|
|
82
|
+
let bytes = exports.MIN_CONTENT_BLOCK_BYTES;
|
|
83
|
+
while (Math.ceil(totalBytes / bytes) > exports.MAX_CONTENT_BLOCKS && bytes < exports.MAX_CONTENT_BLOCK_BYTES) {
|
|
84
|
+
bytes *= 2;
|
|
85
|
+
}
|
|
86
|
+
return bytes;
|
|
87
|
+
}
|
|
88
|
+
/** Split a byte count into adaptive full blocks, then the remainder. */
|
|
89
|
+
function chunkSizes(totalBytes) {
|
|
90
|
+
if (!Number.isSafeInteger(totalBytes) || totalBytes < 0)
|
|
91
|
+
return [];
|
|
92
|
+
const blockBytes = contentBlockSize(totalBytes);
|
|
93
|
+
const sizes = [];
|
|
94
|
+
for (let remaining = totalBytes; remaining > 0; remaining -= blockBytes) {
|
|
95
|
+
sizes.push(Math.min(remaining, blockBytes));
|
|
96
|
+
}
|
|
97
|
+
return sizes;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/contracts/content.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAqCH,oDAoCC;AAOD,gDAQC;AAID,4CAOC;AAGD,gCAQC;AA5GD,+CAAmE;AAEnE;;8EAE8E;AACjE,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AACpD,QAAA,gBAAgB,GAAG,yBAAyB,CAAC;AAG7C,QAAA,uBAAuB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1C,QAAA,uBAAuB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AACxD,2EAA2E;AAC9D,QAAA,WAAW,GAAG,+BAAuB,CAAC;AACtC,QAAA,kBAAkB,GAAG,KAAK,CAAC;AAExC,MAAM,IAAI,GAAG,gBAAgB,CAAC;AAc9B;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,KAAc,EAAE,eAA8B,IAAI;IACrF,IACE,CAAC,IAAA,sBAAQ,EAAC,KAAK,CAAC;QAChB,CAAC,KAAK,CAAC,QAAQ,KAAK,wBAAgB,IAAI,KAAK,CAAC,QAAQ,KAAK,+BAAuB,CAAC;QACnF,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;QACrC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAC7B,CAAC,YAAY,KAAK,IAAI,IAAI,KAAK,CAAC,WAAW,KAAK,YAAY,CAAC;QAC7D,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;QACjC,KAAK,CAAC,KAAgB,GAAG,CAAC;QAC3B,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;QAC5B,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,0BAAkB;QACxC,KAAK,CAAC,MAAM,CAAC,IAAI,CACf,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,IAAA,sBAAQ,EAAC,KAAK,CAAC;YAChB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;YACjC,KAAK,CAAC,KAAgB,GAAG,CAAC;YAC1B,KAAK,CAAC,KAAgB,GAAG,mBAAW,CACxC,EACD,CAAC;QACD,OAAO,IAAA,kBAAI,EAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAe,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,MAA0D,CAAC;IAChF,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QACtE,OAAO,IAAA,kBAAI,EAAC,+CAA+C,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,IAAA,kBAAI,EAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAA,kBAAI,EAAC;QACV,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK;QACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;KAC9E,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAChC,WAAmB,EACnB,MAA+B;IAE/B,OAAO,oBAAoB,CACzB,EAAE,QAAQ,EAAE,wBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EACnG,WAAW,CACZ,CAAC;AACJ,CAAC;AAED;qEACqE;AACrE,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,+BAAuB,CAAC;IACxF,IAAI,KAAK,GAAG,+BAAuB,CAAC;IACpC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,0BAAkB,IAAI,KAAK,GAAG,+BAAuB,EAAE,CAAC;QAC7F,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wEAAwE;AACxE,SAAgB,UAAU,CAAC,UAAkB;IAC3C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnE,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,SAAS,GAAG,UAAU,EAAE,SAAS,GAAG,CAAC,EAAE,SAAS,IAAI,UAAU,EAAE,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|