@serve.zone/interfaces 29.0.0 → 30.1.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.
@@ -0,0 +1,281 @@
1
+ import { isSha256Digest } from './immutableimage.js';
2
+ import { evaluateRuntimeAssignmentV1, getRuntimeAssignmentV1Reference, snapshotRuntimeAssignmentV1 } from './runtimeassignment.js';
3
+ import { bindRuntimeReporterSessionV1, snapshotRuntimeSessionBindingV1 } from './runtimesession.js';
4
+ import { canonicalizeStrictJson, createCanonicalJsonSha256Hex } from '../private/canonicaljson.js';
5
+ export const runtimeAssignmentTerminalReceiptV1Contract = Object.freeze({
6
+ digestDomain: 'serve.zone/runtime-assignment-terminal-receipt-v1',
7
+ maximumReceiptCanonicalBytes: 16_384,
8
+ maximumHistoryCanonicalBytes: 98_304,
9
+ maximumReceipts: 2,
10
+ maximumAssignmentRevisions: 3,
11
+ error: 'Runtime terminal receipt contract rejected.',
12
+ });
13
+ const fail = () => { throw new Error(runtimeAssignmentTerminalReceiptV1Contract.error); };
14
+ function requireValue(conditionArg) { if (!conditionArg)
15
+ fail(); }
16
+ const safe = (operationArg) => { try {
17
+ return operationArg();
18
+ }
19
+ catch {
20
+ return fail();
21
+ } };
22
+ const canonical = (valueArg) => canonicalizeStrictJson(valueArg, fail);
23
+ const encoder = new TextEncoder();
24
+ const identifier = (valueArg) => {
25
+ requireValue(typeof valueArg === 'string' && /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/.test(valueArg));
26
+ return valueArg;
27
+ };
28
+ const digest = (valueArg) => {
29
+ requireValue(typeof valueArg === 'string' && isSha256Digest(valueArg));
30
+ return valueArg;
31
+ };
32
+ /** Bounded inert copy before hashing or calling any nested validator. */
33
+ const capture = (valueArg, maximumBytesArg = runtimeAssignmentTerminalReceiptV1Contract.maximumHistoryCanonicalBytes) => safe(() => {
34
+ let nodes = 0;
35
+ let bytes = 0;
36
+ const ancestors = new Set();
37
+ const account = (value) => {
38
+ requireValue(value.length <= maximumBytesArg);
39
+ bytes += encoder.encode(value).byteLength;
40
+ requireValue(bytes <= maximumBytesArg);
41
+ };
42
+ const copy = (value, depth) => {
43
+ requireValue(++nodes <= 4096 && depth <= 12);
44
+ if (typeof value === 'string') {
45
+ account(value);
46
+ return value;
47
+ }
48
+ if (value === null || typeof value === 'boolean' || typeof value === 'number')
49
+ return value;
50
+ requireValue(value !== null && typeof value === 'object' && !ancestors.has(value));
51
+ const array = Array.isArray(value);
52
+ const prototype = Object.getPrototypeOf(value);
53
+ requireValue(array ? prototype === Array.prototype : prototype === Object.prototype || prototype === null);
54
+ ancestors.add(value);
55
+ try {
56
+ const keys = Reflect.ownKeys(value);
57
+ requireValue(keys.length <= 65);
58
+ if (array) {
59
+ const length = Object.getOwnPropertyDescriptor(value, 'length')?.value;
60
+ requireValue(Number.isSafeInteger(length) && length >= 0 && length <= 64 && keys.length === length + 1);
61
+ const result = [];
62
+ for (let index = 0; index < length; index++) {
63
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
64
+ requireValue(descriptor?.enumerable && Object.hasOwn(descriptor, 'value'));
65
+ result.push(copy(descriptor.value, depth + 1));
66
+ }
67
+ return result;
68
+ }
69
+ const result = Object.create(null);
70
+ for (const key of keys) {
71
+ requireValue(typeof key === 'string');
72
+ account(key);
73
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
74
+ requireValue(descriptor?.enumerable && Object.hasOwn(descriptor, 'value'));
75
+ result[key] = copy(descriptor.value, depth + 1);
76
+ }
77
+ return result;
78
+ }
79
+ finally {
80
+ ancestors.delete(value);
81
+ }
82
+ };
83
+ const serialized = canonical(copy(valueArg, 0));
84
+ requireValue(encoder.encode(serialized).byteLength <= maximumBytesArg);
85
+ return JSON.parse(serialized);
86
+ });
87
+ const record = (valueArg, keysArg) => {
88
+ requireValue(valueArg !== null && typeof valueArg === 'object' && !Array.isArray(valueArg));
89
+ const keys = Object.keys(valueArg);
90
+ requireValue(keys.length === keysArg.length && keys.every((key) => keysArg.includes(key)));
91
+ return valueArg;
92
+ };
93
+ const reference = (valueArg) => {
94
+ const value = record(valueArg, ['assignmentId', 'generation', 'digest']);
95
+ requireValue(typeof value.generation === 'number' && Number.isSafeInteger(value.generation)
96
+ && value.generation >= 1 && value.generation <= 3);
97
+ return { assignmentId: identifier(value.assignmentId), generation: value.generation, digest: digest(value.digest) };
98
+ };
99
+ const evidence = (valueArg) => {
100
+ const value = record(valueArg, ['phase', 'sandboxId', 'containerId', 'imageConfigDigest', 'ipAddresses', 'exitCode']);
101
+ requireValue(value.phase === 'absent' || value.phase === 'stopped');
102
+ for (const field of ['sandboxId', 'containerId'])
103
+ requireValue(value[field] === null
104
+ || (typeof value[field] === 'string' && /^[a-f0-9]{64}$/.test(value[field])));
105
+ requireValue(value.imageConfigDigest === null || (typeof value.imageConfigDigest === 'string'
106
+ && isSha256Digest(value.imageConfigDigest)));
107
+ requireValue(Array.isArray(value.ipAddresses) && value.ipAddresses.length === 0);
108
+ requireValue(value.exitCode === null || (typeof value.exitCode === 'number' && Number.isSafeInteger(value.exitCode)
109
+ && value.exitCode >= -2_147_483_648 && value.exitCode <= 2_147_483_647));
110
+ requireValue(value.phase === 'absent'
111
+ ? value.sandboxId === null && value.containerId === null && value.imageConfigDigest === null && value.exitCode === null
112
+ : value.sandboxId !== null);
113
+ requireValue(value.containerId !== null || (value.imageConfigDigest === null && value.exitCode === null));
114
+ return value;
115
+ };
116
+ /** Detached exact-schema assertion only; digest, journal provenance and authority remain unverified. */
117
+ export const snapshotRuntimeAssignmentTerminalReceiptV1 = (valueArg) => safe(() => {
118
+ const value = record(capture(valueArg, runtimeAssignmentTerminalReceiptV1Contract.maximumReceiptCanonicalBytes), ['schemaVersion', 'assignment', 'runAssignment', 'reporterSessionId', 'sequence', 'operation', 'previousReceiptDigest', 'digest']);
119
+ const assignment = reference(value.assignment);
120
+ const runAssignment = reference(value.runAssignment);
121
+ const operation = record(value.operation, ['id', 'action', 'bootId', 'status', 'evidence']);
122
+ const terminalEvidence = evidence(operation.evidence);
123
+ requireValue(value.schemaVersion === 1 && (value.sequence === 1 || value.sequence === 2)
124
+ && operation.status === 'completed' && assignment.generation === value.sequence + 1
125
+ && runAssignment.generation === 1 && runAssignment.assignmentId === assignment.assignmentId);
126
+ requireValue(typeof operation.bootId === 'string'
127
+ && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(operation.bootId));
128
+ requireValue(value.sequence === 1 ? operation.action === 'stop' && value.previousReceiptDigest === null
129
+ : operation.action === 'remove' && terminalEvidence.phase === 'absent' && value.previousReceiptDigest !== null);
130
+ return { schemaVersion: 1, assignment, runAssignment, reporterSessionId: identifier(value.reporterSessionId),
131
+ sequence: value.sequence, operation: { id: identifier(operation.id), action: operation.action,
132
+ bootId: operation.bootId, status: 'completed', evidence: terminalEvidence },
133
+ previousReceiptDigest: value.previousReceiptDigest === null ? null : digest(value.previousReceiptDigest), digest: digest(value.digest) };
134
+ });
135
+ /** Bounded exact receipt history for synchronous persistence assertions; hashes remain unchecked. */
136
+ export const snapshotRuntimeAssignmentTerminalReceiptHistoryV1 = (valueArg) => safe(() => {
137
+ const values = capture(valueArg);
138
+ requireValue(Array.isArray(values) && values.length <= runtimeAssignmentTerminalReceiptV1Contract.maximumReceipts);
139
+ const receipts = values.map(snapshotRuntimeAssignmentTerminalReceiptV1);
140
+ for (const [index, receipt] of receipts.entries()) {
141
+ requireValue(receipt.sequence === index + 1);
142
+ if (index > 0)
143
+ requireValue(receipt.previousReceiptDigest === receipts[0].digest
144
+ && canonical(receipt.runAssignment) === canonical(receipts[0].runAssignment)
145
+ && receipt.operation.id !== receipts[0].operation.id);
146
+ }
147
+ return receipts;
148
+ });
149
+ const assignments = (valueArg) => {
150
+ const values = capture(valueArg);
151
+ requireValue(Array.isArray(values) && values.length >= 2
152
+ && values.length <= runtimeAssignmentTerminalReceiptV1Contract.maximumAssignmentRevisions);
153
+ return values.map(snapshotRuntimeAssignmentV1);
154
+ };
155
+ const checkAssignmentHistory = async (historyArg) => {
156
+ const run = historyArg[0];
157
+ const scope = { controller: run.controller, organizationId: run.organizationId,
158
+ nodeId: run.nodeId, runtimeNamespace: run.runtimeNamespace };
159
+ for (const [index, assignment] of historyArg.entries()) {
160
+ requireValue(assignment.generation === index + 1
161
+ && assignment.disposition === ['run', 'stop-preserve', 'remove-runtime-preserve-storage'][index]);
162
+ requireValue((await evaluateRuntimeAssignmentV1(assignment, index === 0 ? null : historyArg[index - 1], scope)).status === 'accept');
163
+ }
164
+ };
165
+ const computeSnapshotDigest = async (receiptArg) => {
166
+ const { digest: _digest, ...payload } = receiptArg;
167
+ return `sha256:${await createCanonicalJsonSha256Hex(canonical({
168
+ domain: runtimeAssignmentTerminalReceiptV1Contract.digestDomain, payload,
169
+ }), fail)}`;
170
+ };
171
+ /** Domain-separated exact body digest; captures before asynchronous hashing. */
172
+ export const computeRuntimeAssignmentTerminalReceiptV1Digest = async (valueArg) => {
173
+ try {
174
+ return await computeSnapshotDigest(snapshotRuntimeAssignmentTerminalReceiptV1(valueArg));
175
+ }
176
+ catch {
177
+ return fail();
178
+ }
179
+ };
180
+ const checkReceipt = async (receiptArg, historyArg, previousArg) => {
181
+ requireValue(historyArg.length > receiptArg.sequence
182
+ && canonical(receiptArg.runAssignment) === canonical(getRuntimeAssignmentV1Reference(historyArg[0]))
183
+ && canonical(receiptArg.assignment) === canonical(getRuntimeAssignmentV1Reference(historyArg[receiptArg.sequence]))
184
+ && receiptArg.digest === await computeSnapshotDigest(receiptArg));
185
+ if (receiptArg.sequence === 1)
186
+ requireValue(previousArg === null);
187
+ else {
188
+ requireValue(previousArg !== null && previousArg.sequence === 1);
189
+ await checkReceipt(previousArg, historyArg, null);
190
+ requireValue(receiptArg.previousReceiptDigest === previousArg.digest && receiptArg.operation.id !== previousArg.operation.id);
191
+ }
192
+ };
193
+ /** Full immutable run/stop/remove chain and exact prior stop receipt are mandatory for removal. */
194
+ export const validateRuntimeAssignmentTerminalReceiptV1 = async (valueArg, assignmentHistoryArg, previousReceiptArg) => {
195
+ try {
196
+ const receipt = snapshotRuntimeAssignmentTerminalReceiptV1(valueArg);
197
+ const history = assignments(assignmentHistoryArg);
198
+ const previous = previousReceiptArg === null ? null : snapshotRuntimeAssignmentTerminalReceiptV1(previousReceiptArg);
199
+ await checkAssignmentHistory(history);
200
+ await checkReceipt(receipt, history, previous);
201
+ return [];
202
+ }
203
+ catch {
204
+ return [runtimeAssignmentTerminalReceiptV1Contract.error];
205
+ }
206
+ };
207
+ /**
208
+ * Pure bounded CAS decision. Persist under the owning transaction and current
209
+ * credential/peer fence. New acceptance also requires the exact global incumbent;
210
+ * only a previously persisted exact body can replay after the incumbent changes.
211
+ * The helper cannot prove either condition. Retain both bodies after removal.
212
+ */
213
+ export const evaluateRuntimeAssignmentTerminalReceiptV1 = async (valueArg, acceptedHistoryArg, assignmentHistoryArg) => {
214
+ try {
215
+ const receipt = snapshotRuntimeAssignmentTerminalReceiptV1(valueArg);
216
+ const accepted = snapshotRuntimeAssignmentTerminalReceiptHistoryV1(acceptedHistoryArg);
217
+ const history = assignments(assignmentHistoryArg);
218
+ await checkAssignmentHistory(history);
219
+ for (const existing of accepted)
220
+ await checkReceipt(existing, history, existing.sequence === 1 ? null : accepted[0]);
221
+ if (receipt.digest !== await computeSnapshotDigest(receipt)
222
+ || history.length <= receipt.sequence
223
+ || canonical(receipt.runAssignment) !== canonical(getRuntimeAssignmentV1Reference(history[0]))
224
+ || canonical(receipt.assignment) !== canonical(getRuntimeAssignmentV1Reference(history[receipt.sequence]))) {
225
+ return { status: 'reject', reason: 'invalid' };
226
+ }
227
+ const existing = accepted[receipt.sequence - 1];
228
+ if (existing)
229
+ return canonical(existing) === canonical(receipt)
230
+ ? { status: 'replay', receipt: existing } : { status: 'reject', reason: 'conflict' };
231
+ if (receipt.sequence !== accepted.length + 1)
232
+ return { status: 'reject', reason: 'sequence-gap' };
233
+ if (receipt.sequence === 2 && (receipt.previousReceiptDigest !== accepted[0].digest
234
+ || receipt.operation.id === accepted[0].operation.id))
235
+ return { status: 'reject', reason: 'predecessor-mismatch' };
236
+ return { status: 'accept', receipt };
237
+ }
238
+ catch {
239
+ return { status: 'reject', reason: 'invalid' };
240
+ }
241
+ };
242
+ export const snapshotReportRuntimeAssignmentTerminalReceiptRequestV1 = (valueArg) => safe(() => {
243
+ const value = record(capture(valueArg), ['session', 'receipt']);
244
+ return { session: snapshotRuntimeSessionBindingV1(value.session), receipt: snapshotRuntimeAssignmentTerminalReceiptV1(value.receipt) };
245
+ });
246
+ export const snapshotReportRuntimeAssignmentTerminalReceiptResponseV1 = (valueArg) => safe(() => {
247
+ const value = record(capture(valueArg), ['receipt', 'authorityUse']);
248
+ requireValue(value.authorityUse === 'current-session' || value.authorityUse === 'historical-recovery');
249
+ return { receipt: snapshotRuntimeAssignmentTerminalReceiptV1(value.receipt), authorityUse: value.authorityUse };
250
+ });
251
+ /**
252
+ * CURRENT physical session and immutable server-indexed reporter history are
253
+ * trusted owner inputs, never wire claims. The previous stop receipt must also
254
+ * come from the durable owner. This binds content; it does not authenticate,
255
+ * prove the local operation join, advance CAS, or admit a replacement.
256
+ */
257
+ export const bindReportRuntimeAssignmentTerminalReceiptRequestV1 = async (valueArg, assignmentHistoryArg, previousReceiptArg, trustedSessionArg, reporterHistoryArg) => {
258
+ try {
259
+ const request = snapshotReportRuntimeAssignmentTerminalReceiptRequestV1(valueArg);
260
+ const history = assignments(assignmentHistoryArg);
261
+ const previous = previousReceiptArg === null ? null : snapshotRuntimeAssignmentTerminalReceiptV1(previousReceiptArg);
262
+ requireValue(history.length > request.receipt.sequence);
263
+ const binding = bindRuntimeReporterSessionV1(request.session, request.receipt.reporterSessionId, history[request.receipt.sequence], trustedSessionArg, reporterHistoryArg);
264
+ await checkAssignmentHistory(history);
265
+ await checkReceipt(request.receipt, history, previous);
266
+ return { request, authorityUse: binding.authorityUse };
267
+ }
268
+ catch {
269
+ return fail();
270
+ }
271
+ };
272
+ /** Exact ACK of the immutable outbox body; no rewritten session, operation or chain. */
273
+ export const bindReportRuntimeAssignmentTerminalReceiptResponseV1 = (valueArg, requestArg) => safe(() => {
274
+ const response = snapshotReportRuntimeAssignmentTerminalReceiptResponseV1(valueArg);
275
+ const request = snapshotReportRuntimeAssignmentTerminalReceiptRequestV1(requestArg);
276
+ requireValue(canonical(response.receipt) === canonical(request.receipt)
277
+ && response.authorityUse === (request.receipt.reporterSessionId === request.session.reporterSessionId
278
+ ? 'current-session' : 'historical-recovery'));
279
+ return response;
280
+ });
281
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZXRlcm1pbmFscmVjZWlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvcnVudGltZXRlcm1pbmFscmVjZWlwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFckQsT0FBTyxFQUFFLDJCQUEyQixFQUFFLCtCQUErQixFQUNuRSwyQkFBMkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTlELE9BQU8sRUFBRSw0QkFBNEIsRUFBRSwrQkFBK0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3BHLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSw0QkFBNEIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBNERuRyxNQUFNLENBQUMsTUFBTSwwQ0FBMEMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3RFLFlBQVksRUFBRSxtREFBbUQ7SUFDakUsNEJBQTRCLEVBQUUsTUFBTTtJQUNwQyw0QkFBNEIsRUFBRSxNQUFNO0lBQ3BDLGVBQWUsRUFBRSxDQUFDO0lBQ2xCLDBCQUEwQixFQUFFLENBQUM7SUFDN0IsS0FBSyxFQUFFLDZDQUE2QztDQUM1QyxDQUFDLENBQUM7QUFFWixNQUFNLElBQUksR0FBRyxHQUFVLEVBQUUsR0FBRyxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2pHLFNBQVMsWUFBWSxDQUFDLFlBQXFCLElBQTBCLElBQUksQ0FBQyxZQUFZO0lBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ2pHLE1BQU0sSUFBSSxHQUFHLENBQUksWUFBcUIsRUFBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO0lBQUMsT0FBTyxZQUFZLEVBQUUsQ0FBQztBQUFDLENBQUM7QUFBQyxNQUFNLENBQUM7SUFBQyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQUMsQ0FBQyxDQUFDLENBQUMs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
@@ -41,7 +41,8 @@ export interface IRequest_PushImageVersion extends plugins.typedrequestInterface
41
41
  identity: userInterfaces.IIdentity;
