@amalgm/live 0.2.29 → 0.2.31

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.
Files changed (93) hide show
  1. package/PURPOSE.md +37 -2
  2. package/README.md +1 -0
  3. package/dist/apply/content-results.d.ts +26 -0
  4. package/dist/apply/content-results.d.ts.map +1 -0
  5. package/dist/apply/content-results.js +52 -0
  6. package/dist/apply/content-results.js.map +1 -0
  7. package/dist/apply/contracts.d.ts +191 -0
  8. package/dist/apply/contracts.d.ts.map +1 -0
  9. package/dist/apply/contracts.js +47 -0
  10. package/dist/apply/contracts.js.map +1 -0
  11. package/dist/apply/index.d.ts +10 -0
  12. package/dist/apply/index.d.ts.map +1 -0
  13. package/dist/apply/index.js +10 -0
  14. package/dist/apply/index.js.map +1 -0
  15. package/dist/apply/local-work.d.ts +10 -0
  16. package/dist/apply/local-work.d.ts.map +1 -0
  17. package/dist/apply/local-work.js +17 -0
  18. package/dist/apply/local-work.js.map +1 -0
  19. package/dist/apply/plans.d.ts +14 -0
  20. package/dist/apply/plans.d.ts.map +1 -0
  21. package/dist/apply/plans.js +183 -0
  22. package/dist/apply/plans.js.map +1 -0
  23. package/dist/apply/rail.d.ts +25 -0
  24. package/dist/apply/rail.d.ts.map +1 -0
  25. package/dist/apply/rail.js +304 -0
  26. package/dist/apply/rail.js.map +1 -0
  27. package/dist/apply/repository-result.d.ts +25 -0
  28. package/dist/apply/repository-result.d.ts.map +1 -0
  29. package/dist/apply/repository-result.js +83 -0
  30. package/dist/apply/repository-result.js.map +1 -0
  31. package/dist/apply/selection.d.ts +14 -0
  32. package/dist/apply/selection.d.ts.map +1 -0
  33. package/dist/apply/selection.js +63 -0
  34. package/dist/apply/selection.js.map +1 -0
  35. package/dist/apply/type-adapters.d.ts +13 -0
  36. package/dist/apply/type-adapters.d.ts.map +1 -0
  37. package/dist/apply/type-adapters.js +37 -0
  38. package/dist/apply/type-adapters.js.map +1 -0
  39. package/dist/detection/adapter-contract.d.ts +11 -8
  40. package/dist/detection/adapter-contract.d.ts.map +1 -1
  41. package/dist/detection/adapter-contract.js +5 -5
  42. package/dist/detection/adapter-contract.js.map +1 -1
  43. package/dist/detection/echo.d.ts +1 -1
  44. package/dist/detection/echo.d.ts.map +1 -1
  45. package/dist/detection/echo.js +8 -1
  46. package/dist/detection/echo.js.map +1 -1
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/records/index.d.ts +2 -0
  52. package/dist/records/index.d.ts.map +1 -1
  53. package/dist/records/index.js +2 -0
  54. package/dist/records/index.js.map +1 -1
  55. package/dist/records/rail.d.ts +97 -0
  56. package/dist/records/rail.d.ts.map +1 -0
  57. package/dist/records/rail.js +250 -0
  58. package/dist/records/rail.js.map +1 -0
  59. package/dist/records/wire.d.ts +63 -0
  60. package/dist/records/wire.d.ts.map +1 -0
  61. package/dist/records/wire.js +86 -0
  62. package/dist/records/wire.js.map +1 -0
  63. package/dist-cjs/apply/content-results.js +57 -0
  64. package/dist-cjs/apply/content-results.js.map +1 -0
  65. package/dist-cjs/apply/contracts.js +53 -0
  66. package/dist-cjs/apply/contracts.js.map +1 -0
  67. package/dist-cjs/apply/index.js +28 -0
  68. package/dist-cjs/apply/index.js.map +1 -0
  69. package/dist-cjs/apply/local-work.js +20 -0
  70. package/dist-cjs/apply/local-work.js.map +1 -0
  71. package/dist-cjs/apply/plans.js +187 -0
  72. package/dist-cjs/apply/plans.js.map +1 -0
  73. package/dist-cjs/apply/rail.js +308 -0
  74. package/dist-cjs/apply/rail.js.map +1 -0
  75. package/dist-cjs/apply/repository-result.js +86 -0
  76. package/dist-cjs/apply/repository-result.js.map +1 -0
  77. package/dist-cjs/apply/selection.js +66 -0
  78. package/dist-cjs/apply/selection.js.map +1 -0
  79. package/dist-cjs/apply/type-adapters.js +41 -0
  80. package/dist-cjs/apply/type-adapters.js.map +1 -0
  81. package/dist-cjs/detection/adapter-contract.js +5 -5
  82. package/dist-cjs/detection/adapter-contract.js.map +1 -1
  83. package/dist-cjs/detection/echo.js +8 -1
  84. package/dist-cjs/detection/echo.js.map +1 -1
  85. package/dist-cjs/index.js +1 -0
  86. package/dist-cjs/index.js.map +1 -1
  87. package/dist-cjs/records/index.js +2 -0
  88. package/dist-cjs/records/index.js.map +1 -1
  89. package/dist-cjs/records/rail.js +254 -0
  90. package/dist-cjs/records/rail.js.map +1 -0
  91. package/dist-cjs/records/wire.js +91 -0
  92. package/dist-cjs/records/wire.js.map +1 -0
  93. package/package.json +7 -1
