@serve.zone/interfaces 30.7.0 → 30.9.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,448 @@
1
+ import type { TSha256Digest } from './immutableimage.js';
2
+ import type { IRuntimeAssignmentReferenceV1, IRuntimeAuthorityReferenceV1, IRuntimeControllerV1 } from './runtimeassignment.js';
3
+ import { snapshotRuntimeAssignmentV1, validateRuntimeAssignmentV1 } from './runtimeassignment.js';
4
+ import type { IRuntimeNetworkHandoffLeaseV1, IRuntimeNetworkProtectedAuthorityV1 } from './networkauthority.js';
5
+ import { bindRuntimeNetworkHandoffLeaseV1, computeRuntimeNetworkProtectedAuthorityV1Digest,
6
+ snapshotRuntimeNetworkHandoffLeaseV1, snapshotRuntimeNetworkProtectedAuthorityV1 } from './networkauthority.js';
7
+ import type { IPrivateNetworkV1, IServicePrivateNetworksV1, IServicePrivateNetworkDnsPolicyV1 } from './privatenetwork.js';
8
+ import { buildPrivateNetworkFqdnV1, composeServicePrivateNetworkDnsPolicyV1,
9
+ snapshotPrivateNetworkV1, snapshotServicePrivateNetworksV1 } from './privatenetwork.js';
10
+ import { captureNetwork, failNetwork, networkCanonical, networkContains, networkController, networkCounter,
11
+ networkDigest, networkEqual, networkHash, networkId, networkIpv4, networkIpv4Number, networkList,
12
+ networkOverlaps, networkPrefixBounds, networkRecord, networkReference, networkReferenceOf, networkRevision,
13
+ networkSafe, networkSorted, requireNetwork } from '../private/networkcontract.js';
14
+
15
+ export interface IRuntimeNetworkNodeScopeV1 {
16
+ controller: IRuntimeControllerV1;
17
+ nodeId: string;
18
+ runtimeNamespace: string;
19
+ }
20
+
21
+ /** Immutable per-attempt address material. Membership and projection revisions are independent. */
22
+ export interface IRuntimeNetworkWorkloadLeaseV1 extends IRuntimeNetworkNodeScopeV1 {
23
+ schemaVersion: 1;
24
+ id: string;
25
+ /** Allocation incarnation, not a mutable desired-state revision. */
26
+ generation: number;
27
+ organizationId: string;
28
+ assignmentId: string;
29
+ serviceId: string;
30
+ replicaId: string;
31
+ attemptId: string;
32
+ protectedAuthority: IRuntimeAuthorityReferenceV1;
33
+ routerIncarnationId: string;
34
+ ipv4: {
35
+ poolId: string;
36
+ /** Dedicated, unbridged point-to-point subnet; never the host transit pool. */
37
+ linkSubnet: string;
38
+ address: string;
39
+ /** Exactly address/32, distinct from the link subnet and node-control prefix. */
40
+ sourcePrefix: string;
41
+ gateway: string;
42
+ };
43
+ /** Router-side reachable address on port 53, injected through CRI dns_config. */
44
+ dnsServer: string;
45
+ digest: TSha256Digest;
46
+ }
47
+
48
+ /** Controller-owned readiness evidence. A signature does not prove this evidence's provenance. */
49
+ export interface IRuntimeNetworkEndpointV1 {
50
+ lease: IRuntimeNetworkWorkloadLeaseV1;
51
+ ready: boolean;
52
+ observation: {
53
+ assignment: IRuntimeAssignmentReferenceV1;
54
+ reporterSessionId: string;
55
+ sequence: number;
56
+ digest: TSha256Digest;
57
+ } | null;
58
+ /** TCP/UDP only; the complete protected union remains denied. */
59
+ publicEgress: boolean;
60
+ platformEndpointIds: string[];
61
+ }
62
+
63
+ /** Exact directed grant identity; receiver-owned realization resolves the lease to kernel facts. */
64
+ export interface IRuntimeNetworkPacketGrantV1 {
65
+ source: IRuntimeAuthorityReferenceV1;
66
+ destination:
67
+ | { kind: 'workload'; lease: IRuntimeAuthorityReferenceV1 }
68
+ | { kind: 'public' }
69
+ | { kind: 'platform'; id: string; address: string; protocol: 'tcp' | 'udp'; port: number };
70
+ }
71
+
72
+ export interface IRuntimeNetworkProjectionV1 extends IRuntimeNetworkNodeScopeV1 {
73
+ schemaVersion: 1;
74
+ id: string;
75
+ generation: number;
76
+ previous: IRuntimeAuthorityReferenceV1 | null;
77
+ protectedAuthority: IRuntimeNetworkProtectedAuthorityV1;
78
+ /** Exact historical authorities needed to authenticate retained allocation material. */
79
+ allocationAuthorities: IRuntimeNetworkProtectedAuthorityV1[];
80
+ handoff: IRuntimeNetworkHandoffLeaseV1 | null;
81
+ /** COMPLETE relevant definitions, including declared names with no ready replicas. */
82
+ networks: IPrivateNetworkV1[];
83
+ memberships: IServicePrivateNetworksV1[];
84
+ endpoints: IRuntimeNetworkEndpointV1[];
85
+ dns: { issuedAt: number; notBefore: number; expiresAt: number };
86
+ /** Explicit denial intent. Carry until the exact predecessor's application is proven. */
87
+ withdrawals: IRuntimeNetworkPacketGrantV1[];
88
+ retiredLeases: IRuntimeAuthorityReferenceV1[];
89
+ retiredHandoffs: IRuntimeAuthorityReferenceV1[];
90
+ digest: TSha256Digest;
91
+ }
92
+
93
+ export interface IRuntimeNetworkDnsViewV1 {
94
+ source: IRuntimeAuthorityReferenceV1;
95
+ sourceAddress: string;
96
+ dnsServer: string;
97
+ policy: IServicePrivateNetworkDnsPolicyV1;
98
+ /** Sorted complete A sets; [] is declared NODATA, never an omitted name. AAAA is NODATA. */
99
+ records: Array<{ name: string; addresses: string[] }>;
100
+ }
101
+
102
+ export const runtimeNetworkProjectionV1Contract = Object.freeze({
103
+ workloadDigestDomain: 'serve.zone/runtime-network-workload-lease-v1',
104
+ projectionDigestDomain: 'serve.zone/runtime-network-projection-v1',
105
+ maximumCanonicalBytes: 917_504,
106
+ maximumAllocationAuthorities: 16,
107
+ maximumNetworks: 128,
108
+ maximumMemberships: 256,
109
+ maximumEndpoints: 256,
110
+ maximumGrants: 4096,
111
+ maximumDnsLeaseMs: 900_000,
112
+ positiveTtlSeconds: 5,
113
+ negativeTtlSeconds: 1,
114
+ omission: 'no-effect-without-explicit-withdrawal',
115
+ packetLifetime: 'until-applied-denial-or-independent-fence',
116
+ acknowledgement: 'admission-is-not-application-or-readiness',
117
+ allocationReuse: 'requires-controller-quarantine-and-all-affected-authority-fences',
118
+ } as const);
119
+
120
+ const scope = (item: Record<string, unknown>): IRuntimeNetworkNodeScopeV1 => ({
121
+ controller: networkController(item.controller), nodeId: networkId(item.nodeId), runtimeNamespace: networkId(item.runtimeNamespace),
122
+ });
123
+ const sameScope = (left: IRuntimeNetworkNodeScopeV1, right: IRuntimeNetworkNodeScopeV1): boolean =>
124
+ networkEqual(left.controller, right.controller) && left.nodeId === right.nodeId && left.runtimeNamespace === right.runtimeNamespace;
125
+ const ownerKey = (value: { organizationId: string; serviceId: string }): string => networkCanonical([value.organizationId, value.serviceId]);
126
+ const attemptKey = (value: IRuntimeNetworkWorkloadLeaseV1): string =>
127
+ networkCanonical([value.organizationId, value.serviceId, value.replicaId, value.attemptId]);
128
+ const refKey = (value: IRuntimeAuthorityReferenceV1): string => networkCanonical(networkReferenceOf(value));
129
+ const sortedReferences = (value: unknown): IRuntimeAuthorityReferenceV1[] =>
130
+ networkSorted(networkList(value, 256, networkReference), refKey);
131
+
132
+ export const snapshotRuntimeNetworkNodeScopeV1 = (value: unknown): IRuntimeNetworkNodeScopeV1 => networkSafe(() =>
133
+ scope(networkRecord(captureNetwork(value), ['controller', 'nodeId', 'runtimeNamespace'])));
134
+
135
+ export const snapshotRuntimeNetworkWorkloadLeaseV1 = (value: unknown): IRuntimeNetworkWorkloadLeaseV1 => networkSafe(() => {
136
+ const item = networkRecord(captureNetwork(value), ['schemaVersion', 'id', 'generation', 'controller', 'nodeId', 'runtimeNamespace',
137
+ 'organizationId', 'assignmentId', 'serviceId', 'replicaId', 'attemptId', 'protectedAuthority', 'routerIncarnationId', 'ipv4', 'dnsServer', 'digest']);
138
+ requireNetwork(item.schemaVersion === 1);
139
+ const ip = networkRecord(item.ipv4, ['poolId', 'linkSubnet', 'address', 'sourcePrefix', 'gateway']);
140
+ requireNetwork(typeof ip.linkSubnet === 'string' && ip.linkSubnet.length <= 18);
141
+ const pieces = ip.linkSubnet.split('/');
142
+ requireNetwork(pieces.length === 2 && /^(?:[89]|[12][0-9]|3[01])$/.test(pieces[1]));
143
+ const first = networkIpv4Number(networkIpv4(pieces[0]));
144
+ requireNetwork(first % 2 ** (32 - Number(pieces[1])) === 0
145
+ && ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'].some(prefix => networkContains(prefix, ip.linkSubnet as string)));
146
+ const address = networkIpv4(ip.address), gateway = networkIpv4(ip.gateway), [low, high] = networkPrefixBounds(ip.linkSubnet);
147
+ requireNetwork(address !== gateway && ip.sourcePrefix === `${address}/32`);
148
+ for (const current of [address, gateway]) {
149
+ const number = networkIpv4Number(current);
150
+ requireNetwork(number >= low && number <= high && (high - low === 1 || (number !== low && number !== high)));
151
+ }
152
+ requireNetwork(item.dnsServer === gateway);
153
+ return { schemaVersion: 1, id: networkId(item.id), generation: networkCounter(item.generation), ...scope(item),
154
+ organizationId: networkId(item.organizationId), assignmentId: networkId(item.assignmentId), serviceId: networkId(item.serviceId),
155
+ replicaId: networkId(item.replicaId), attemptId: networkId(item.attemptId), protectedAuthority: networkReference(item.protectedAuthority),
156
+ routerIncarnationId: networkId(item.routerIncarnationId), ipv4: { poolId: networkId(ip.poolId), linkSubnet: ip.linkSubnet,
157
+ address, sourcePrefix: ip.sourcePrefix, gateway }, dnsServer: gateway, digest: networkDigest(item.digest) };
158
+ });
159
+
160
+ export const computeRuntimeNetworkWorkloadLeaseV1Digest = (value: IRuntimeNetworkWorkloadLeaseV1): Promise<TSha256Digest> =>
161
+ networkHash(runtimeNetworkProjectionV1Contract.workloadDigestDomain, snapshotRuntimeNetworkWorkloadLeaseV1(value));
162
+
163
+ const packetGrant = (value: unknown): IRuntimeNetworkPacketGrantV1 => {
164
+ const item = networkRecord(value, ['source', 'destination']);
165
+ requireNetwork(item.destination !== null && typeof item.destination === 'object');
166
+ const kind = (item.destination as Record<string, unknown>).kind;
167
+ if (kind === 'workload') {
168
+ const destination = networkRecord(item.destination, ['kind', 'lease']);
169
+ const source = networkReference(item.source), lease = networkReference(destination.lease);
170
+ requireNetwork(!networkEqual(source, lease));
171
+ return { source, destination: { kind, lease } };
172
+ }
173
+ if (kind === 'public') {
174
+ networkRecord(item.destination, ['kind']); return { source: networkReference(item.source), destination: { kind } };
175
+ }
176
+ requireNetwork(kind === 'platform');
177
+ const destination = networkRecord(item.destination, ['kind', 'id', 'address', 'protocol', 'port']);
178
+ requireNetwork(destination.protocol === 'tcp' || destination.protocol === 'udp');
179
+ return { source: networkReference(item.source), destination: { kind, id: networkId(destination.id), address: networkIpv4(destination.address),
180
+ protocol: destination.protocol, port: networkCounter(destination.port, 65535) } };
181
+ };
182
+ const endpoint = (value: unknown): IRuntimeNetworkEndpointV1 => {
183
+ const item = networkRecord(value, ['lease', 'ready', 'observation', 'publicEgress', 'platformEndpointIds']);
184
+ requireNetwork(typeof item.ready === 'boolean' && typeof item.publicEgress === 'boolean');
185
+ const lease = snapshotRuntimeNetworkWorkloadLeaseV1(item.lease);
186
+ let observation: IRuntimeNetworkEndpointV1['observation'] = null;
187
+ if (item.observation !== null) {
188
+ const observed = networkRecord(item.observation, ['assignment', 'reporterSessionId', 'sequence', 'digest']);
189
+ const assignment = networkRecord(observed.assignment, ['assignmentId', 'generation', 'digest']);
190
+ requireNetwork(assignment.assignmentId === lease.assignmentId);
191
+ observation = { assignment: { assignmentId: lease.assignmentId, generation: networkCounter(assignment.generation), digest: networkDigest(assignment.digest) },
192
+ reporterSessionId: networkId(observed.reporterSessionId), sequence: networkCounter(observed.sequence), digest: networkDigest(observed.digest) };
193
+ }
194
+ requireNetwork(!item.ready || (observation !== null && observation.assignment.generation === 1));
195
+ return { lease, ready: item.ready, observation, publicEgress: item.publicEgress,
196
+ platformEndpointIds: networkSorted(networkList(item.platformEndpointIds, 64, networkId), value => value) };
197
+ };
198
+
199
+ /** Structural snapshot only; use validate/signature/admission helpers before accepting authority. */
200
+ export const snapshotRuntimeNetworkProjectionV1 = (value: unknown): IRuntimeNetworkProjectionV1 => networkSafe(() => {
201
+ const captured = captureNetwork(value);
202
+ requireNetwork(new TextEncoder().encode(networkCanonical(captured)).length <= runtimeNetworkProjectionV1Contract.maximumCanonicalBytes);
203
+ const item = networkRecord(captured, ['schemaVersion', 'id', 'generation', 'previous', 'controller', 'nodeId', 'runtimeNamespace',
204
+ 'protectedAuthority', 'allocationAuthorities', 'handoff', 'networks', 'memberships', 'endpoints', 'dns', 'withdrawals', 'retiredLeases', 'retiredHandoffs', 'digest']);
205
+ requireNetwork(item.schemaVersion === 1);
206
+ const dns = networkRecord(item.dns, ['issuedAt', 'notBefore', 'expiresAt']);
207
+ const window = { issuedAt: networkCounter(dns.issuedAt), notBefore: networkCounter(dns.notBefore), expiresAt: networkCounter(dns.expiresAt) };
208
+ requireNetwork(window.notBefore >= window.issuedAt && window.expiresAt > window.notBefore && window.expiresAt - window.issuedAt <= 900_000);
209
+ return { schemaVersion: 1, ...networkRevision(item), ...scope(item),
210
+ protectedAuthority: snapshotRuntimeNetworkProtectedAuthorityV1(item.protectedAuthority),
211
+ allocationAuthorities: networkSorted(networkList(item.allocationAuthorities, 16, snapshotRuntimeNetworkProtectedAuthorityV1), refKey),
212
+ handoff: item.handoff === null ? null : snapshotRuntimeNetworkHandoffLeaseV1(item.handoff),
213
+ networks: networkSorted(networkList(item.networks, 128, snapshotPrivateNetworkV1), value => value.id),
214
+ memberships: networkSorted(networkList(item.memberships, 256, snapshotServicePrivateNetworksV1), ownerKey),
215
+ endpoints: networkSorted(networkList(item.endpoints, 256, endpoint), value => value.lease.id), dns: window,
216
+ withdrawals: networkSorted(networkList(item.withdrawals, 4096, packetGrant), networkCanonical),
217
+ retiredLeases: sortedReferences(item.retiredLeases), retiredHandoffs: sortedReferences(item.retiredHandoffs), digest: networkDigest(item.digest) };
218
+ });
219
+
220
+ const grantsOf = (projection: IRuntimeNetworkProjectionV1): IRuntimeNetworkPacketGrantV1[] => {
221
+ const result: IRuntimeNetworkPacketGrantV1[] = [];
222
+ const memberships = new Map(projection.memberships.map(member => [ownerKey(member), member]));
223
+ const append = (grant: IRuntimeNetworkPacketGrantV1) => {
224
+ requireNetwork(result.length < 4096); result.push(grant);
225
+ };
226
+ for (const source of projection.endpoints) {
227
+ const member = memberships.get(ownerKey(source.lease)); requireNetwork(member);
228
+ for (const destination of projection.endpoints) {
229
+ if (source === destination || (!sameScope(source.lease, projection) && !sameScope(destination.lease, projection))) continue;
230
+ const target = memberships.get(ownerKey(destination.lease)); requireNetwork(target);
231
+ if (member.organizationId === target.organizationId && member.attachments.some(attachment =>
232
+ target.attachments.some(other => other.networkId === attachment.networkId))) {
233
+ append({ source: networkReferenceOf(source.lease), destination: { kind: 'workload', lease: networkReferenceOf(destination.lease) } });
234
+ }
235
+ }
236
+ if (!sameScope(source.lease, projection)) continue;
237
+ if (source.publicEgress) append({ source: networkReferenceOf(source.lease), destination: { kind: 'public' } });
238
+ for (const id of source.platformEndpointIds) {
239
+ const platform = projection.protectedAuthority.platformEndpoints.find(item => item.id === id); requireNetwork(platform);
240
+ append({ source: networkReferenceOf(source.lease), destination: { kind: 'platform', ...platform } });
241
+ }
242
+ }
243
+ return result.sort((left, right) => networkCanonical(left) < networkCanonical(right) ? -1 : 1);
244
+ };
245
+
246
+ export const computeRuntimeNetworkProjectionV1Digest = (value: IRuntimeNetworkProjectionV1): Promise<TSha256Digest> =>
247
+ networkHash(runtimeNetworkProjectionV1Contract.projectionDigestDomain, snapshotRuntimeNetworkProjectionV1(value));
248
+
249
+ /** Complete structural, digest, allocation and policy binding. Not an allocation/barrier/readiness proof. */
250
+ export const validateRuntimeNetworkProjectionV1 = async (value: unknown): Promise<IRuntimeNetworkProjectionV1> => {
251
+ try {
252
+ const projection = snapshotRuntimeNetworkProjectionV1(value), current = projection.protectedAuthority;
253
+ requireNetwork(networkEqual(current.controller, projection.controller) && current.egressAuthorities.some(owner =>
254
+ owner.nodeId === projection.nodeId && owner.runtimeNamespace === projection.runtimeNamespace));
255
+ const authorities = [current, ...projection.allocationAuthorities];
256
+ requireNetwork(new Set(authorities.map(refKey)).size === authorities.length);
257
+ for (const authority of authorities) {
258
+ requireNetwork(networkEqual(authority.controller, projection.controller)
259
+ && authority.digest === await computeRuntimeNetworkProtectedAuthorityV1Digest(authority));
260
+ }
261
+ const allocationAuthority = (reference: IRuntimeAuthorityReferenceV1) => {
262
+ const result = authorities.find(authority => networkEqual(networkReferenceOf(authority), reference)); requireNetwork(result); return result;
263
+ };
264
+ if (projection.handoff !== null) {
265
+ await bindRuntimeNetworkHandoffLeaseV1(projection.handoff, allocationAuthority(projection.handoff.protectedAuthority));
266
+ requireNetwork(sameScope(projection.handoff, projection));
267
+ requireNetwork(current.pools.some(pool => pool.id === projection.handoff!.transit.poolId && pool.purpose === 'transit'
268
+ && networkContains(pool.prefix, projection.handoff!.transit.prefix)));
269
+ }
270
+ const networks = new Map(projection.networks.map(network => [network.id, network]));
271
+ const organizationKeys = new Map<string, string>(), keysToOrganizations = new Map<string, string>();
272
+ const names = new Set<string>();
273
+ for (const network of projection.networks) {
274
+ requireNetwork(network.state === 'active');
275
+ const key = `${network.organizationDnsKey}.${network.networkDnsKey}`;
276
+ requireNetwork(!names.has(key)); names.add(key);
277
+ requireNetwork(!organizationKeys.has(network.organizationId) || organizationKeys.get(network.organizationId) === network.organizationDnsKey);
278
+ requireNetwork(!keysToOrganizations.has(network.organizationDnsKey) || keysToOrganizations.get(network.organizationDnsKey) === network.organizationId);
279
+ organizationKeys.set(network.organizationId, network.organizationDnsKey); keysToOrganizations.set(network.organizationDnsKey, network.organizationId);
280
+ for (const upstream of network.policy.externalDns?.upstreams ?? []) requireNetwork(current.resolvers.some(resolver =>
281
+ resolver.address === upstream.address && resolver.port === upstream.port));
282
+ }
283
+ const members = new Map(projection.memberships.map(member => [ownerKey(member), member])), aliases = new Set<string>();
284
+ for (const member of projection.memberships) {
285
+ composeServicePrivateNetworkDnsPolicyV1(member, member.attachments.map(attachment => networks.get(attachment.networkId)));
286
+ for (const attachment of member.attachments) for (const alias of attachment.aliases) {
287
+ const name = buildPrivateNetworkFqdnV1(networks.get(attachment.networkId), alias);
288
+ requireNetwork(!aliases.has(name)); aliases.add(name);
289
+ }
290
+ }
291
+ const assignments = new Set<string>(), attempts = new Set<string>(), readyReplicas = new Set<string>();
292
+ for (const endpoint of projection.endpoints) {
293
+ const lease = endpoint.lease, authority = allocationAuthority(lease.protectedAuthority);
294
+ requireNetwork(networkEqual(lease.controller, projection.controller) && members.has(ownerKey(lease))
295
+ && !assignments.has(lease.assignmentId) && !attempts.has(attemptKey(lease)));
296
+ assignments.add(lease.assignmentId); attempts.add(attemptKey(lease));
297
+ if (endpoint.ready) {
298
+ const replica = networkCanonical([lease.organizationId, lease.serviceId, lease.replicaId]);
299
+ requireNetwork(!readyReplicas.has(replica)); readyReplicas.add(replica);
300
+ }
301
+ requireNetwork(lease.digest === await computeRuntimeNetworkWorkloadLeaseV1Digest(lease));
302
+ requireNetwork(authority.egressAuthorities.some(owner => owner.nodeId === lease.nodeId && owner.runtimeNamespace === lease.runtimeNamespace)
303
+ && current.egressAuthorities.some(owner => owner.nodeId === lease.nodeId && owner.runtimeNamespace === lease.runtimeNamespace));
304
+ for (const protection of [authority, current]) requireNetwork(protection.pools.some(pool =>
305
+ pool.id === lease.ipv4.poolId && pool.purpose === 'workload' && networkContains(pool.prefix, lease.ipv4.linkSubnet)));
306
+ if (sameScope(lease, projection)) requireNetwork(projection.handoff !== null && lease.routerIncarnationId === projection.handoff.routerIncarnationId);
307
+ for (const id of endpoint.platformEndpointIds) requireNetwork(current.platformEndpoints.some(platform => platform.id === id));
308
+ requireNetwork(!projection.retiredLeases.some(retired => networkEqual(retired, networkReferenceOf(lease))));
309
+ }
310
+ for (let index = 0; index < projection.endpoints.length; index++) for (let previous = 0; previous < index; previous++) {
311
+ requireNetwork(!networkOverlaps(projection.endpoints[index].lease.ipv4.linkSubnet, projection.endpoints[previous].lease.ipv4.linkSubnet));
312
+ }
313
+ if (projection.handoff) requireNetwork(!projection.retiredHandoffs.some(retired => networkEqual(retired, networkReferenceOf(projection.handoff!))));
314
+ const grants = new Set(grantsOf(projection).map(networkCanonical));
315
+ requireNetwork(projection.withdrawals.every(grant => !grants.has(networkCanonical(grant))));
316
+ requireNetwork(projection.digest === await computeRuntimeNetworkProjectionV1Digest(projection));
317
+ return projection;
318
+ } catch { return failNetwork(); }
319
+ };
320
+
321
+ /** Complete directed full-mesh and explicitly authorized egress; no DNS readiness dependency. */
322
+ export const getRuntimeNetworkProjectionPacketGrantsV1 = async (value: unknown): Promise<IRuntimeNetworkPacketGrantV1[]> =>
323
+ grantsOf(await validateRuntimeNetworkProjectionV1(value));
324
+
325
+ /** Complete offline DNS material, including authorized names never previously queried. */
326
+ export const composeRuntimeNetworkProjectionDnsViewsV1 = async (value: unknown): Promise<IRuntimeNetworkDnsViewV1[]> => {
327
+ const projection = await validateRuntimeNetworkProjectionV1(value);
328
+ const networks = new Map(projection.networks.map(network => [network.id, network]));
329
+ const members = new Map(projection.memberships.map(member => [ownerKey(member), member]));
330
+ return projection.endpoints.filter(endpoint => sameScope(endpoint.lease, projection)).map(endpoint => {
331
+ const member = members.get(ownerKey(endpoint.lease))!;
332
+ const policy = composeServicePrivateNetworkDnsPolicyV1(member, member.attachments.map(attachment => networks.get(attachment.networkId)));
333
+ const records: IRuntimeNetworkDnsViewV1['records'] = [];
334
+ for (const target of projection.memberships) {
335
+ if (target.organizationId !== member.organizationId) continue;
336
+ const addresses = projection.endpoints.filter(candidate => candidate.ready && ownerKey(candidate.lease) === ownerKey(target))
337
+ .map(candidate => candidate.lease.ipv4.address).sort();
338
+ for (const attachment of target.attachments) {
339
+ if (!member.attachments.some(own => own.networkId === attachment.networkId)) continue;
340
+ for (const alias of attachment.aliases) records.push({ name: buildPrivateNetworkFqdnV1(networks.get(attachment.networkId), alias), addresses: [...addresses] });
341
+ }
342
+ }
343
+ records.sort((left, right) => left.name < right.name ? -1 : 1);
344
+ return { source: networkReferenceOf(endpoint.lease), sourceAddress: endpoint.lease.ipv4.address, dnsServer: endpoint.lease.dnsServer, policy, records };
345
+ });
346
+ };
347
+
348
+ /** Bind immutable address material without a circular assignment-digest dependency. */
349
+ export const bindRuntimeNetworkWorkloadLeaseToAssignmentV1 = async (leaseValue: unknown, assignmentValue: unknown): Promise<IRuntimeNetworkWorkloadLeaseV1> => {
350
+ try {
351
+ const lease = snapshotRuntimeNetworkWorkloadLeaseV1(leaseValue), assignment = snapshotRuntimeAssignmentV1(assignmentValue);
352
+ requireNetwork((await validateRuntimeAssignmentV1(assignment)).length === 0 && sameScope(lease, assignment)
353
+ && lease.organizationId === assignment.organizationId && lease.assignmentId === assignment.assignmentId
354
+ && lease.serviceId === assignment.serviceId && lease.replicaId === assignment.replicaId && lease.attemptId === assignment.attemptId
355
+ && networkEqual(networkReferenceOf(lease), assignment.workload.network)
356
+ && lease.digest === await computeRuntimeNetworkWorkloadLeaseV1Digest(lease));
357
+ return lease;
358
+ } catch { return failNetwork(); }
359
+ };
360
+
361
+ /**
362
+ * Pure revision decision. appliedPrevious must be the receiver's exact durable,
363
+ * joined application receipt, never an incoming ACK field. All prior accepted
364
+ * material/apply journals survive until effects and DNS/allocation quarantine end.
365
+ */
366
+ export const admitRuntimeNetworkProjectionV1 = async (
367
+ value: unknown, previousValue: unknown | null, trustedScopeValue: unknown, appliedPreviousValue: unknown | null,
368
+ ): Promise<{ status: 'accepted' | 'replay'; projection: IRuntimeNetworkProjectionV1 }> => {
369
+ try {
370
+ // Snapshot ALL caller-owned inputs before the first asynchronous operation.
371
+ const incoming = snapshotRuntimeNetworkProjectionV1(value);
372
+ const previousInput = previousValue === null ? null : snapshotRuntimeNetworkProjectionV1(previousValue);
373
+ const trusted = snapshotRuntimeNetworkNodeScopeV1(trustedScopeValue);
374
+ const applied = appliedPreviousValue === null ? null : networkReference(captureNetwork(appliedPreviousValue));
375
+ const projection = await validateRuntimeNetworkProjectionV1(incoming);
376
+ requireNetwork(sameScope(projection, trusted));
377
+ if (previousInput === null) {
378
+ requireNetwork(projection.generation === 1 && applied === null && projection.withdrawals.length === 0
379
+ && projection.retiredLeases.length === 0 && projection.retiredHandoffs.length === 0);
380
+ return { status: 'accepted', projection };
381
+ }
382
+ const previous = await validateRuntimeNetworkProjectionV1(previousInput);
383
+ requireNetwork(sameScope(previous, trusted) && previous.id === projection.id);
384
+ requireNetwork(applied === null || networkEqual(applied, networkReferenceOf(previous)));
385
+ if (projection.generation === previous.generation) {
386
+ requireNetwork(networkEqual(previous, projection)); return { status: 'replay', projection };
387
+ }
388
+ requireNetwork(networkEqual(projection.previous, networkReferenceOf(previous)));
389
+ requireNetwork(projection.dns.issuedAt >= previous.dns.issuedAt);
390
+ for (const old of previous.networks) {
391
+ const current = projection.networks.find(network => network.id === old.id);
392
+ if (!current) continue;
393
+ requireNetwork(current.organizationId === old.organizationId && current.organizationDnsKey === old.organizationDnsKey
394
+ && current.networkDnsKey === old.networkDnsKey && current.createdAt === old.createdAt && current.revision >= old.revision);
395
+ if (current.revision === old.revision) requireNetwork(networkEqual(current, old));
396
+ }
397
+ for (const old of previous.memberships) {
398
+ const current = projection.memberships.find(member => ownerKey(member) === ownerKey(old));
399
+ if (!current) continue;
400
+ requireNetwork(current.revision >= old.revision);
401
+ if (current.revision === old.revision) requireNetwork(networkEqual(current, old));
402
+ }
403
+ const grants = new Set(grantsOf(projection).map(networkCanonical)), withdrawn = new Set(projection.withdrawals.map(networkCanonical));
404
+ const previousGrants = grantsOf(previous);
405
+ for (const grant of previousGrants) requireNetwork(grants.has(networkCanonical(grant)) || withdrawn.has(networkCanonical(grant)));
406
+ const knownWithdrawals = new Set([...previousGrants, ...previous.withdrawals].map(networkCanonical));
407
+ requireNetwork(projection.withdrawals.every(grant => knownWithdrawals.has(networkCanonical(grant))));
408
+ const knownLeases = [...previous.endpoints.map(endpoint => networkReferenceOf(endpoint.lease)), ...previous.retiredLeases];
409
+ const knownHandoffs = [...(previous.handoff ? [networkReferenceOf(previous.handoff)] : []), ...previous.retiredHandoffs];
410
+ requireNetwork(projection.retiredLeases.every(retired => knownLeases.some(known => networkEqual(known, retired)))
411
+ && projection.retiredHandoffs.every(retired => knownHandoffs.some(known => networkEqual(known, retired))));
412
+ const requireCarried = (old: IRuntimeAuthorityReferenceV1[], next: IRuntimeAuthorityReferenceV1[]) => {
413
+ for (const reference of old) requireNetwork(next.some(item => networkEqual(item, reference)));
414
+ };
415
+ if (applied === null) {
416
+ for (const grant of previous.withdrawals) requireNetwork(withdrawn.has(networkCanonical(grant)));
417
+ requireCarried(previous.retiredLeases, projection.retiredLeases); requireCarried(previous.retiredHandoffs, projection.retiredHandoffs);
418
+ }
419
+ for (const old of previous.endpoints) {
420
+ // A different allocation ID cannot rename the same immutable execution attempt.
421
+ for (const candidate of projection.endpoints) {
422
+ if (candidate.lease.assignmentId === old.lease.assignmentId || attemptKey(candidate.lease) === attemptKey(old.lease)) {
423
+ requireNetwork(networkEqual(candidate.lease, old.lease));
424
+ }
425
+ }
426
+ const current = projection.endpoints.find(item => item.lease.id === old.lease.id);
427
+ if (current) {
428
+ requireNetwork(networkEqual(current.lease, old.lease));
429
+ if (old.observation) {
430
+ requireNetwork(current.observation !== null && current.observation.sequence >= old.observation.sequence);
431
+ requireNetwork(current.observation.assignment.generation >= old.observation.assignment.generation);
432
+ if (current.observation.assignment.generation === old.observation.assignment.generation) {
433
+ requireNetwork(networkEqual(current.observation.assignment, old.observation.assignment));
434
+ }
435
+ if (current.observation.sequence === old.observation.sequence) requireNetwork(networkEqual(current.observation, old.observation)
436
+ && (!current.ready || old.ready));
437
+ }
438
+ }
439
+ else requireNetwork(projection.retiredLeases.some(item => networkEqual(item, networkReferenceOf(old.lease))));
440
+ }
441
+ if (previous.handoff && !networkEqual(previous.handoff, projection.handoff)) requireNetwork(projection.retiredHandoffs.some(item =>
442
+ networkEqual(item, networkReferenceOf(previous.handoff!))));
443
+ const protection = projection.protectedAuthority, oldProtection = previous.protectedAuthority;
444
+ requireNetwork(networkEqual(protection, oldProtection) || (protection.id === oldProtection.id
445
+ && networkEqual(protection.previous, networkReferenceOf(oldProtection))));
446
+ return { status: 'accepted', projection };
447
+ } catch { return failNetwork(); }
448
+ };
@@ -0,0 +1,175 @@
1
+ import type { TSha256Digest } from './immutableimage.js';
2
+ import type { IRuntimeAuthorityReferenceV1 } from './runtimeassignment.js';
3
+ import type { IRuntimeNetworkNodeScopeV1 } from './networkprojection.js';
4
+ import { snapshotRuntimeNetworkNodeScopeV1 } from './networkprojection.js';
5
+ import type { IRuntimeNetworkProtectedAuthorityV1 } from './networkauthority.js';
6
+ import { computeRuntimeNetworkProtectedAuthorityV1Digest, snapshotRuntimeNetworkProtectedAuthorityV1 } from './networkauthority.js';
7
+ import type { IRuntimeSessionBindingV1 } from './runtimesession.js';
8
+ import { snapshotRuntimeSessionBindingV1 } from './runtimesession.js';
9
+ import { captureNetwork, failNetwork, networkCanonical, networkDigest, networkEqual, networkHash,
10
+ networkId, networkList, networkRecord, networkReference, networkReferenceOf, networkRevision,
11
+ networkSafe, networkSorted, requireNetwork } from '../private/networkcontract.js';
12
+
13
+ /**
14
+ * Durable native protection report, independent of projection admission and DNS.
15
+ * The producer owns a joined native journal covering ALL affected local egress
16
+ * paths. nativeBarrier identifies that complete journal, never an admission ACK,
17
+ * a single table inspection, a boot event or a caller-selected success flag.
18
+ * A null nativeBarrier explicitly withdraws this node's allocation eligibility.
19
+ */
20
+ export interface IRuntimeNetworkProtectionReceiptV1 extends IRuntimeNetworkNodeScopeV1 {
21
+ schemaVersion: 1;
22
+ id: string;
23
+ generation: number;
24
+ previous: IRuntimeAuthorityReferenceV1 | null;
25
+ protectedAuthority: IRuntimeAuthorityReferenceV1;
26
+ reporterSessionId: string;
27
+ bootId: string;
28
+ nativeBarrier: IRuntimeAuthorityReferenceV1 | null;
29
+ digest: TSha256Digest;
30
+ }
31
+
32
+ export interface IReportRuntimeNetworkProtectionRequestV1 {
33
+ session: IRuntimeSessionBindingV1;
34
+ receipt: IRuntimeNetworkProtectionReceiptV1;
35
+ }
36
+ export interface IReportRuntimeNetworkProtectionResponseV1 {
37
+ status: 'accepted' | 'replay';
38
+ receipt: IRuntimeAuthorityReferenceV1;
39
+ authorityUse: 'current' | 'historical';
40
+ }
41
+
42
+ export const runtimeNetworkProtectionV1Contract = Object.freeze({
43
+ digestDomain: 'serve.zone/runtime-network-protection-receipt-v1',
44
+ maximumAuthorities: 256,
45
+ allocation: 'all-current-affected-egress-receipts-before-reserving-any-lease',
46
+ receiptSource: 'joined-complete-native-protection-journal',
47
+ unavailable: 'null-native-barrier-removes-allocation-eligibility',
48
+ historical: 'retain-for-outbox-replay-never-current-allocation-eligibility',
49
+ quarantine: 'no-release-authority',
50
+ } as const);
51
+
52
+ const scopeOf = (value: IRuntimeNetworkNodeScopeV1): IRuntimeNetworkNodeScopeV1 =>
53
+ ({ controller: value.controller, nodeId: value.nodeId, runtimeNamespace: value.runtimeNamespace });
54
+ const scopeKey = (value: { nodeId: string; runtimeNamespace: string }): string =>
55
+ networkCanonical([value.nodeId, value.runtimeNamespace]);
56
+
57
+ export const snapshotRuntimeNetworkProtectionReceiptV1 = (value: unknown): IRuntimeNetworkProtectionReceiptV1 => networkSafe(() => {
58
+ const item = networkRecord(captureNetwork(value), ['schemaVersion', 'id', 'generation', 'previous',
59
+ 'controller', 'nodeId', 'runtimeNamespace', 'protectedAuthority', 'reporterSessionId', 'bootId', 'nativeBarrier', 'digest']);
60
+ requireNetwork(item.schemaVersion === 1 && typeof item.bootId === 'string'
61
+ && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(item.bootId)
62
+ && item.bootId !== '00000000-0000-0000-0000-000000000000');
63
+ const scope = snapshotRuntimeNetworkNodeScopeV1({ controller: item.controller, nodeId: item.nodeId, runtimeNamespace: item.runtimeNamespace });
64
+ return { schemaVersion: 1, ...networkRevision(item), ...scope,
65
+ protectedAuthority: networkReference(item.protectedAuthority), reporterSessionId: networkId(item.reporterSessionId),
66
+ bootId: item.bootId, nativeBarrier: item.nativeBarrier === null ? null : networkReference(item.nativeBarrier),
67
+ digest: networkDigest(item.digest) };
68
+ });
69
+
70
+ export const computeRuntimeNetworkProtectionReceiptV1Digest = (value: IRuntimeNetworkProtectionReceiptV1): Promise<TSha256Digest> =>
71
+ networkHash(runtimeNetworkProtectionV1Contract.digestDomain, snapshotRuntimeNetworkProtectionReceiptV1(value));
72
+
73
+ /** Pure revision binding. The owner must authenticate the reporter and fence all DB writes. */
74
+ export const admitRuntimeNetworkProtectionReceiptV1 = async (
75
+ value: unknown, previousValue: unknown | null, trustedScopeValue: unknown, knownProtectionValue: unknown,
76
+ ): Promise<{ status: 'accepted' | 'replay'; receipt: IRuntimeNetworkProtectionReceiptV1 }> => {
77
+ try {
78
+ const receipt = snapshotRuntimeNetworkProtectionReceiptV1(value);
79
+ const previous = previousValue === null ? null : snapshotRuntimeNetworkProtectionReceiptV1(previousValue);
80
+ const scope = snapshotRuntimeNetworkNodeScopeV1(captureNetwork(trustedScopeValue));
81
+ const protection = snapshotRuntimeNetworkProtectedAuthorityV1(captureNetwork(knownProtectionValue));
82
+ requireNetwork(networkEqual(scopeOf(receipt), scope) && networkEqual(receipt.controller, protection.controller)
83
+ && networkEqual(receipt.protectedAuthority, networkReferenceOf(protection))
84
+ && protection.egressAuthorities.some(owner => scopeKey(owner) === scopeKey(receipt)));
85
+ requireNetwork(receipt.digest === await computeRuntimeNetworkProtectionReceiptV1Digest(receipt)
86
+ && protection.digest === await computeRuntimeNetworkProtectedAuthorityV1Digest(protection));
87
+ if (!previous) requireNetwork(receipt.generation === 1 && receipt.previous === null);
88
+ else {
89
+ requireNetwork(networkEqual(scopeOf(previous), scope)
90
+ && previous.digest === await computeRuntimeNetworkProtectionReceiptV1Digest(previous));
91
+ if (networkEqual(receipt, previous)) return { status: 'replay', receipt };
92
+ requireNetwork(receipt.id === previous.id && receipt.generation === previous.generation + 1
93
+ && networkEqual(receipt.previous, networkReferenceOf(previous))
94
+ && receipt.protectedAuthority.id === previous.protectedAuthority.id
95
+ && receipt.protectedAuthority.generation >= previous.protectedAuthority.generation);
96
+ if (receipt.protectedAuthority.generation === previous.protectedAuthority.generation) {
97
+ requireNetwork(networkEqual(receipt.protectedAuthority, previous.protectedAuthority));
98
+ }
99
+ if (receipt.nativeBarrier && previous.nativeBarrier) {
100
+ if (receipt.bootId !== previous.bootId || !networkEqual(receipt.protectedAuthority, previous.protectedAuthority)) {
101
+ requireNetwork(!networkEqual(receipt.nativeBarrier, previous.nativeBarrier));
102
+ }
103
+ if (receipt.nativeBarrier.id === previous.nativeBarrier.id) {
104
+ requireNetwork(receipt.nativeBarrier.generation >= previous.nativeBarrier.generation);
105
+ if (receipt.nativeBarrier.generation === previous.nativeBarrier.generation) {
106
+ requireNetwork(networkEqual(receipt.nativeBarrier, previous.nativeBarrier));
107
+ }
108
+ }
109
+ }
110
+ }
111
+ return { status: 'accepted', receipt };
112
+ } catch { return failNetwork(); }
113
+ };
114
+
115
+ export const snapshotReportRuntimeNetworkProtectionRequestV1 = (value: unknown): IReportRuntimeNetworkProtectionRequestV1 => networkSafe(() => {
116
+ const item = networkRecord(captureNetwork(value), ['session', 'receipt']);
117
+ return { session: snapshotRuntimeSessionBindingV1(item.session), receipt: snapshotRuntimeNetworkProtectionReceiptV1(item.receipt) };
118
+ });
119
+
120
+ /** Both trusted bindings come from the receiver's fenced physical-session/history owner. */
121
+ export const bindReportRuntimeNetworkProtectionRequestV1 = (
122
+ value: unknown, trustedCurrentSessionValue: unknown, trustedReporterSessionValue: unknown,
123
+ ): { request: IReportRuntimeNetworkProtectionRequestV1; authorityUse: 'current' | 'historical' } => networkSafe(() => {
124
+ const request = snapshotReportRuntimeNetworkProtectionRequestV1(value);
125
+ const current = snapshotRuntimeSessionBindingV1(captureNetwork(trustedCurrentSessionValue));
126
+ const reporter = snapshotRuntimeSessionBindingV1(captureNetwork(trustedReporterSessionValue));
127
+ requireNetwork(networkEqual(request.session, current) && networkEqual(scopeOf(request.receipt), scopeOf(current))
128
+ && networkEqual(scopeOf(reporter), scopeOf(current)) && reporter.reporterSessionId === request.receipt.reporterSessionId);
129
+ const authorityUse = reporter.reporterSessionId === current.reporterSessionId ? 'current' : 'historical';
130
+ requireNetwork(authorityUse === 'current' ? networkEqual(reporter, current)
131
+ : reporter.sessionEpoch < current.sessionEpoch && reporter.credentialGeneration <= current.credentialGeneration);
132
+ return { request, authorityUse };
133
+ });
134
+
135
+ export const snapshotReportRuntimeNetworkProtectionResponseV1 = (value: unknown): IReportRuntimeNetworkProtectionResponseV1 => networkSafe(() => {
136
+ const item = networkRecord(captureNetwork(value), ['status', 'receipt', 'authorityUse']);
137
+ requireNetwork((item.status === 'accepted' || item.status === 'replay')
138
+ && (item.authorityUse === 'current' || item.authorityUse === 'historical'));
139
+ return { status: item.status, receipt: networkReference(item.receipt), authorityUse: item.authorityUse };
140
+ });
141
+
142
+ export const bindReportRuntimeNetworkProtectionResponseV1 = (value: unknown, sentReceiptValue: unknown): IReportRuntimeNetworkProtectionResponseV1 => networkSafe(() => {
143
+ const response = snapshotReportRuntimeNetworkProtectionResponseV1(value);
144
+ requireNetwork(networkEqual(response.receipt, networkReference(captureNetwork(sentReceiptValue))));
145
+ return response;
146
+ });
147
+
148
+ /**
149
+ * Complete allocation prerequisite, not authentication or a native inspector.
150
+ * Inputs MUST be the current receiver-persisted receipts and CURRENT durable
151
+ * sessions, fenced together with protection and lease insertion. Never supply
152
+ * worker-authored lists or just online peers. Missing/offline/unavailable owners
153
+ * cannot be omitted. Independent fences need their own verified owning contract;
154
+ * this helper supplies no generic override, expiry or quorum escape hatch.
155
+ */
156
+ export const bindRuntimeNetworkAllocationProtectionV1 = async (
157
+ protectionValue: unknown, receiptsValue: unknown, currentSessionsValue: unknown,
158
+ ): Promise<{ protection: IRuntimeNetworkProtectedAuthorityV1; receipts: IRuntimeNetworkProtectionReceiptV1[] }> => {
159
+ try {
160
+ const protection = snapshotRuntimeNetworkProtectedAuthorityV1(captureNetwork(protectionValue));
161
+ const receipts = networkSorted(networkList(captureNetwork(receiptsValue), 256, snapshotRuntimeNetworkProtectionReceiptV1), scopeKey);
162
+ const sessions = networkSorted(networkList(captureNetwork(currentSessionsValue), 256, snapshotRuntimeSessionBindingV1), scopeKey);
163
+ requireNetwork(protection.digest === await computeRuntimeNetworkProtectedAuthorityV1Digest(protection)
164
+ && receipts.length === protection.egressAuthorities.length && sessions.length === receipts.length);
165
+ for (const [index, owner] of protection.egressAuthorities.entries()) {
166
+ const receipt = receipts[index], session = sessions[index];
167
+ requireNetwork(scopeKey(receipt) === scopeKey(owner) && scopeKey(session) === scopeKey(owner)
168
+ && networkEqual(receipt.controller, protection.controller) && networkEqual(session.controller, protection.controller)
169
+ && receipt.reporterSessionId === session.reporterSessionId && receipt.nativeBarrier !== null
170
+ && networkEqual(receipt.protectedAuthority, networkReferenceOf(protection))
171
+ && receipt.digest === await computeRuntimeNetworkProtectionReceiptV1Digest(receipt));
172
+ }
173
+ return { protection, receipts };
174
+ } catch { return failNetwork(); }
175
+ };