42
42
  imageId: string;
43
43
  versionString: string;
44
- imageStream: plugins.typedrequestInterfaces.IVirtualStream;
44
+ /** Requester sends archive bytes; TypedHandler receives the opposite endpoint. */
45
+ imageStream: plugins.typedrequestInterfaces.TVirtualStream<'send'>;
45
46
  };
46
47
  response: {
47
48
  allowed: boolean;
@@ -55,7 +56,8 @@ export interface IRequest_PullImageVersion extends plugins.typedrequestInterface
55
56
  versionString: string;
56
57
  };
57
58
  response: {
58
- imageStream: plugins.typedrequestInterfaces.IVirtualStream;
59
+ /** Requester receives archive bytes; TypedHandler returns a sender endpoint. */
60
+ imageStream: plugins.typedrequestInterfaces.TVirtualStream<'receive'>;
59
61
  };
60
62
  }
61
63
  export interface IRequest_DeleteImage extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_DeleteImage> {
@@ -1,5 +1,6 @@
1
1
  import * as plugins from '../plugins.js';
2
2
  import type * as data from '../data/runtimesession.js';
3
+ import type * as terminal from '../data/runtimeterminalreceipt.js';
3
4
  /** WSS-only Pallet bootstrap. Derive physical peer/process/idempotency server-side. */
4
5
  export interface IReq_Pallet_Cloudly_RegisterPalletRuntimeSessionV1 extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Cloudly_RegisterPalletRuntimeSessionV1> {
5
6
  method: 'registerPalletRuntimeSessionV1';
@@ -18,6 +19,12 @@ export interface IReq_Pallet_Controller_ReportRuntimeAssignmentObservationV1 ext
18
19
  request: data.IReportRuntimeAssignmentObservationRequestV1;
19
20
  response: data.IReportRuntimeAssignmentObservationResponseV1;
20
21
  }
22
+ /** Exact joined terminal-operation receipt; observations and boot changes cannot substitute. */
23
+ export interface IReq_Pallet_Controller_ReportRuntimeAssignmentTerminalReceiptV1 extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_ReportRuntimeAssignmentTerminalReceiptV1> {
24
+ method: 'reportRuntimeAssignmentTerminalReceiptV1';
25
+ request: terminal.IReportRuntimeAssignmentTerminalReceiptRequestV1;
26
+ response: terminal.IReportRuntimeAssignmentTerminalReceiptResponseV1;
27
+ }
21
28
  /** Current-peer, exact current assignment authorization; response is secret material. */
22
29
  export interface IReq_Pallet_Controller_GetRuntimeRegistryCredentialV1 extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_GetRuntimeRegistryCredentialV1> {
23
30
  method: 'getRuntimeRegistryCredentialV1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "29.0.0",
3
+ "version": "30.1.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
@@ -21,7 +21,7 @@
21
21
  "author": "Task Venture Capital GmbH",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "@api.global/typedrequest-interfaces": "^4.0.0",
24
+ "@api.global/typedrequest-interfaces": "^7.1.0",
25
25
  "@push.rocks/smartcrypto": "^2.2.0",
26
26
  "@push.rocks/smartlog-interfaces": "^3.0.2",
27
27
  "@tsclass/tsclass": "^9.5.1"
package/readme.md CHANGED
@@ -47,6 +47,30 @@ validator; unlike `@serve.zone/interfaces/runtime`, it does not load the general
47
47
  runtime graph, `plugins.js`, SmartCrypto, TypedRequest, Corestore, or settlement
48
48
  runtime modules.
49
49
 
50
+ ### Directional Image Streams
51
+
52
+ Image transfer contracts use `@api.global/typedrequest-interfaces` 7.1.0 and the
53
+ directional VirtualStream protocol used by TypedRequest 8 and TypedSocket 8.
54
+ Directions in shared DTOs describe the requesting peer:
55
+
56
+ | Contract field | Requester endpoint | TypedHandler endpoint |
57
+ | --- | --- | --- |
58
+ | `requests.image.IRequest_PushImageVersion.request.imageStream` | `TVirtualStream<'send'>` | `TVirtualStream<'receive'>` |
59
+ | `requests.image.IRequest_PullImageVersion.response.imageStream` | `TVirtualStream<'receive'>` | `TVirtualStream<'send'>` |
60
+
61
+ The method names remain `pushImageVersion` and `pullImageVersion`. Each stream
62
+ carries ordered `Uint8Array` chunks. TypedRequest reverses stream directions for
63
+ the handler automatically; do not reverse the shared declaration yourself.
64
+
65
+ Consumers must replace the removed undirected `IVirtualStream` API with explicit
66
+ transport-created endpoints. Senders use `send()` or `writable`, then close;
67
+ receivers use `receive()` or `readable`, then explicitly `accept()` after draining
68
+ EOF and completing application storage or delivery. `completion` confirms the
69
+ receiver's accepted receipt, while `closed` confirms transport cleanup. The
70
+ upload response's `allowed` flag permits sending; it does not confirm storage.
71
+ Receiver rejection, aborts and failed completion must reach the caller. Existing
72
+ deployment log and shell push-message contracts retain their message shapes.
73
+
50
74
  ### Human Credential Administration
51
75
 
52
76
  `requests.admin.getHumanCredential` and `mutateHumanCredential` describe human
@@ -227,6 +251,41 @@ machine JWT on a physical TypedSocket so the server can own its identity tag.
227
251
  Both registration methods reject HTTP transport. Sensitive requests and registry
228
252
  responses must be excluded from hooks, logs, diagnostics and durable journals.
229
253
 
254
+ ### Joined Runtime Terminal Receipts
255
+
256
+ `data.IRuntimeAssignmentTerminalReceiptV1` and
257
+ `requests.runtimesession.reportRuntimeAssignmentTerminalReceiptV1` carry a separate
258
+ receipt for the exact Pallet attempt's joined terminal execution. Sequence 1 binds
259
+ the generation 2 stop assignment; sequence 2 binds generation 3 removal and the
260
+ exact stop receipt digest. Both retain the original generation 1 run reference.
261
+ The full immutable assignment chain and both receipt bodies remain durable after
262
+ removal, permitting an exact earlier stop receipt to be acknowledged again.
263
+
264
+ Only a durably completed native operation can issue a terminal receipt. Native
265
+ stop joins container and sandbox stop; native remove requires an already stopped
266
+ sandbox and joins container and sandbox removal. The assignment owner separately
267
+ requires the exact completed stop before admitting removal. Terminal evidence
268
+ contains precise CRI identifiers, the kernel boot UUID, and stopped/absent state;
269
+ this native path does not collect IP addresses. Pending, unknown and host-fenced
270
+ journal entries never qualify. A proven boot change can permit a new joined
271
+ terminal operation but cannot skip the stop/remove chain.
272
+
273
+ The synchronous snapshot helpers validate bounded exact data only. Digest,
274
+ assignment-chain and receipt-chain helpers do not prove native execution or
275
+ authenticate a reporter. `bindRuntimeReporterSessionV1` and the terminal report
276
+ binder require the current physical session and immutable server-indexed reporter
277
+ history from their trusted owners. Reconnect recovery preserves every original
278
+ receipt field and returns `historical-recovery`; it never restores active
279
+ readiness, routes or liveness. The response binder rejects rewritten receipt bodies.
280
+
281
+ Cloudly must transact new acceptance against the exact global incumbent, stored
282
+ assignment chain and current peer, credential and node authority. A first receipt
283
+ after the incumbent changes is denied; only an already persisted exact receipt
284
+ can be acknowledged again under current authentication. These receipts settle
285
+ only the named Pallet attempt. They do not authorize storage relocation, prove
286
+ whole-host or Docker/Coreflow absence, grant another controller or organization
287
+ authority, or replace independently qualified readiness and routing evidence.
288
+
230
289
  ### Offline SmartDB Settlement And Packaging
231
290
 
232
291
  The Node-only `@serve.zone/interfaces/runtime` export includes isolated V1
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '29.0.0',
6
+ version: '30.1.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
package/ts/data/index.ts CHANGED
@@ -26,6 +26,7 @@ export * from './registry.js';
26
26
  export * from './runtimeassignment.js';
27
27
  export * from './runtimeconfig.js';
28
28
  export * from './runtimesession.js';
29
+ export * from './runtimeterminalreceipt.js';
29
30
  export * from './secret.js';
30
31
  export * from './baremetal.js';
31
32
  export * from './baseos.js';
@@ -61,6 +61,14 @@ export interface IReportRuntimeAssignmentObservationRequestV1 {
61
61
 
62
62
  export type TRuntimeObservationAuthorityUseV1 = 'current-session' | 'historical-recovery';
63
63
 
64
+ /** Content comparison result only; all supplied authority must come from its trusted owner. */
65
+ export interface IRuntimeReporterSessionBindingV1 {
66
+ session: IRuntimeSessionBindingV1;
67
+ assignment: IRuntimeAssignmentV1;
68
+ reporterHistory: IRuntimeSessionBindingV1;
69
+ authorityUse: TRuntimeObservationAuthorityUseV1;
70
+ }
71
+
64
72
  export interface IReportRuntimeAssignmentObservationResponseV1 {
65
73
  /** Exact request body after a durable sequence/receipt transaction. */
66
74
  observation: IRuntimeAssignmentObservationV1;
@@ -343,6 +351,32 @@ export const bindApplyRuntimeAssignmentResponseV1 = (
343
351
  return response;
344
352
  });
345
353
 
354
+ /**
355
+ * Synchronous detached content binding, not authentication. trustedSessionArg must
356
+ * be the CURRENT authenticated physical peer; reporterHistoryArg must be immutable
357
+ * server-indexed Pallet-purpose history. Never obtain either from request fields.
358
+ * The owning transaction must recheck current credential/peer authority. Assignment
359
+ * digest validation and report-specific authority remain the caller's responsibility.
360
+ */
361
+ export const bindRuntimeReporterSessionV1 = (
362
+ sessionArg: unknown, reporterSessionIdArg: string, assignmentArg: unknown,
363
+ trustedSessionArg: unknown, reporterHistoryArg: unknown,
364
+ ): IRuntimeReporterSessionBindingV1 => safe(() => {
365
+ const incomingSession = snapshotRuntimeSessionBindingV1(sessionArg);
366
+ const reporterSessionId = identifier(reporterSessionIdArg);
367
+ const assignment = snapshotRuntimeAssignmentV1(capture(assignmentArg));
368
+ const trustedSession = snapshotRuntimeSessionBindingV1(trustedSessionArg);
369
+ const reporterHistory = snapshotRuntimeSessionBindingV1(reporterHistoryArg);
370
+ requireValue(sameSession(incomingSession, trustedSession) && matchesAssignment(trustedSession, assignment)
371
+ && reporterSessionId === reporterHistory.reporterSessionId && sameOwner(trustedSession, reporterHistory));
372
+ const current = sameSession(reporterHistory, trustedSession);
373
+ requireValue(current || (reporterHistory.reporterSessionId !== trustedSession.reporterSessionId
374
+ && reporterHistory.sessionEpoch < trustedSession.sessionEpoch
375
+ && reporterHistory.credentialGeneration <= trustedSession.credentialGeneration));
376
+ return { session: incomingSession, assignment, reporterHistory,
377
+ authorityUse: current ? 'current-session' : 'historical-recovery' };
378
+ });
379
+
346
380
  /**
347
381
  * trustedSessionArg is the CURRENT authenticated physical peer. reporterHistoryArg
348
382
  * must be server-indexed immutable session history, obtained by the original
@@ -359,18 +393,10 @@ export const bindReportRuntimeAssignmentObservationRequestV1 = async (
359
393
  ): Promise<{ request: IReportRuntimeAssignmentObservationRequestV1; authorityUse: TRuntimeObservationAuthorityUseV1 }> => {
360
394
  try {
361
395
  const request = snapshotReportRuntimeAssignmentObservationRequestV1(valueArg);
362
- const assignment = snapshotRuntimeAssignmentV1(capture(assignmentArg));
363
- const trustedSession = snapshotRuntimeSessionBindingV1(trustedSessionArg);
364
- const reporterHistory = snapshotRuntimeSessionBindingV1(reporterHistoryArg);
365
- requireValue(sameSession(request.session, trustedSession) && matchesAssignment(trustedSession, assignment)
366
- && request.observation.reporterSessionId === reporterHistory.reporterSessionId
367
- && sameOwner(trustedSession, reporterHistory));
368
- const current = sameSession(reporterHistory, trustedSession);
369
- requireValue(current || (reporterHistory.reporterSessionId !== trustedSession.reporterSessionId
370
- && reporterHistory.sessionEpoch < trustedSession.sessionEpoch
371
- && reporterHistory.credentialGeneration <= trustedSession.credentialGeneration));
372
- requireValue((await validateRuntimeAssignmentObservationV1(request.observation, assignment)).length === 0);
373
- return { request, authorityUse: current ? 'current-session' : 'historical-recovery' };
396
+ const binding = bindRuntimeReporterSessionV1(request.session, request.observation.reporterSessionId,
397
+ assignmentArg, trustedSessionArg, reporterHistoryArg);
398
+ requireValue((await validateRuntimeAssignmentObservationV1(request.observation, binding.assignment)).length === 0);
399
+ return { request, authorityUse: binding.authorityUse };
374
400
  } catch { return fail(); }
375
401
  };
376
402