@@ -0,0 +1,250 @@
1
+ /** Portable, event-driven Send and Receive orchestration. Hosts inject effects. */
2
+ import { nextEntitySends } from './outbox.js';
3
+ export const ENTITY_RECORD_DELIVERY_LIMIT = 256;
4
+ export const ENTITY_RECORD_RETRY_BASE_MS = 1_000;
5
+ export const ENTITY_RECORD_RETRY_MAX_MS = 30_000;
6
+ /**
7
+ * One rail has only two reasons to run: local work exists, or authority work
8
+ * may exist. Repeated reasons coalesce while the current run is in flight.
9
+ */
10
+ export class EntityRecordRail {
11
+ #authorityId;
12
+ #store;
13
+ #cargo;
14
+ #authority;
15
+ #schedule;
16
+ #onInboxCommitted;
17
+ #onBackgroundError;
18
+ #started = false;
19
+ #stopped = false;
20
+ #subscribed = false;
21
+ #needsSubscribe = false;
22
+ #needsSend = false;
23
+ #running = null;
24
+ #retry = null;
25
+ #retryAttempt = 0;
26
+ #removeAvailable = null;
27
+ #removeDisconnect = null;
28
+ constructor(options) {
29
+ if (!options.authorityId.trim())
30
+ throw new Error('entity record authority is required');
31
+ this.#authorityId = options.authorityId;
32
+ this.#store = options.store;
33
+ this.#cargo = options.cargo;
34
+ this.#authority = options.authority;
35
+ this.#schedule = options.schedule;
36
+ this.#onInboxCommitted = options.onInboxCommitted ?? (() => undefined);
37
+ this.#onBackgroundError = options.onBackgroundError ?? (() => undefined);
38
+ }
39
+ /** Subscribe first, catch up from the durable cursor, then drain local work. */
40
+ async start() {
41
+ if (this.#started)
42
+ throw new Error('entity record rail already started');
43
+ if (this.#stopped)
44
+ throw new Error('entity record rail is stopped');
45
+ this.#started = true;
46
+ this.#removeAvailable = this.#authority.onAvailable((signal) => {
47
+ if (signal.authorityId !== this.#authorityId || this.#stopped)
48
+ return;
49
+ this.#needsSubscribe = true;
50
+ this.#kick();
51
+ });
52
+ this.#removeDisconnect = this.#authority.onDisconnect(() => {
53
+ if (this.#stopped)
54
+ return;
55
+ this.#subscribed = false;
56
+ this.#needsSubscribe = true;
57
+ this.#scheduleRetry();
58
+ });
59
+ this.#needsSubscribe = true;
60
+ this.#needsSend = true;
61
+ await this.#runExplicitly();
62
+ }
63
+ /** Record calls this only after its local outbox transaction commits. */
64
+ localRecordsAvailable() {
65
+ if (this.#stopped)
66
+ return;
67
+ this.#needsSend = true;
68
+ if (this.#started)
69
+ this.#kick();
70
+ }
71
+ /** Await all work known at this boundary; it never creates an idle query. */
72
+ async flush() {
73
+ if (!this.#started)
74
+ throw new Error('entity record rail has not started');
75
+ if (this.#stopped)
76
+ return;
77
+ this.#needsSend = true;
78
+ if (!this.#subscribed)
79
+ this.#needsSubscribe = true;
80
+ await this.#runExplicitly();
81
+ }
82
+ /** Stop accepting events. Closing the injected wire may interrupt a request. */
83
+ async stop() {
84
+ if (this.#stopped)
85
+ return;
86
+ this.#stopped = true;
87
+ this.#cancelRetry();
88
+ this.#removeAvailable?.();
89
+ this.#removeAvailable = null;
90
+ this.#removeDisconnect?.();
91
+ this.#removeDisconnect = null;
92
+ await this.#running?.catch(() => undefined);
93
+ }
94
+ async #runExplicitly() {
95
+ this.#cancelRetry();
96
+ try {
97
+ await this.#ensureRun();
98
+ this.#retryAttempt = 0;
99
+ }
100
+ catch (error) {
101
+ this.#scheduleRetry();
102
+ throw error;
103
+ }
104
+ }
105
+ #kick() {
106
+ if (!this.#started || this.#stopped)
107
+ return;
108
+ this.#cancelRetry();
109
+ void this.#ensureRun().then(() => {
110
+ this.#retryAttempt = 0;
111
+ }, (error) => {
112
+ this.#onBackgroundError(error);
113
+ this.#scheduleRetry();
114
+ });
115
+ }
116
+ #ensureRun() {
117
+ if (this.#running)
118
+ return this.#running;
119
+ const running = this.#drain();
120
+ this.#running = running;
121
+ void running.then(() => {
122
+ if (this.#running === running)
123
+ this.#running = null;
124
+ if (!this.#stopped && (this.#needsSubscribe || this.#needsSend))
125
+ this.#kick();
126
+ }, () => {
127
+ if (this.#running === running)
128
+ this.#running = null;
129
+ });
130
+ return running;
131
+ }
132
+ async #drain() {
133
+ while (!this.#stopped && (this.#needsSubscribe || this.#needsSend)) {
134
+ if (this.#needsSubscribe) {
135
+ this.#needsSubscribe = false;
136
+ try {
137
+ await this.#catchUp();
138
+ this.#subscribed = true;
139
+ }
140
+ catch (error) {
141
+ this.#subscribed = false;
142
+ this.#needsSubscribe = true;
143
+ throw error;
144
+ }
145
+ }
146
+ if (this.#stopped)
147
+ return;
148
+ if (this.#needsSend) {
149
+ this.#needsSend = false;
150
+ try {
151
+ if (await this.#sendPending())
152
+ this.#needsSubscribe = true;
153
+ }
154
+ catch (error) {
155
+ this.#needsSend = true;
156
+ throw error;
157
+ }
158
+ }
159
+ }
160
+ }
161
+ async #catchUp() {
162
+ let after = await this.#store.readDeliveryCursor(this.#authorityId);
163
+ while (!this.#stopped) {
164
+ const deliveries = await this.#authority.subscribe({
165
+ authorityId: this.#authorityId,
166
+ afterDeliverySequence: after,
167
+ limit: ENTITY_RECORD_DELIVERY_LIMIT,
168
+ });
169
+ if (deliveries.length === 0)
170
+ return;
171
+ let stored = await this.#store.receive({
172
+ authorityId: this.#authorityId,
173
+ deliveries,
174
+ advanceDeliveryCursor: true,
175
+ });
176
+ if (stored.kind === 'stored')
177
+ this.#onInboxCommitted();
178
+ if (stored.kind === 'gap') {
179
+ const missing = await this.#authority.backfill({
180
+ authorityId: this.#authorityId,
181
+ entityId: stored.gap.entityId,
182
+ afterGlobalSequence: stored.gap.after,
183
+ throughGlobalSequence: stored.gap.received,
184
+ });
185
+ if (missing.length === 0) {
186
+ throw new Error(`entity ${stored.gap.entityId} is missing sequence ${stored.gap.after + 1}`);
187
+ }
188
+ const repaired = await this.#store.receive({
189
+ authorityId: this.#authorityId,
190
+ deliveries: missing,
191
+ advanceDeliveryCursor: false,
192
+ });
193
+ if (repaired.kind === 'gap') {
194
+ throw new Error(`entity ${repaired.gap.entityId} history remained gapped after backfill`);
195
+ }
196
+ this.#onInboxCommitted();
197
+ stored = await this.#store.receive({
198
+ authorityId: this.#authorityId,
199
+ deliveries,
200
+ advanceDeliveryCursor: true,
201
+ });
202
+ if (stored.kind === 'gap') {
203
+ throw new Error(`entity ${stored.gap.entityId} history did not reach ${stored.gap.received}`);
204
+ }
205
+ this.#onInboxCommitted();
206
+ }
207
+ after = stored.deliveryCursor;
208
+ if (deliveries.length < ENTITY_RECORD_DELIVERY_LIMIT)
209
+ return;
210
+ }
211
+ }
212
+ async #sendPending() {
213
+ let sent = false;
214
+ while (!this.#stopped) {
215
+ const pending = await this.#store.readPending();
216
+ const selected = nextEntitySends(pending);
217
+ if (selected.length === 0)
218
+ return sent;
219
+ const results = await Promise.allSettled(selected.map(async (row) => {
220
+ await this.#cargo.ensure(row.record);
221
+ if (this.#stopped)
222
+ return;
223
+ const accepted = await this.#authority.submit(row.record);
224
+ await this.#store.stampAccepted(row, accepted);
225
+ sent = true;
226
+ }));
227
+ const failure = results.find((result) => result.status === 'rejected');
228
+ if (failure)
229
+ throw failure.reason;
230
+ }
231
+ return sent;
232
+ }
233
+ #scheduleRetry() {
234
+ if (this.#stopped || this.#retry)
235
+ return;
236
+ const base = Math.min(ENTITY_RECORD_RETRY_MAX_MS, ENTITY_RECORD_RETRY_BASE_MS * (2 ** Math.min(this.#retryAttempt, 16)));
237
+ const random = Math.max(0, Math.min(1, this.#schedule.random()));
238
+ const delay = Math.round(base * (0.5 + random));
239
+ this.#retryAttempt += 1;
240
+ this.#retry = this.#schedule.schedule(delay, () => {
241
+ this.#retry = null;
242
+ this.#kick();
243
+ });
244
+ }
245
+ #cancelRetry() {
246
+ this.#retry?.cancel();
247
+ this.#retry = null;
248
+ }
249
+ }
250
+ //# sourceMappingURL=rail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rail.js","sourceRoot":"","sources":["../../src/records/rail.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /** Exact wire for the entity Record/Send/Receive rail. */
2
+ import type { DeliveredEntityRecord, EntityRecordAuthorityPort, EntityRecordAvailability } from './rail.js';
3
+ export interface EntityRecordSubmitFrame {
4
+ readonly type: 'entity.record.submit';
5
+ readonly request_id: string;
6
+ readonly record_json: string;
7
+ }
8
+ export interface EntityRecordSubscribeFrame {
9
+ readonly type: 'entity.record.subscribe';
10
+ readonly request_id: string;
11
+ readonly authority_id: string;
12
+ readonly after_delivery_sequence: number;
13
+ readonly limit: number;
14
+ }
15
+ export interface EntityRecordBackfillFrame {
16
+ readonly type: 'entity.record.backfill';
17
+ readonly request_id: string;
18
+ readonly authority_id: string;
19
+ readonly entity_id: string;
20
+ readonly after_global_sequence: number;
21
+ readonly through_global_sequence: number;
22
+ }
23
+ export type EntityRecordRuntimeFrame = EntityRecordSubmitFrame | EntityRecordSubscribeFrame | EntityRecordBackfillFrame;
24
+ export interface EntityRecordAckFrame {
25
+ readonly type: 'entity.record.ack';
26
+ readonly request_id: string;
27
+ readonly record_json: string;
28
+ readonly duplicate: boolean;
29
+ }
30
+ export interface EntityRecordDeliveryFrame {
31
+ readonly delivery_sequence: number;
32
+ readonly record_json: string;
33
+ }
34
+ export interface EntityRecordSubscribedFrame {
35
+ readonly type: 'entity.record.subscribed';
36
+ readonly request_id: string;
37
+ readonly records: readonly EntityRecordDeliveryFrame[];
38
+ }
39
+ export interface EntityRecordBackfillResultFrame {
40
+ readonly type: 'entity.record.backfill-result';
41
+ readonly request_id: string;
42
+ readonly records: readonly EntityRecordDeliveryFrame[];
43
+ }
44
+ export interface EntityRecordAvailableFrame {
45
+ readonly type: 'entity.record.available';
46
+ readonly authority_id: string;
47
+ }
48
+ export type EntityRecordAuthorityFrame = EntityRecordAckFrame | EntityRecordSubscribedFrame | EntityRecordBackfillResultFrame | EntityRecordAvailableFrame;
49
+ type WithoutRequestId<T> = T extends {
50
+ readonly request_id: string;
51
+ } ? Omit<T, 'request_id'> : T;
52
+ export type EntityRecordWireRequest = WithoutRequestId<EntityRecordRuntimeFrame>;
53
+ export interface EntityRecordWirePort {
54
+ request(frame: EntityRecordWireRequest, acceptedTypes: readonly string[]): Promise<unknown>;
55
+ onFrame(listener: (frame: unknown) => void): () => void;
56
+ onDisconnect(listener: (error: unknown) => void): () => void;
57
+ }
58
+ export declare function decodeEntityRecordDeliveries(value: unknown): readonly DeliveredEntityRecord[];
59
+ export declare function decodeEntityRecordAvailability(value: unknown): EntityRecordAvailability;
60
+ /** Map one authenticated request/event wire onto the portable authority port. */
61
+ export declare function createEntityRecordAuthorityPort(wire: EntityRecordWirePort): EntityRecordAuthorityPort;
62
+ export {};
63
+ //# sourceMappingURL=wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/records/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /** Exact wire for the entity Record/Send/Receive rail. */
2
+ import { isRecord } from '../contracts/validate.js';
3
+ import { decodeAcceptedEntityRecord, encodeEntityRecord } from './codec.js';
4
+ const positiveSequence = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
5
+ export function decodeEntityRecordDeliveries(value) {
6
+ if (!Array.isArray(value))
7
+ throw new Error('entity record authority did not return a records array');
8
+ return Object.freeze(value.map((item) => {
9
+ if (!isRecord(item)
10
+ || !positiveSequence(item.delivery_sequence)
11
+ || typeof item.record_json !== 'string') {
12
+ throw new Error('entity record authority returned an invalid delivery');
13
+ }
14
+ return Object.freeze({
15
+ deliverySequence: item.delivery_sequence,
16
+ record: decodeAcceptedEntityRecord(item.record_json),
17
+ });
18
+ }));
19
+ }
20
+ export function decodeEntityRecordAvailability(value) {
21
+ if (!isRecord(value)
22
+ || value.type !== 'entity.record.available'
23
+ || typeof value.authority_id !== 'string'
24
+ || !value.authority_id) {
25
+ throw new Error('entity record availability signal is invalid');
26
+ }
27
+ return Object.freeze({
28
+ authorityId: value.authority_id,
29
+ });
30
+ }
31
+ /** Map one authenticated request/event wire onto the portable authority port. */
32
+ export function createEntityRecordAuthorityPort(wire) {
33
+ return {
34
+ async submit(record) {
35
+ const frame = await wire.request({
36
+ type: 'entity.record.submit',
37
+ record_json: encodeEntityRecord(record),
38
+ }, ['entity.record.ack']);
39
+ if (!isRecord(frame) || frame.type !== 'entity.record.ack' || typeof frame.record_json !== 'string') {
40
+ throw new Error('entity record acknowledgement is invalid');
41
+ }
42
+ return decodeAcceptedEntityRecord(frame.record_json);
43
+ },
44
+ async subscribe(input) {
45
+ const frame = await wire.request({
46
+ type: 'entity.record.subscribe',
47
+ authority_id: input.authorityId,
48
+ after_delivery_sequence: input.afterDeliverySequence,
49
+ limit: input.limit,
50
+ }, ['entity.record.subscribed']);
51
+ if (!isRecord(frame) || frame.type !== 'entity.record.subscribed') {
52
+ throw new Error('entity record subscription response is invalid');
53
+ }
54
+ return decodeEntityRecordDeliveries(frame.records);
55
+ },
56
+ async backfill(input) {
57
+ const frame = await wire.request({
58
+ type: 'entity.record.backfill',
59
+ authority_id: input.authorityId,
60
+ entity_id: input.entityId,
61
+ after_global_sequence: input.afterGlobalSequence,
62
+ through_global_sequence: input.throughGlobalSequence,
63
+ }, ['entity.record.backfill-result']);
64
+ if (!isRecord(frame) || frame.type !== 'entity.record.backfill-result') {
65
+ throw new Error('entity record backfill response is invalid');
66
+ }
67
+ return decodeEntityRecordDeliveries(frame.records);
68
+ },
69
+ onAvailable(listener) {
70
+ return wire.onFrame((frame) => {
71
+ if (!isRecord(frame) || frame.type !== 'entity.record.available')
72
+ return;
73
+ try {
74
+ listener(decodeEntityRecordAvailability(frame));
75
+ }
76
+ catch {
77
+ // A malformed unsolicited frame is not authority evidence.
78
+ }
79
+ });
80
+ },
81
+ onDisconnect(listener) {
82
+ return wire.onDisconnect(listener);
83
+ },
84
+ };
85
+ }
86
+ //# sourceMappingURL=wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/records/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /** Portable private-result construction for file and link adapters. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.prepareTextResult = prepareTextResult;
5
+ exports.prepareBinaryResult = prepareBinaryResult;
6
+ exports.prepareLinkResult = prepareLinkResult;
7
+ const content_js_1 = require("../detection/content.js");
8
+ const bytes_js_1 = require("../entities/bytes.js");
9
+ const exactResult = (bytes, expected, sha256Hex, label) => {
10
+ if (sha256Hex(bytes) !== expected) {
11
+ throw new Error(`${label} does not match its accepted complete result`);
12
+ }
13
+ return bytes;
14
+ };
15
+ /**
16
+ * Construct text privately. The snapshot is mandatory truth. A delta is only
17
+ * a shortcut over the exact immutable base; reproduceTextChange falls back to
18
+ * the already-verified snapshot on every base or result mismatch. The returned
19
+ * snapshot reference remains caller-owned immutable input; Apply never mutates
20
+ * it and the host streams it into private staging.
21
+ */
22
+ function prepareTextResult(plan, snapshot, exactBase, sha256Hex) {
23
+ const verifiedSnapshot = exactResult(snapshot, plan.artifact.contentHash, sha256Hex, 'text Apply snapshot');
24
+ if (plan.strategy.kind === 'snapshot')
25
+ return verifiedSnapshot;
26
+ return (0, content_js_1.reproduceTextChange)(exactBase, {
27
+ kind: 'file.text',
28
+ mode: 'delta',
29
+ basePayloadVersion: plan.strategy.basePayloadVersion,
30
+ resultPayloadVersion: plan.artifact.contentHash,
31
+ delta: plan.strategy.delta,
32
+ }, verifiedSnapshot, sha256Hex);
33
+ }
34
+ /** Verify reusable binary blocks while streaming them into private staging. */
35
+ async function prepareBinaryResult(plan, read, sink, sha256Hex) {
36
+ for (const [index, expected] of plan.manifest.chunks.entries()) {
37
+ const chunk = await read(index);
38
+ if (!(chunk instanceof Uint8Array)
39
+ || chunk.byteLength !== expected.bytes
40
+ || sha256Hex(chunk) !== expected.sha256) {
41
+ throw new Error(`binary Apply block ${index} failed verification`);
42
+ }
43
+ await sink.write(index, chunk);
44
+ }
45
+ const receipt = await sink.seal();
46
+ if (receipt.bytes !== plan.manifest.bytes
47
+ || receipt.contentHash !== plan.artifact.contentHash) {
48
+ throw new Error('binary Apply staged result failed complete verification');
49
+ }
50
+ return Object.freeze({ ...receipt });
51
+ }
52
+ /** A link result is only its literal UTF-8 target bytes. */
53
+ function prepareLinkResult(plan, sha256Hex) {
54
+ exactResult((0, bytes_js_1.utf8Encode)(plan.targetText), plan.artifact.contentHash, sha256Hex, 'link Apply target');
55
+ return plan.targetText;
56
+ }
57
+ //# sourceMappingURL=content-results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-results.js","sourceRoot":"","sources":["../../src/apply/content-results.ts"],"names":[],"mappings":";AAAA,uEAAuE;;AA0BvE,8CAiBC;AAeD,kDAqBC;AAGD,8CAKC;AArFD,wDAA8D;AAC9D,mDAAkD;AAIlD,MAAM,WAAW,GAAG,CAClB,KAAiB,EACjB,QAAgB,EAChB,SAAoB,EACpB,KAAa,EACD,EAAE;IACd,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,8CAA8C,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAC/B,IAAmB,EACnB,QAAoB,EACpB,SAA4B,EAC5B,SAAoB;IAEpB,MAAM,gBAAgB,GAAG,WAAW,CAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CACtE,CAAC;IACF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,gBAAgB,CAAC;IAC/D,OAAO,IAAA,gCAAmB,EAAC,SAAS,EAAE;QACpC,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,OAAO;QACb,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB;QACpD,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW;QAC/C,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK;KAC3B,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC;AAcD,+EAA+E;AACxE,KAAK,UAAU,mBAAmB,CACvC,IAAqB,EACrB,IAA4C,EAC5C,IAAqB,EACrB,SAAoB;IAEpB,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC;eAC7B,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,KAAK;eACnC,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,sBAAsB,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK;WACpC,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,4DAA4D;AAC5D,SAAgB,iBAAiB,CAAC,IAAmB,EAAE,SAAoB;IACzE,WAAW,CACT,IAAA,qBAAU,EAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,mBAAmB,CACvF,CAAC;IACF,OAAO,IAAI,CAAC,UAAU,CAAC;AACzB,CAAC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /** Portable contracts at the Inbox -> Apply -> Verify boundary. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ENTITY_APPLY_INTENT_CONTRACT = void 0;
5
+ exports.assertApplyIntent = assertApplyIntent;
6
+ exports.createApplyIntent = createApplyIntent;
7
+ exports.advanceApplyIntent = advanceApplyIntent;
8
+ const types_js_1 = require("../entities/types.js");
9
+ exports.ENTITY_APPLY_INTENT_CONTRACT = 'amalgm.entity-apply-intent@1';
10
+ const HASH = /^[0-9a-f]{64}$/;
11
+ const PHASES = new Set(['declared', 'prepared', 'revealed']);
12
+ const sequence = (value, positive = false) => Number.isSafeInteger(value) && value >= (positive ? 1 : 0);
13
+ function assertApplyIntent(intent) {
14
+ if (intent.contract !== exports.ENTITY_APPLY_INTENT_CONTRACT
15
+ || !intent.authorityId
16
+ || !types_js_1.UUID_PATTERN.test(intent.entityId)
17
+ || !sequence(intent.fromSequence)
18
+ || !sequence(intent.throughSequence, true)
19
+ || intent.throughSequence < intent.fromSequence + 1
20
+ || !intent.targetMutationId
21
+ || !HASH.test(intent.targetState)
22
+ || !(0, types_js_1.isEntityType)(intent.targetType)
23
+ || !PHASES.has(intent.phase)
24
+ || !sequence(intent.createdAt)) {
25
+ throw new Error('entity Apply intent is invalid');
26
+ }
27
+ }
28
+ function createApplyIntent(input) {
29
+ const intent = Object.freeze({
30
+ contract: exports.ENTITY_APPLY_INTENT_CONTRACT,
31
+ authorityId: input.authorityId,
32
+ entityId: input.entityId,
33
+ fromSequence: input.fromSequence,
34
+ throughSequence: input.target.globalSequence,
35
+ targetMutationId: input.target.mutationId,
36
+ targetState: input.target.resultState,
37
+ targetType: input.target.change.result.type,
38
+ phase: 'declared',
39
+ createdAt: input.createdAt,
40
+ });
41
+ assertApplyIntent(intent);
42
+ return intent;
43
+ }
44
+ function advanceApplyIntent(intent, phase) {
45
+ assertApplyIntent(intent);
46
+ const legal = intent.phase === phase
47
+ || (intent.phase === 'declared' && phase === 'prepared')
48
+ || (intent.phase === 'prepared' && phase === 'revealed');
49
+ if (!legal)
50
+ throw new Error(`entity Apply intent cannot move from ${intent.phase} to ${phase}`);
51
+ return Object.freeze({ ...intent, phase });
52
+ }
53
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/apply/contracts.ts"],"names":[],"mappings":";AAAA,mEAAmE;;;AA2NnE,8CAcC;AAED,8CAqBC;AAED,gDAUC;AAzQD,mDAAmG;AAMtF,QAAA,4BAA4B,GAAG,8BAA8B,CAAC;AA4M3E,MAAM,IAAI,GAAG,gBAAgB,CAAC;AAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAmB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/E,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,QAAQ,GAAG,KAAK,EAAW,EAAE,CAC5D,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7D,SAAgB,iBAAiB,CAAC,MAAyB;IACzD,IAAI,MAAM,CAAC,QAAQ,KAAK,oCAA4B;WAC/C,CAAC,MAAM,CAAC,WAAW;WACnB,CAAC,uBAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;WACnC,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC;WAC9B,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC;WACvC,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,YAAY,GAAG,CAAC;WAChD,CAAC,MAAM,CAAC,gBAAgB;WACxB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;WAC9B,CAAC,IAAA,uBAAY,EAAC,MAAM,CAAC,UAAU,CAAC;WAChC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;WACzB,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAMjC;IACC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC3B,QAAQ,EAAE,oCAA4B;QACtC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QAC5C,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACzC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;QACrC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;QAC3C,KAAK,EAAE,UAAmB;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC;IACH,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,kBAAkB,CAChC,MAAyB,EACzB,KAA4C;IAE5C,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,KAAK,KAAK;WAC/B,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,CAAC;WACrD,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC;IAChG,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /** Entity Apply and Verify subsystem. */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.planEntityApply = void 0;
19
+ __exportStar(require("./contracts.js"), exports);
20
+ __exportStar(require("./content-results.js"), exports);
21
+ __exportStar(require("./local-work.js"), exports);
22
+ var plans_js_1 = require("./plans.js");
23
+ Object.defineProperty(exports, "planEntityApply", { enumerable: true, get: function () { return plans_js_1.planEntityApply; } });
24
+ __exportStar(require("./rail.js"), exports);
25
+ __exportStar(require("./repository-result.js"), exports);
26
+ __exportStar(require("./selection.js"), exports);
27
+ __exportStar(require("./type-adapters.js"), exports);
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apply/index.ts"],"names":[],"mappings":";AAAA,yCAAyC;;;;;;;;;;;;;;;;;AAEzC,iDAA+B;AAC/B,uDAAqC;AACrC,kDAAgC;AAChC,uCAA6C;AAApC,2GAAA,eAAe,OAAA;AACxB,4CAA0B;AAC1B,yDAAuC;AACvC,iDAA+B;AAC/B,qDAAmC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ /** Pure form of the Outbox gate used by the Apply store transaction. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.hasLocalWorkAfter = hasLocalWorkAfter;
5
+ /**
6
+ * A local result protects working ground when cloud has not sequenced it yet,
7
+ * or when its accepted sequence is later than the incoming target. An
8
+ * accepted local row at the target is no longer a blocker: that is the
9
+ * official position Apply should Verify against the already-equal disk.
10
+ */
11
+ function hasLocalWorkAfter(rows, authorityId, entityId, targetSequence) {
12
+ if (!authorityId || !entityId
13
+ || !Number.isSafeInteger(targetSequence) || targetSequence < 1) {
14
+ throw new Error('Apply local-work target is invalid');
15
+ }
16
+ return rows.some((row) => row.record.authorityId === authorityId
17
+ && row.record.entityId === entityId
18
+ && (row.status === 'pending' || row.globalSequence > targetSequence));
19
+ }
20
+ //# sourceMappingURL=local-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-work.js","sourceRoot":"","sources":["../../src/apply/local-work.ts"],"names":[],"mappings":";AAAA,wEAAwE;;AAUxE,8CAaC;AAnBD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAC/B,IAA0B,EAC1B,WAAmB,EACnB,QAAgB,EAChB,cAAsB;IAEtB,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ;WACxB,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,WAAW;WAC3D,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;WAChC,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC;AAC1E,CAAC"}