@serve.zone/interfaces 32.49.0 → 32.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +53 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/deploymentlegacyimport.d.ts +120 -6
- package/dist_ts/data/deploymentlegacyimport.js +289 -5
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/networkapplication.d.ts +84 -0
- package/dist_ts/data/networkapplication.js +128 -0
- package/dist_ts/data/networkprojection.d.ts +5 -3
- package/dist_ts/data/networkprojection.js +6 -4
- package/dist_ts/requests/runtimesession.d.ts +11 -0
- package/dist_ts/requests/service.d.ts +9 -5
- package/package.json +2 -2
- package/readme.md +71 -5
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/deploymentlegacyimport.ts +413 -13
- package/ts/data/index.ts +1 -0
- package/ts/data/networkapplication.ts +188 -0
- package/ts/data/networkprojection.ts +5 -3
- package/ts/requests/runtimesession.ts +14 -0
- package/ts/requests/service.ts +12 -5
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { TSha256Digest } from './immutableimage.js';
|
|
2
|
+
import type { IRuntimeAuthorityReference } from './runtimeassignment.js';
|
|
3
|
+
import type { IRuntimeNetworkNodeScope } from './networkprojection.js';
|
|
4
|
+
import { computeRuntimeNetworkProjectionDigest, snapshotRuntimeNetworkNodeScope,
|
|
5
|
+
snapshotRuntimeNetworkProjection } from './networkprojection.js';
|
|
6
|
+
import type { IRuntimeSessionBinding } from './runtimesession.js';
|
|
7
|
+
import { snapshotRuntimeSessionBinding } from './runtimesession.js';
|
|
8
|
+
import { captureNetwork, failNetwork, networkDigest, networkEqual, networkHash, networkId, networkRecord,
|
|
9
|
+
networkReference, networkReferenceOf, networkRevision, networkSafe, requireNetwork } from '../private/networkcontract.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A node's durable statement that its packet authority is bounded by one admitted projection.
|
|
13
|
+
*
|
|
14
|
+
* Every packet table the node holds was composed from `projection`, or the node holds none: the
|
|
15
|
+
* flows its kernel admits are a subset of that projection's grants. Only the node's joined native
|
|
16
|
+
* packet owner can supply it — the journaled application of the projection's policies on every
|
|
17
|
+
* role, or the release of every table — never an admission ACK, a single table inspection or a
|
|
18
|
+
* caller-selected flag. A crash, a reboot or a restored guard only removes authority, so a receipt
|
|
19
|
+
* never becomes false; applying a successor projection supersedes it.
|
|
20
|
+
*
|
|
21
|
+
* `nativeJournal` names the node-private joined packet journal that applied the projection, or is
|
|
22
|
+
* null when the node holds no packet table at all. The receipts of one node form one monotonic
|
|
23
|
+
* chain; a receipt never names an older projection than its predecessor. These portable values
|
|
24
|
+
* neither inspect a kernel nor authenticate their producer: the receiver binds the report to the
|
|
25
|
+
* current authenticated session or its own reporter history.
|
|
26
|
+
*/
|
|
27
|
+
export interface IRuntimeNetworkProjectionApplicationReceipt extends IRuntimeNetworkNodeScope {
|
|
28
|
+
id: string;
|
|
29
|
+
generation: number;
|
|
30
|
+
previous: IRuntimeAuthorityReference | null;
|
|
31
|
+
projection: IRuntimeAuthorityReference;
|
|
32
|
+
reporterSessionId: string;
|
|
33
|
+
bootId: string;
|
|
34
|
+
nativeJournal: IRuntimeAuthorityReference | null;
|
|
35
|
+
digest: TSha256Digest;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface IReportRuntimeNetworkProjectionApplicationRequest {
|
|
39
|
+
session: IRuntimeSessionBinding;
|
|
40
|
+
receipt: IRuntimeNetworkProjectionApplicationReceipt;
|
|
41
|
+
}
|
|
42
|
+
export interface IReportRuntimeNetworkProjectionApplicationResponse {
|
|
43
|
+
status: 'accepted' | 'replay';
|
|
44
|
+
receipt: IRuntimeAuthorityReference;
|
|
45
|
+
authorityUse: 'current' | 'historical';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const runtimeNetworkProjectionApplicationContract = Object.freeze({
|
|
49
|
+
digestDomain: 'serve.zone/runtime-network-projection-application-receipt',
|
|
50
|
+
claim: 'packet-authority-within-the-grants-of-the-named-projection',
|
|
51
|
+
receiptSource: 'joined-native-packet-journal-or-no-packet-table',
|
|
52
|
+
appliedPrevious: 'only-a-receipt-naming-the-exact-previous-projection',
|
|
53
|
+
olderProjection: 'advances-the-chain-never-applied-previous',
|
|
54
|
+
acknowledgement: 'an-admission-ack-is-never-an-application-receipt',
|
|
55
|
+
authentication: 'current-authenticated-session-or-receiver-reporter-history',
|
|
56
|
+
} as const);
|
|
57
|
+
|
|
58
|
+
const bootIdPattern = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
|
|
59
|
+
const scopeOf = (value: IRuntimeNetworkNodeScope): IRuntimeNetworkNodeScope =>
|
|
60
|
+
({ controller: value.controller, nodeId: value.nodeId, runtimeNamespace: value.runtimeNamespace });
|
|
61
|
+
const bootId = (value: unknown): string => {
|
|
62
|
+
requireNetwork(typeof value === 'string' && bootIdPattern.test(value) && value !== '00000000-0000-0000-0000-000000000000');
|
|
63
|
+
return value;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** Exact-key structural snapshot; digest and chain rules are `admitRuntimeNetworkProjectionApplicationReceipt`'s. */
|
|
67
|
+
export const snapshotRuntimeNetworkProjectionApplicationReceipt = (
|
|
68
|
+
value: unknown,
|
|
69
|
+
): IRuntimeNetworkProjectionApplicationReceipt => networkSafe(() => {
|
|
70
|
+
const item = networkRecord(captureNetwork(value), ['id', 'generation', 'previous', 'controller', 'nodeId',
|
|
71
|
+
'runtimeNamespace', 'projection', 'reporterSessionId', 'bootId', 'nativeJournal', 'digest']);
|
|
72
|
+
const scope = snapshotRuntimeNetworkNodeScope({ controller: item.controller, nodeId: item.nodeId,
|
|
73
|
+
runtimeNamespace: item.runtimeNamespace });
|
|
74
|
+
return { ...networkRevision(item), ...scope, projection: networkReference(item.projection),
|
|
75
|
+
reporterSessionId: networkId(item.reporterSessionId), bootId: bootId(item.bootId),
|
|
76
|
+
nativeJournal: item.nativeJournal === null ? null : networkReference(item.nativeJournal),
|
|
77
|
+
digest: networkDigest(item.digest) };
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const computeRuntimeNetworkProjectionApplicationReceiptDigest = (
|
|
81
|
+
value: IRuntimeNetworkProjectionApplicationReceipt,
|
|
82
|
+
): Promise<TSha256Digest> => networkHash(runtimeNetworkProjectionApplicationContract.digestDomain,
|
|
83
|
+
snapshotRuntimeNetworkProjectionApplicationReceipt(value));
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Pure chain binding of one reported receipt. `previousReceiptValue` is the receiver's current
|
|
87
|
+
* receipt for the node, or null while it holds none; `headValue` is the receiver's current
|
|
88
|
+
* projection for the node. The owner must authenticate the reporter and fence its writes.
|
|
89
|
+
*
|
|
90
|
+
* The receipt names the head's projection chain at a generation the head has reached: the head
|
|
91
|
+
* itself, exactly, or an older generation. An older one is a receipt minted before the node
|
|
92
|
+
* admitted the head; it advances the chain and is never usable as `appliedPrevious`.
|
|
93
|
+
*/
|
|
94
|
+
export const admitRuntimeNetworkProjectionApplicationReceipt = async (
|
|
95
|
+
value: unknown, previousReceiptValue: unknown | null, trustedScopeValue: unknown, headValue: unknown,
|
|
96
|
+
): Promise<{ status: 'accepted' | 'replay'; receipt: IRuntimeNetworkProjectionApplicationReceipt }> => {
|
|
97
|
+
try {
|
|
98
|
+
const receipt = snapshotRuntimeNetworkProjectionApplicationReceipt(value);
|
|
99
|
+
const previous = previousReceiptValue === null ? null : snapshotRuntimeNetworkProjectionApplicationReceipt(previousReceiptValue);
|
|
100
|
+
const scope = snapshotRuntimeNetworkNodeScope(captureNetwork(trustedScopeValue));
|
|
101
|
+
const head = snapshotRuntimeNetworkProjection(headValue);
|
|
102
|
+
requireNetwork(networkEqual(scopeOf(receipt), scope) && networkEqual(scopeOf(head), scope));
|
|
103
|
+
requireNetwork(receipt.digest === await computeRuntimeNetworkProjectionApplicationReceiptDigest(receipt)
|
|
104
|
+
&& head.digest === await computeRuntimeNetworkProjectionDigest(head));
|
|
105
|
+
requireNetwork(receipt.projection.id === head.id && receipt.projection.generation <= head.generation);
|
|
106
|
+
if (receipt.projection.generation === head.generation) requireNetwork(networkEqual(receipt.projection, networkReferenceOf(head)));
|
|
107
|
+
if (previous === null) requireNetwork(receipt.generation === 1 && receipt.previous === null);
|
|
108
|
+
else {
|
|
109
|
+
requireNetwork(networkEqual(scopeOf(previous), scope)
|
|
110
|
+
&& previous.digest === await computeRuntimeNetworkProjectionApplicationReceiptDigest(previous));
|
|
111
|
+
if (networkEqual(receipt, previous)) return { status: 'replay', receipt };
|
|
112
|
+
requireNetwork(receipt.id === previous.id && receipt.generation === previous.generation + 1
|
|
113
|
+
&& networkEqual(receipt.previous, networkReferenceOf(previous))
|
|
114
|
+
&& receipt.projection.id === previous.projection.id
|
|
115
|
+
&& receipt.projection.generation >= previous.projection.generation);
|
|
116
|
+
if (receipt.projection.generation === previous.projection.generation) {
|
|
117
|
+
requireNetwork(networkEqual(receipt.projection, previous.projection));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return { status: 'accepted', receipt };
|
|
121
|
+
} catch { return failNetwork(); }
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The `appliedPrevious` argument of `admitRuntimeNetworkProjection` for the successor of
|
|
126
|
+
* `previousProjectionValue`: the receipt's projection when it is exactly that projection, else
|
|
127
|
+
* null. `receiptValue` must be the receiver's own admitted receipt for the node (a node passes its
|
|
128
|
+
* own durable receipt, a controller the latest receipt it admitted), never an ACK field.
|
|
129
|
+
*/
|
|
130
|
+
export const selectRuntimeNetworkProjectionAppliedPrevious = async (
|
|
131
|
+
receiptValue: unknown | null, previousProjectionValue: unknown,
|
|
132
|
+
): Promise<IRuntimeAuthorityReference | null> => {
|
|
133
|
+
try {
|
|
134
|
+
// Snapshot both caller-owned inputs before the first asynchronous operation.
|
|
135
|
+
const previous = snapshotRuntimeNetworkProjection(previousProjectionValue);
|
|
136
|
+
const receipt = receiptValue === null ? null : snapshotRuntimeNetworkProjectionApplicationReceipt(receiptValue);
|
|
137
|
+
requireNetwork(previous.digest === await computeRuntimeNetworkProjectionDigest(previous));
|
|
138
|
+
if (receipt === null) return null;
|
|
139
|
+
requireNetwork(networkEqual(scopeOf(receipt), scopeOf(previous))
|
|
140
|
+
&& receipt.digest === await computeRuntimeNetworkProjectionApplicationReceiptDigest(receipt));
|
|
141
|
+
return networkEqual(receipt.projection, networkReferenceOf(previous)) ? networkReferenceOf(receipt.projection) : null;
|
|
142
|
+
} catch { return failNetwork(); }
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export const snapshotReportRuntimeNetworkProjectionApplicationRequest = (
|
|
146
|
+
value: unknown,
|
|
147
|
+
): IReportRuntimeNetworkProjectionApplicationRequest => networkSafe(() => {
|
|
148
|
+
const item = networkRecord(captureNetwork(value), ['session', 'receipt']);
|
|
149
|
+
return { session: snapshotRuntimeSessionBinding(item.session),
|
|
150
|
+
receipt: snapshotRuntimeNetworkProjectionApplicationReceipt(item.receipt) };
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Both trusted bindings come from the receiver's fenced physical-session/history owner: the
|
|
155
|
+
* current session, and the session history entry that names the receipt's reporter. A receipt
|
|
156
|
+
* minted under an earlier session of the same node still drains from its outbox as `historical`.
|
|
157
|
+
*/
|
|
158
|
+
export const bindReportRuntimeNetworkProjectionApplicationRequest = (
|
|
159
|
+
value: unknown, trustedCurrentSessionValue: unknown, trustedReporterSessionValue: unknown,
|
|
160
|
+
): { request: IReportRuntimeNetworkProjectionApplicationRequest; authorityUse: 'current' | 'historical' } => networkSafe(() => {
|
|
161
|
+
const request = snapshotReportRuntimeNetworkProjectionApplicationRequest(value);
|
|
162
|
+
const current = snapshotRuntimeSessionBinding(captureNetwork(trustedCurrentSessionValue));
|
|
163
|
+
const reporter = snapshotRuntimeSessionBinding(captureNetwork(trustedReporterSessionValue));
|
|
164
|
+
requireNetwork(networkEqual(request.session, current) && networkEqual(scopeOf(request.receipt), scopeOf(current))
|
|
165
|
+
&& networkEqual(scopeOf(reporter), scopeOf(current)) && reporter.reporterSessionId === request.receipt.reporterSessionId);
|
|
166
|
+
const authorityUse = reporter.reporterSessionId === current.reporterSessionId ? 'current' : 'historical';
|
|
167
|
+
requireNetwork(authorityUse === 'current' ? networkEqual(reporter, current)
|
|
168
|
+
: reporter.sessionEpoch < current.sessionEpoch && reporter.credentialGeneration <= current.credentialGeneration);
|
|
169
|
+
return { request, authorityUse };
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export const snapshotReportRuntimeNetworkProjectionApplicationResponse = (
|
|
173
|
+
value: unknown,
|
|
174
|
+
): IReportRuntimeNetworkProjectionApplicationResponse => networkSafe(() => {
|
|
175
|
+
const item = networkRecord(captureNetwork(value), ['status', 'receipt', 'authorityUse']);
|
|
176
|
+
requireNetwork((item.status === 'accepted' || item.status === 'replay')
|
|
177
|
+
&& (item.authorityUse === 'current' || item.authorityUse === 'historical'));
|
|
178
|
+
return { status: item.status, receipt: networkReference(item.receipt), authorityUse: item.authorityUse };
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
/** Compare the response with the exact SENT receipt, never with a response-derived value. */
|
|
182
|
+
export const bindReportRuntimeNetworkProjectionApplicationResponse = (
|
|
183
|
+
value: unknown, sentReceiptValue: unknown,
|
|
184
|
+
): IReportRuntimeNetworkProjectionApplicationResponse => networkSafe(() => {
|
|
185
|
+
const response = snapshotReportRuntimeNetworkProjectionApplicationResponse(value);
|
|
186
|
+
requireNetwork(networkEqual(response.receipt, networkReference(captureNetwork(sentReceiptValue))));
|
|
187
|
+
return response;
|
|
188
|
+
});
|
|
@@ -788,9 +788,11 @@ export const bindRuntimeNetworkWorkloadLeaseToAssignment = async (leaseValue: un
|
|
|
788
788
|
};
|
|
789
789
|
|
|
790
790
|
/**
|
|
791
|
-
* Pure revision decision. appliedPrevious must
|
|
792
|
-
* joined application receipt
|
|
793
|
-
*
|
|
791
|
+
* Pure revision decision. appliedPrevious must come from the receiver's exact durable,
|
|
792
|
+
* joined application receipt (`IRuntimeNetworkProjectionApplicationReceipt`, selected by
|
|
793
|
+
* `selectRuntimeNetworkProjectionAppliedPrevious`), never from an incoming ACK field. Only a
|
|
794
|
+
* receipt naming exactly `previousValue` releases its carried withdrawals and tombstones. All
|
|
795
|
+
* prior accepted material/apply journals survive until effects and DNS/allocation quarantine end.
|
|
794
796
|
*/
|
|
795
797
|
export const admitRuntimeNetworkProjection = async (
|
|
796
798
|
value: unknown, previousValue: unknown | null, trustedScopeValue: unknown, appliedPreviousValue: unknown | null,
|
|
@@ -4,6 +4,7 @@ import type * as binding from '../data/noderuntimebinding.js';
|
|
|
4
4
|
import type * as terminal from '../data/runtimeterminalreceipt.js';
|
|
5
5
|
import type * as network from '../data/networkdelivery.js';
|
|
6
6
|
import type * as protection from '../data/networkprotection.js';
|
|
7
|
+
import type * as application from '../data/networkapplication.js';
|
|
7
8
|
import type * as credential from '../data/networkcredential.js';
|
|
8
9
|
import type * as assignmentSecret from '../runtime.assignmentsecret.js';
|
|
9
10
|
import type * as fleet from '../data/fleetcutover.js';
|
|
@@ -32,6 +33,19 @@ export interface IReq_Pallet_Controller_ReportRuntimeNetworkProtection extends p
|
|
|
32
33
|
response: protection.IReportRuntimeNetworkProtectionResponse;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Current authenticated peer reports its durable joined application receipt: the projection that
|
|
38
|
+
* bounds its packet authority. The controller passes it as `appliedPrevious` only while it names
|
|
39
|
+
* the exact head; an admission ACK never stands in for it.
|
|
40
|
+
*/
|
|
41
|
+
export interface IReq_Pallet_Controller_ReportRuntimeNetworkProjectionApplication extends plugins.typedrequestInterfaces.implementsTR<
|
|
42
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_ReportRuntimeNetworkProjectionApplication
|
|
43
|
+
> {
|
|
44
|
+
method: 'reportRuntimeNetworkProjectionApplication';
|
|
45
|
+
request: application.IReportRuntimeNetworkProjectionApplicationRequest;
|
|
46
|
+
response: application.IReportRuntimeNetworkProjectionApplicationResponse;
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
/**
|
|
36
50
|
* Current authenticated Pallet session only. Cloudly reads the current pallet runtime and exact
|
|
37
51
|
* owner records, then grants one held prepared handoff; serialized session content is no proof.
|
package/ts/requests/service.ts
CHANGED
|
@@ -17,7 +17,10 @@ import type {
|
|
|
17
17
|
IServiceDeploymentStatus,
|
|
18
18
|
} from '../data/deploymentoperation.js';
|
|
19
19
|
import type { TSha256Digest } from '../data/immutableimage.js';
|
|
20
|
-
import type {
|
|
20
|
+
import type {
|
|
21
|
+
ILegacyServiceHostObservation,
|
|
22
|
+
ILegacyServiceRuntimeAttestation,
|
|
23
|
+
} from '../data/deploymentlegacyimport.js';
|
|
21
24
|
import type { IProtocolOffer } from '../protocol.js';
|
|
22
25
|
import type {
|
|
23
26
|
IRuntimeAssignmentLogAttemptPage,
|
|
@@ -330,10 +333,13 @@ extends plugins.typedrequestInterfaces.implementsTR<
|
|
|
330
333
|
}
|
|
331
334
|
|
|
332
335
|
/**
|
|
333
|
-
* Captures durable evidence that a legacy `deployOnPush` service runs exactly
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
336
|
+
* Captures durable evidence that a legacy `deployOnPush` service runs exactly one registry root of
|
|
337
|
+
* its own repository, from an administrator's observation of its Swarm service and containers on
|
|
338
|
+
* the hosts that run them (`hostObservation`). Cloudly judges the observation itself
|
|
339
|
+
* (`data.judgeLegacyServiceHostObservation`): every desired replica running, healthy or without a
|
|
340
|
+
* healthcheck, on one root that is whole in Cloudly's own registry, its platform manifests read
|
|
341
|
+
* from there. The source tag need not still name that root. Administrators only, and only while
|
|
342
|
+
* the legacy runtime still runs — incomplete evidence is refused, never stored.
|
|
337
343
|
*
|
|
338
344
|
* `expectedRuntimeDigest`, when stated, is an assertion the observed digest must equal. Capturing
|
|
339
345
|
* again for an unchanged digest returns the attestation already stored.
|
|
@@ -348,6 +354,7 @@ extends plugins.typedrequestInterfaces.implementsTR<
|
|
|
348
354
|
identity: IIdentityCredential;
|
|
349
355
|
legacyServiceId: string;
|
|
350
356
|
expectedRuntimeDigest?: TSha256Digest;
|
|
357
|
+
hostObservation: ILegacyServiceHostObservation;
|
|
351
358
|
};
|
|
352
359
|
response: {
|
|
353
360
|
attestation: ILegacyServiceRuntimeAttestation;
|