@serve.zone/interfaces 31.8.0 → 32.0.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.
Files changed (215) hide show
  1. package/.smartconfig.json +1 -0
  2. package/changelog.md +512 -0
  3. package/dist_ts/00_commitinfo_data.js +3 -3
  4. package/dist_ts/appstore/types.d.ts +4 -6
  5. package/dist_ts/appstore/types.js +5 -5
  6. package/dist_ts/data/backup.d.ts +3 -26
  7. package/dist_ts/data/cluster.d.ts +36 -11
  8. package/dist_ts/data/cluster.js +33 -22
  9. package/dist_ts/data/clusteringress.d.ts +8 -0
  10. package/dist_ts/data/clusteringress.js +13 -8
  11. package/dist_ts/data/clusternode.d.ts +121 -74
  12. package/dist_ts/data/clusternode.js +109 -132
  13. package/dist_ts/data/clusterruntime.d.ts +39 -0
  14. package/dist_ts/data/clusterruntime.js +11 -0
  15. package/dist_ts/data/coremail.d.ts +3 -7
  16. package/dist_ts/data/coremail.js +2 -2
  17. package/dist_ts/data/coremail.runtime.d.ts +0 -1
  18. package/dist_ts/data/coremail.runtime.js +5 -22
  19. package/dist_ts/data/deploymentadoption.d.ts +0 -2
  20. package/dist_ts/data/deploymentadoption.js +40 -6
  21. package/dist_ts/data/deploymentoperation.js +16 -3
  22. package/dist_ts/data/deploymentpreflight.d.ts +0 -2
  23. package/dist_ts/data/deploymentpreflight.js +1 -1
  24. package/dist_ts/data/immutableimage.d.ts +38 -21
  25. package/dist_ts/data/immutableimage.js +45 -5
  26. package/dist_ts/data/index.d.ts +5 -1
  27. package/dist_ts/data/index.js +5 -1
  28. package/dist_ts/data/isolatedrestore.d.ts +139 -21
  29. package/dist_ts/data/isolatedrestore.golden.d.ts +0 -1
  30. package/dist_ts/data/isolatedrestore.golden.js +6 -9
  31. package/dist_ts/data/isolatedrestore.js +176 -40
  32. package/dist_ts/data/mail.d.ts +1 -1
  33. package/dist_ts/data/networkaddressplan.d.ts +78 -0
  34. package/dist_ts/data/networkaddressplan.js +114 -0
  35. package/dist_ts/data/networkauthority.d.ts +20 -22
  36. package/dist_ts/data/networkauthority.js +29 -43
  37. package/dist_ts/data/networkcredential.d.ts +10 -10
  38. package/dist_ts/data/networkcredential.js +16 -16
  39. package/dist_ts/data/networkdelivery.d.ts +18 -18
  40. package/dist_ts/data/networkdelivery.js +16 -16
  41. package/dist_ts/data/networklease.d.ts +18 -7
  42. package/dist_ts/data/networklease.js +29 -7
  43. package/dist_ts/data/networknode.d.ts +37 -0
  44. package/dist_ts/data/networknode.js +6 -0
  45. package/dist_ts/data/networkprojection.d.ts +59 -60
  46. package/dist_ts/data/networkprojection.js +53 -57
  47. package/dist_ts/data/networkprotection.d.ts +27 -28
  48. package/dist_ts/data/networkprotection.js +36 -36
  49. package/dist_ts/data/networkrouter.d.ts +11 -11
  50. package/dist_ts/data/networkrouter.js +1 -1
  51. package/dist_ts/data/networksigning.d.ts +16 -18
  52. package/dist_ts/data/networksigning.js +20 -21
  53. package/dist_ts/data/nodecredential.d.ts +4 -6
  54. package/dist_ts/data/nodeenrollment.d.ts +35 -40
  55. package/dist_ts/data/nodeenrollment.js +57 -72
  56. package/dist_ts/data/privatenetwork.d.ts +21 -24
  57. package/dist_ts/data/privatenetwork.js +39 -54
  58. package/dist_ts/data/runtimeassignment.d.ts +50 -34
  59. package/dist_ts/data/runtimeassignment.js +79 -45
  60. package/dist_ts/data/runtimeconfig.d.ts +21 -22
  61. package/dist_ts/data/runtimeconfig.js +37 -100
  62. package/dist_ts/data/runtimesession.d.ts +100 -62
  63. package/dist_ts/data/runtimesession.js +98 -79
  64. package/dist_ts/data/runtimeterminalreceipt.d.ts +28 -29
  65. package/dist_ts/data/runtimeterminalreceipt.js +42 -42
  66. package/dist_ts/data/secret.d.ts +18 -25
  67. package/dist_ts/data/secret.js +12 -52
  68. package/dist_ts/data/servicecredential.d.ts +14 -16
  69. package/dist_ts/data/servicecredential.js +17 -28
  70. package/dist_ts/data/serviceruntime.d.ts +128 -0
  71. package/dist_ts/data/serviceruntime.js +92 -0
  72. package/dist_ts/data/sparknodereport.d.ts +27 -14
  73. package/dist_ts/data/sparknodereport.js +35 -28
  74. package/dist_ts/data/webpush.d.ts +0 -1
  75. package/dist_ts/index.d.ts +2 -1
  76. package/dist_ts/index.js +3 -2
  77. package/dist_ts/platform/objectstorageretention.d.ts +21 -24
  78. package/dist_ts/platform/objectstorageretention.js +6 -18
  79. package/dist_ts/platform/storage.d.ts +1 -3
  80. package/dist_ts/platform/storagemigration.d.ts +0 -7
  81. package/dist_ts/platform/storagemigration.golden.d.ts +0 -1
  82. package/dist_ts/platform/storagemigration.golden.js +8 -12
  83. package/dist_ts/platform/storagemigration.js +6 -51
  84. package/dist_ts/platform/types.d.ts +2 -2
  85. package/dist_ts/private/canonicaljson.d.ts +9 -1
  86. package/dist_ts/private/canonicaljson.js +14 -2
  87. package/dist_ts/private/dataproperties.d.ts +62 -0
  88. package/dist_ts/private/dataproperties.js +117 -0
  89. package/dist_ts/private/networkcontract.d.ts +14 -10
  90. package/dist_ts/private/networkcontract.js +15 -1
  91. package/dist_ts/private/producercontract.d.ts +11 -0
  92. package/dist_ts/private/producercontract.js +21 -0
  93. package/dist_ts/private/releaseversion.d.ts +37 -0
  94. package/dist_ts/private/releaseversion.js +48 -0
  95. package/dist_ts/private/runtimepolicy.d.ts +31 -0
  96. package/dist_ts/private/runtimepolicy.js +90 -0
  97. package/dist_ts/private/tokenlist.d.ts +9 -0
  98. package/dist_ts/private/tokenlist.js +23 -0
  99. package/dist_ts/protocol.d.ts +137 -0
  100. package/dist_ts/protocol.js +255 -0
  101. package/dist_ts/requests/admin.d.ts +8 -8
  102. package/dist_ts/requests/backup.d.ts +102 -112
  103. package/dist_ts/requests/cluster.d.ts +47 -10
  104. package/dist_ts/requests/cluster.js +1 -1
  105. package/dist_ts/requests/clusteringress.d.ts +9 -0
  106. package/dist_ts/requests/clusteringress.js +1 -1
  107. package/dist_ts/requests/config.d.ts +3 -3
  108. package/dist_ts/requests/corestore.d.ts +0 -3
  109. package/dist_ts/requests/corestore.js +5 -9
  110. package/dist_ts/requests/network.d.ts +87 -31
  111. package/dist_ts/requests/node.d.ts +15 -28
  112. package/dist_ts/requests/pallet.d.ts +13 -13
  113. package/dist_ts/requests/runtimesession.d.ts +53 -41
  114. package/dist_ts/requests/secret.d.ts +4 -5
  115. package/dist_ts/requests/secret.js +1 -5
  116. package/dist_ts/requests/service.d.ts +60 -0
  117. package/dist_ts/runtime.corestore.d.ts +56 -74
  118. package/dist_ts/runtime.corestore.databaseexportpackage.d.ts +30 -36
  119. package/dist_ts/runtime.corestore.databaseexportpackage.golden.d.ts +11 -12
  120. package/dist_ts/runtime.corestore.databaseexportpackage.golden.js +54 -71
  121. package/dist_ts/runtime.corestore.databaseexportpackage.js +9 -25
  122. package/dist_ts/runtime.corestore.js +35 -135
  123. package/dist_ts/runtime.corestore.relay.js +2 -7
  124. package/dist_ts/runtime.d.ts +38 -48
  125. package/dist_ts/runtime.js +20 -77
  126. package/dist_ts/runtime.networkprojection.d.ts +4 -4
  127. package/dist_ts/runtime.networkprojection.js +18 -18
  128. package/dist_ts/runtime.workloadinit.d.ts +23 -24
  129. package/dist_ts/runtime.workloadinit.js +6 -13
  130. package/package.json +2 -2
  131. package/readme.md +540 -269
  132. package/ts/00_commitinfo_data.ts +3 -3
  133. package/ts/appstore/types.ts +4 -6
  134. package/ts/data/backup.ts +3 -38
  135. package/ts/data/cluster.ts +51 -34
  136. package/ts/data/clusteringress.ts +12 -12
  137. package/ts/data/clusternode.ts +204 -232
  138. package/ts/data/clusterruntime.ts +45 -0
  139. package/ts/data/coremail.runtime.ts +4 -21
  140. package/ts/data/coremail.ts +3 -7
  141. package/ts/data/deploymentadoption.ts +46 -4
  142. package/ts/data/deploymentoperation.ts +16 -1
  143. package/ts/data/deploymentpreflight.ts +0 -2
  144. package/ts/data/immutableimage.ts +71 -24
  145. package/ts/data/index.ts +5 -1
  146. package/ts/data/isolatedrestore.golden.ts +5 -9
  147. package/ts/data/isolatedrestore.ts +339 -54
  148. package/ts/data/mail.ts +1 -1
  149. package/ts/data/networkaddressplan.ts +175 -0
  150. package/ts/data/networkauthority.ts +45 -61
  151. package/ts/data/networkcredential.ts +24 -24
  152. package/ts/data/networkdelivery.ts +27 -27
  153. package/ts/data/networklease.ts +40 -13
  154. package/ts/data/networknode.ts +37 -0
  155. package/ts/data/networkprojection.ts +119 -124
  156. package/ts/data/networkprotection.ts +54 -55
  157. package/ts/data/networkrouter.ts +14 -14
  158. package/ts/data/networksigning.ts +29 -32
  159. package/ts/data/nodecredential.ts +4 -6
  160. package/ts/data/nodeenrollment.ts +96 -114
  161. package/ts/data/privatenetwork.ts +58 -74
  162. package/ts/data/runtimeassignment.ts +143 -94
  163. package/ts/data/runtimeconfig.ts +62 -122
  164. package/ts/data/runtimesession.ts +185 -138
  165. package/ts/data/runtimeterminalreceipt.ts +72 -73
  166. package/ts/data/secret.ts +28 -76
  167. package/ts/data/servicecredential.ts +33 -43
  168. package/ts/data/serviceruntime.ts +208 -0
  169. package/ts/data/sparknodereport.ts +48 -36
  170. package/ts/data/webpush.ts +0 -1
  171. package/ts/index.ts +2 -0
  172. package/ts/platform/objectstorageretention.ts +36 -55
  173. package/ts/platform/storage.ts +1 -3
  174. package/ts/platform/storagemigration.golden.ts +7 -11
  175. package/ts/platform/storagemigration.ts +5 -55
  176. package/ts/platform/types.ts +2 -2
  177. package/ts/private/canonicaljson.ts +13 -1
  178. package/ts/private/dataproperties.ts +139 -0
  179. package/ts/private/networkcontract.ts +23 -9
  180. package/ts/private/producercontract.ts +19 -0
  181. package/ts/private/releaseversion.ts +70 -0
  182. package/ts/private/runtimepolicy.ts +105 -0
  183. package/ts/private/tokenlist.ts +30 -0
  184. package/ts/protocol.ts +364 -0
  185. package/ts/requests/admin.ts +11 -11
  186. package/ts/requests/backup.ts +112 -117
  187. package/ts/requests/cluster.ts +58 -13
  188. package/ts/requests/clusteringress.ts +9 -0
  189. package/ts/requests/config.ts +3 -3
  190. package/ts/requests/corestore.ts +4 -16
  191. package/ts/requests/network.ts +90 -41
  192. package/ts/requests/node.ts +21 -38
  193. package/ts/requests/pallet.ts +17 -17
  194. package/ts/requests/runtimesession.ts +63 -51
  195. package/ts/requests/secret.ts +5 -10
  196. package/ts/requests/service.ts +81 -0
  197. package/ts/runtime.corestore.databaseexportpackage.golden.ts +77 -95
  198. package/ts/runtime.corestore.databaseexportpackage.ts +51 -73
  199. package/ts/runtime.corestore.relay.ts +1 -10
  200. package/ts/runtime.corestore.ts +118 -268
  201. package/ts/runtime.networkprojection.ts +30 -30
  202. package/ts/runtime.ts +83 -158
  203. package/ts/runtime.workloadinit.ts +36 -48
  204. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +0 -902
  205. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +0 -35
  206. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +0 -315
  207. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +0 -3315
  208. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.d.ts +0 -291
  209. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.d.ts +0 -30
  210. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js +0 -408
  211. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.js +0 -1126
  212. package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +0 -421
  213. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.ts +0 -510
  214. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.ts +0 -2470
  215. package/ts/runtime.cloudlylegacydeploymentsettlement.ts +0 -6630
@@ -0,0 +1,175 @@
1
+ import type { TSha256Digest } from './immutableimage.js';
2
+ import type { IRuntimeNetworkProtectedAuthority } from './networkauthority.js';
3
+ import { computeRuntimeNetworkProtectedAuthorityDigest, snapshotRuntimeNetworkProtectedAuthority } from './networkauthority.js';
4
+ import type { IGetRuntimeManagedVpnCredentialResponse } from './networkcredential.js';
5
+ import { captureNetwork, failNetwork, networkContains, networkCounter, networkEqual, networkId, networkIpv4, networkOverlaps,
6
+ networkPrefixBounds, networkPrivatePrefix, networkRecord, networkSafe, requireNetwork } from '../private/networkcontract.js';
7
+
8
+ /**
9
+ * The address space an administrator gives the runtime network, and the one input the protected
10
+ * authority is composed from. Cloudly keeps a single plan; pools and prefixes only grow, and the
11
+ * managed VPN never changes once set.
12
+ */
13
+ export interface IRuntimeNetworkAddressPlan {
14
+ id: 'address-plan';
15
+ /** Compare-and-swap counter; every accepted change advances it by one. */
16
+ revision: number;
17
+ /** Every protected prefix: they cover the pools, resolvers, platform endpoints and the VPN. */
18
+ prefixes: string[];
19
+ pools: IRuntimeNetworkProtectedAuthority['pools'];
20
+ resolvers: IRuntimeNetworkProtectedAuthority['resolvers'];
21
+ /** Without the VPN relay, which the composed authority adds as a UDP platform endpoint. */
22
+ platformEndpoints: IRuntimeNetworkProtectedAuthority['platformEndpoints'];
23
+ vpn: {
24
+ /** The private prefix VPN control addresses are allocated from. */
25
+ controlPrefix: string;
26
+ /** The endpoint every node dials for the managed VPN. */
27
+ relay: IGetRuntimeManagedVpnCredentialResponse['relay'];
28
+ };
29
+ }
30
+
31
+ /** What an administrator writes; Cloudly supplies the id and the revision. */
32
+ export type TRuntimeNetworkAddressPlanWritableData = Omit<IRuntimeNetworkAddressPlan, 'id' | 'revision'>;
33
+
34
+ /** What a protection producer fixes around a plan: the authority's identity, revision chain and egress. */
35
+ export type TRuntimeNetworkProtectedAuthorityFrame = Pick<IRuntimeNetworkProtectedAuthority,
36
+ 'id' | 'generation' | 'controller' | 'previous' | 'egressAuthorities'>;
37
+
38
+ /** Refusals the pure change check decides from the two plans alone. */
39
+ export type TRuntimeNetworkAddressPlanChangeRefusal = 'plan-vpn-immutable' | 'plan-pool-removed' | 'plan-prefix-shrunk';
40
+
41
+ /**
42
+ * Every refusal of a plan write. Cloudly adds the two that need live references: a resolver or
43
+ * platform endpoint the change removes or changes while a router selection or a service still names it.
44
+ */
45
+ export type TRuntimeNetworkAddressPlanRefusal =
46
+ | TRuntimeNetworkAddressPlanChangeRefusal | 'plan-resolver-referenced' | 'plan-endpoint-referenced';
47
+
48
+ export type TRuntimeNetworkAddressPlanChange =
49
+ | { status: 'unchanged' }
50
+ /** The ids the change removes or changes, which Cloudly checks against live references before it writes. */
51
+ | { status: 'accepted'; removed: { resolverIds: string[]; platformEndpointIds: string[] } }
52
+ | { status: 'refused'; reason: TRuntimeNetworkAddressPlanChangeRefusal };
53
+
54
+ export const runtimeNetworkAddressPlanContract = Object.freeze({
55
+ id: 'address-plan',
56
+ /**
57
+ * SmartVPN needs its gateway and at least one member inside the control prefix. No minimum length
58
+ * is stated: the private-range rule already keeps the control prefix at /8 or longer.
59
+ */
60
+ maximumControlPrefixLength: 30,
61
+ relayProtocol: 'udp',
62
+ } as const);
63
+
64
+ /**
65
+ * The structural authority validator reads a frame's shape and nothing else, and a plan fixes none of
66
+ * the frame, so every valid frame decides a plan the same way. The digest is a well-formed
67
+ * placeholder: this candidate is never hashed or stored.
68
+ */
69
+ const validationFrame: TRuntimeNetworkProtectedAuthorityFrame = {
70
+ id: 'address-plan', generation: 1, controller: { kind: 'cloudly', id: 'address-plan', epoch: 'address-plan' },
71
+ previous: null, egressAuthorities: [{ nodeId: 'address-plan', runtimeNamespace: 'address-plan' }],
72
+ };
73
+ const unsealedDigest = `sha256:${'0'.repeat(64)}` as TSha256Digest;
74
+
75
+ type TAuthoritySets = Pick<IRuntimeNetworkProtectedAuthority, 'prefixes' | 'pools' | 'resolvers' | 'platformEndpoints'>;
76
+
77
+ /** Unvalidated sets and frame in, the protected authority validator's verdict out. */
78
+ const authorityOf = (
79
+ sets: Record<keyof TAuthoritySets, unknown>, frame: Record<keyof TRuntimeNetworkProtectedAuthorityFrame, unknown>,
80
+ ): IRuntimeNetworkProtectedAuthority => snapshotRuntimeNetworkProtectedAuthority({ id: frame.id,
81
+ generation: frame.generation, controller: frame.controller, previous: frame.previous, egressAuthorities: frame.egressAuthorities,
82
+ prefixes: sets.prefixes, pools: sets.pools, resolvers: sets.resolvers, platformEndpoints: sets.platformEndpoints, digest: unsealedDigest });
83
+
84
+ const setsWithRelay = (plan: IRuntimeNetworkAddressPlan): TAuthoritySets => ({
85
+ prefixes: plan.prefixes, pools: plan.pools, resolvers: plan.resolvers,
86
+ platformEndpoints: [...plan.platformEndpoints, { ...plan.vpn.relay, protocol: runtimeNetworkAddressPlanContract.relayProtocol }]
87
+ .sort((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0),
88
+ });
89
+
90
+ const vpnOf = (value: unknown): IRuntimeNetworkAddressPlan['vpn'] => {
91
+ const item = networkRecord(value, ['controlPrefix', 'relay']);
92
+ const relay = networkRecord(item.relay, ['id', 'address', 'port']);
93
+ const controlPrefix = networkPrivatePrefix(item.controlPrefix);
94
+ requireNetwork(Number(controlPrefix.split('/')[1]) <= runtimeNetworkAddressPlanContract.maximumControlPrefixLength);
95
+ return { controlPrefix, relay: { id: networkId(relay.id), address: networkIpv4(relay.address), port: networkCounter(relay.port, 65535) } };
96
+ };
97
+
98
+ /** The control prefix is protected, and no pool, resolver or platform endpoint, the relay included, sits inside it. */
99
+ const requireVpnProtected = (authority: IRuntimeNetworkProtectedAuthority, controlPrefix: string): void => {
100
+ requireNetwork(authority.prefixes.some(prefix => networkContains(prefix, controlPrefix))
101
+ && authority.pools.every(pool => !networkOverlaps(pool.prefix, controlPrefix))
102
+ && [...authority.resolvers, ...authority.platformEndpoints].every(endpoint => !networkContains(controlPrefix, `${endpoint.address}/32`)));
103
+ };
104
+
105
+ /**
106
+ * Structural snapshot for exact persistence and for a plan write. A plan passes only when both
107
+ * authorities it can describe pass the protected authority's own validator: its sets alone, and
108
+ * its sets with the relay added, so no plan can compose an authority that contract refuses.
109
+ */
110
+ export const snapshotRuntimeNetworkAddressPlan = (value: unknown): IRuntimeNetworkAddressPlan => networkSafe(() => {
111
+ const item = networkRecord(captureNetwork(value), ['id', 'revision', 'prefixes', 'pools', 'resolvers', 'platformEndpoints', 'vpn']);
112
+ requireNetwork(item.id === runtimeNetworkAddressPlanContract.id);
113
+ const own = authorityOf({ prefixes: item.prefixes, pools: item.pools, resolvers: item.resolvers,
114
+ platformEndpoints: item.platformEndpoints }, validationFrame);
115
+ const plan: IRuntimeNetworkAddressPlan = { id: runtimeNetworkAddressPlanContract.id, revision: networkCounter(item.revision),
116
+ prefixes: own.prefixes, pools: own.pools, resolvers: own.resolvers, platformEndpoints: own.platformEndpoints, vpn: vpnOf(item.vpn) };
117
+ requireVpnProtected(authorityOf(setsWithRelay(plan), validationFrame), plan.vpn.controlPrefix);
118
+ return plan;
119
+ });
120
+
121
+ /**
122
+ * The protected authority a plan describes inside a producer's frame, digest included: the plan's
123
+ * sets with the VPN relay as the UDP platform endpoint every node dials. Both inputs are read before
124
+ * the digest is computed.
125
+ */
126
+ export const composeRuntimeNetworkProtectedAuthority = async (
127
+ planValue: unknown, frameValue: unknown,
128
+ ): Promise<IRuntimeNetworkProtectedAuthority> => {
129
+ try {
130
+ const plan = snapshotRuntimeNetworkAddressPlan(planValue);
131
+ const frame = networkRecord(captureNetwork(frameValue), ['id', 'generation', 'controller', 'previous', 'egressAuthorities']);
132
+ const authority = authorityOf(setsWithRelay(plan), frame);
133
+ return { ...authority, digest: await computeRuntimeNetworkProtectedAuthorityDigest(authority) };
134
+ } catch { return failNetwork(); }
135
+ };
136
+
137
+ /** Whether the union of `prefixes`, which never overlap one another, covers every address of `prefix`. */
138
+ const coveredBy = (prefixes: string[], prefix: string): boolean => {
139
+ const [first, last] = networkPrefixBounds(prefix);
140
+ const covered = prefixes.reduce((sum, candidate) => {
141
+ const [low, high] = networkPrefixBounds(candidate);
142
+ return sum + Math.max(0, Math.min(last, high) - Math.max(first, low) + 1);
143
+ }, 0);
144
+ return covered === last - first + 1;
145
+ };
146
+
147
+ /**
148
+ * The entries of `previous` that `next` does not hold exactly as they were. An entry changed under its
149
+ * old id counts: whatever still names that id would now reach something else.
150
+ */
151
+ const removedOrChanged = <T>(previous: T[], next: T[]): T[] =>
152
+ previous.filter(item => !next.some(candidate => networkEqual(candidate, item)));
153
+
154
+ const idsOf = (entries: Array<{ id: string }>): string[] => entries.map(entry => entry.id);
155
+
156
+ /**
157
+ * The pure decision for replacing `previousValue`, the stored plan or null, with `nextValue` at the
158
+ * following revision. Leases and the managed VPN outlive a plan revision, so every pool stays exactly
159
+ * as it was, the protected address space only grows, and the VPN never changes. Resolvers and platform
160
+ * endpoints may go or change; `accepted` names every one that did. Equal content is `unchanged`:
161
+ * Cloudly writes nothing and the stored revision stands.
162
+ */
163
+ export const admitRuntimeNetworkAddressPlanChange = (previousValue: unknown | null, nextValue: unknown): TRuntimeNetworkAddressPlanChange =>
164
+ networkSafe(() => {
165
+ const previous = previousValue === null ? null : snapshotRuntimeNetworkAddressPlan(previousValue);
166
+ const next = snapshotRuntimeNetworkAddressPlan(nextValue);
167
+ requireNetwork(next.revision === (previous?.revision ?? 0) + 1);
168
+ if (previous === null) return { status: 'accepted', removed: { resolverIds: [], platformEndpointIds: [] } };
169
+ if (networkEqual({ ...previous, revision: next.revision }, next)) return { status: 'unchanged' };
170
+ if (!networkEqual(previous.vpn, next.vpn)) return { status: 'refused', reason: 'plan-vpn-immutable' };
171
+ if (removedOrChanged(previous.pools, next.pools).length > 0) return { status: 'refused', reason: 'plan-pool-removed' };
172
+ if (!previous.prefixes.every(prefix => coveredBy(next.prefixes, prefix))) return { status: 'refused', reason: 'plan-prefix-shrunk' };
173
+ return { status: 'accepted', removed: { resolverIds: idsOf(removedOrChanged(previous.resolvers, next.resolvers)),
174
+ platformEndpointIds: idsOf(removedOrChanged(previous.platformEndpoints, next.platformEndpoints)) } };
175
+ });
@@ -1,14 +1,14 @@
1
1
  import type { TSha256Digest } from './immutableimage.js';
2
- import type { IRuntimeAuthorityReferenceV1, IRuntimeControllerV1 } from './runtimeassignment.js';
2
+ import type { IRuntimeAuthorityReference, IRuntimeController } from './runtimeassignment.js';
3
3
  import { canonicalizeStrictJson, createCanonicalJsonSha256Hex } from '../private/canonicaljson.js';
4
+ import { networkPrefix, networkPrivatePrefix } from '../private/networkcontract.js';
4
5
 
5
6
  /** Controller declaration; a digest does not authenticate completeness or activate a pool. */
6
- export interface IRuntimeNetworkProtectedAuthorityV1 {
7
- schemaVersion: 1;
7
+ export interface IRuntimeNetworkProtectedAuthority {
8
8
  id: string;
9
9
  generation: number;
10
- controller: IRuntimeControllerV1;
11
- previous: IRuntimeAuthorityReferenceV1 | null;
10
+ controller: IRuntimeController;
11
+ previous: IRuntimeAuthorityReference | null;
12
12
  /** Complete canonical IPv4 union, including all pools and protected endpoints. */
13
13
  prefixes: string[];
14
14
  pools: Array<{ id: string; purpose: 'workload' | 'transit'; prefix: string }>;
@@ -20,33 +20,32 @@ export interface IRuntimeNetworkProtectedAuthorityV1 {
20
20
  digest: TSha256Digest;
21
21
  }
22
22
 
23
- export interface IRuntimeNetworkHandoffPortRangeV1 {
23
+ export interface IRuntimeNetworkHandoffPortRange {
24
24
  protocol: 'tcp' | 'udp';
25
25
  first: number;
26
26
  last: number;
27
27
  }
28
28
 
29
29
  /** Immutable allocation, retained unchanged while active or quarantined. No expiry implies reuse. */
30
- export interface IRuntimeNetworkHandoffLeaseV1 {
31
- schemaVersion: 1;
30
+ export interface IRuntimeNetworkHandoffLease {
32
31
  id: string;
33
32
  generation: number;
34
- controller: IRuntimeControllerV1;
33
+ controller: IRuntimeController;
35
34
  nodeId: string;
36
35
  runtimeNamespace: string;
37
- protectedAuthority: IRuntimeAuthorityReferenceV1;
36
+ protectedAuthority: IRuntimeAuthorityReference;
38
37
  /** Logical allocation incarnation, never a path, PID, inode, descriptor or native capability. */
39
38
  routerIncarnationId: string;
40
39
  transit: { poolId: string; prefix: string; routerAddress: string; hostAddress: string };
41
- sourcePortRanges: IRuntimeNetworkHandoffPortRangeV1[];
40
+ sourcePortRanges: IRuntimeNetworkHandoffPortRange[];
42
41
  conntrackZone: number;
43
42
  conntrackLabel: string;
44
43
  digest: TSha256Digest;
45
44
  }
46
45
 
47
- export const runtimeNetworkAuthorityV1Contract = Object.freeze({
48
- protectedDigestDomain: 'serve.zone/runtime-network-protected-authority-v1',
49
- handoffDigestDomain: 'serve.zone/runtime-network-handoff-lease-v1',
46
+ export const runtimeNetworkAuthorityContract = Object.freeze({
47
+ protectedDigestDomain: 'serve.zone/runtime-network-protected-authority',
48
+ handoffDigestDomain: 'serve.zone/runtime-network-handoff-lease',
50
49
  maximumPrefixes: 128,
51
50
  maximumPools: 64,
52
51
  maximumResolvers: 16,
@@ -100,12 +99,12 @@ const digest = (value: unknown): TSha256Digest => {
100
99
  requireValue(typeof value === 'string' && /^sha256:[a-f0-9]{64}$/.test(value));
101
100
  return value as TSha256Digest;
102
101
  };
103
- const controller = (value: unknown): IRuntimeControllerV1 => {
102
+ const controller = (value: unknown): IRuntimeController => {
104
103
  const item = record(value, ['kind', 'id', 'epoch']);
105
104
  requireValue(item.kind === 'cloudly' || item.kind === 'onebox');
106
105
  return { kind: item.kind, id: id(item.id), epoch: id(item.epoch) };
107
106
  };
108
- const reference = (value: unknown): IRuntimeAuthorityReferenceV1 => {
107
+ const reference = (value: unknown): IRuntimeAuthorityReference => {
109
108
  const item = record(value, ['id', 'generation', 'digest']);
110
109
  return { id: id(item.id), generation: integer(item.generation), digest: digest(item.digest) };
111
110
  };
@@ -129,14 +128,6 @@ const endpointAddress = (value: unknown): string => {
129
128
  requireValue(first > 0 && first < 224 && first !== 127);
130
129
  return result;
131
130
  };
132
- const prefix = (value: unknown): string => {
133
- requireValue(typeof value === 'string' && value.length <= 18);
134
- const parts = value.split('/');
135
- requireValue(parts.length === 2 && /^(?:[0-9]|[12][0-9]|3[0-2])$/.test(parts[1]));
136
- const base = numericAddress(address(parts[0])), width = 2 ** (32 - Number(parts[1]));
137
- requireValue(base % width === 0);
138
- return value;
139
- };
140
131
  const bounds = (value: string): [number, number] => {
141
132
  const [base, bits] = value.split('/'), first = numericAddress(base);
142
133
  return [first, first + 2 ** (32 - Number(bits)) - 1];
@@ -149,11 +140,6 @@ const overlaps = (left: string, right: string): boolean => {
149
140
  const [a, b] = bounds(left), [c, d] = bounds(right);
150
141
  return a <= d && c <= b;
151
142
  };
152
- const privatePrefix = (value: unknown): string => {
153
- const result = prefix(value);
154
- requireValue(['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'].some(range => contains(range, result)));
155
- return result;
156
- };
157
143
  const nonoverlapping = (values: string[]): void => {
158
144
  for (let index = 0; index < values.length; index++) for (let other = 0; other < index; other++) {
159
145
  requireValue(!overlaps(values[index], values[other]));
@@ -163,22 +149,21 @@ const canonical = (value: unknown): string => canonicalizeStrictJson(value, fail
163
149
  const equals = (left: unknown, right: unknown): boolean => canonical(left) === canonical(right);
164
150
 
165
151
  /** Structural snapshot only. Complete inventory, signatures and activation barriers are caller-owned. */
166
- export const snapshotRuntimeNetworkProtectedAuthorityV1 = (value: unknown): IRuntimeNetworkProtectedAuthorityV1 => safe(() => {
167
- const item = record(value, ['schemaVersion', 'id', 'generation', 'controller', 'previous', 'prefixes',
152
+ export const snapshotRuntimeNetworkProtectedAuthority = (value: unknown): IRuntimeNetworkProtectedAuthority => safe(() => {
153
+ const item = record(value, ['id', 'generation', 'controller', 'previous', 'prefixes',
168
154
  'pools', 'resolvers', 'platformEndpoints', 'egressAuthorities', 'digest']);
169
- requireValue(item.schemaVersion === 1);
170
155
  const identity = id(item.id), generation = integer(item.generation);
171
156
  const previous = item.previous === null ? null : reference(item.previous);
172
157
  requireValue(generation === 1 ? previous === null : previous?.id === identity && previous.generation === generation - 1);
173
- const prefixes = sorted(list(item.prefixes, runtimeNetworkAuthorityV1Contract.maximumPrefixes, prefix), value => value);
158
+ const prefixes = sorted(list(item.prefixes, runtimeNetworkAuthorityContract.maximumPrefixes, networkPrefix), value => value);
174
159
  requireValue(prefixes.length > 0);
175
160
  nonoverlapping(prefixes);
176
161
  const protectedPrefix = (value: string) => requireValue(prefixes.some(range => contains(range, value)));
177
- const pools = sorted(list(item.pools, runtimeNetworkAuthorityV1Contract.maximumPools, value => {
162
+ const pools = sorted(list(item.pools, runtimeNetworkAuthorityContract.maximumPools, value => {
178
163
  const pool = record(value, ['id', 'purpose', 'prefix']);
179
164
  requireValue(pool.purpose === 'workload' || pool.purpose === 'transit');
180
- const result: IRuntimeNetworkProtectedAuthorityV1['pools'][number] = {
181
- id: id(pool.id), purpose: pool.purpose, prefix: privatePrefix(pool.prefix),
165
+ const result: IRuntimeNetworkProtectedAuthority['pools'][number] = {
166
+ id: id(pool.id), purpose: pool.purpose, prefix: networkPrivatePrefix(pool.prefix),
182
167
  };
183
168
  protectedPrefix(result.prefix);
184
169
  return result;
@@ -191,35 +176,34 @@ export const snapshotRuntimeNetworkProtectedAuthorityV1 = (value: unknown): IRun
191
176
  requireValue(pools.every(pool => !contains(pool.prefix, `${result.address}/32`)));
192
177
  return withProtocol ? { ...result, protocol: protocol(endpoint.protocol) } : result;
193
178
  };
194
- const resolvers = sorted(list(item.resolvers, runtimeNetworkAuthorityV1Contract.maximumResolvers,
179
+ const resolvers = sorted(list(item.resolvers, runtimeNetworkAuthorityContract.maximumResolvers,
195
180
  value => readEndpoint(value, false)), value => value.id);
196
- const platformEndpoints = sorted(list(item.platformEndpoints, runtimeNetworkAuthorityV1Contract.maximumPlatformEndpoints,
197
- value => readEndpoint(value, true) as IRuntimeNetworkProtectedAuthorityV1['platformEndpoints'][number]), value => value.id);
181
+ const platformEndpoints = sorted(list(item.platformEndpoints, runtimeNetworkAuthorityContract.maximumPlatformEndpoints,
182
+ value => readEndpoint(value, true) as IRuntimeNetworkProtectedAuthority['platformEndpoints'][number]), value => value.id);
198
183
  const allEndpointKeys = [...resolvers.flatMap(value => ['tcp', 'udp'].map(transport => `${value.address}:${value.port}:${transport}`)),
199
184
  ...platformEndpoints.map(value => `${value.address}:${value.port}:${value.protocol}`)];
200
185
  requireValue(new Set(allEndpointKeys).size === allEndpointKeys.length);
201
- const egressAuthorities = sorted(list(item.egressAuthorities, runtimeNetworkAuthorityV1Contract.maximumEgressAuthorities, value => {
186
+ const egressAuthorities = sorted(list(item.egressAuthorities, runtimeNetworkAuthorityContract.maximumEgressAuthorities, value => {
202
187
  const authority = record(value, ['nodeId', 'runtimeNamespace']);
203
188
  return { nodeId: id(authority.nodeId), runtimeNamespace: id(authority.runtimeNamespace) };
204
189
  }), value => canonical([value.nodeId, value.runtimeNamespace]));
205
190
  requireValue(egressAuthorities.length > 0);
206
- return { schemaVersion: 1, id: identity, generation, controller: controller(item.controller), previous,
191
+ return { id: identity, generation, controller: controller(item.controller), previous,
207
192
  prefixes, pools, resolvers, platformEndpoints, egressAuthorities, digest: digest(item.digest) };
208
193
  });
209
194
 
210
- export const snapshotRuntimeNetworkHandoffLeaseV1 = (value: unknown): IRuntimeNetworkHandoffLeaseV1 => safe(() => {
211
- const item = record(value, ['schemaVersion', 'id', 'generation', 'controller', 'nodeId', 'runtimeNamespace',
195
+ export const snapshotRuntimeNetworkHandoffLease = (value: unknown): IRuntimeNetworkHandoffLease => safe(() => {
196
+ const item = record(value, ['id', 'generation', 'controller', 'nodeId', 'runtimeNamespace',
212
197
  'protectedAuthority', 'routerIncarnationId', 'transit', 'sourcePortRanges', 'conntrackZone', 'conntrackLabel', 'digest']);
213
- requireValue(item.schemaVersion === 1);
214
198
  const transit = record(item.transit, ['poolId', 'prefix', 'routerAddress', 'hostAddress']);
215
- const transitPrefix = privatePrefix(transit.prefix), [first, last] = bounds(transitPrefix);
199
+ const transitPrefix = networkPrivatePrefix(transit.prefix), [first, last] = bounds(transitPrefix);
216
200
  const routerAddress = endpointAddress(transit.routerAddress), hostAddress = endpointAddress(transit.hostAddress);
217
201
  requireValue(first !== last && routerAddress !== hostAddress);
218
202
  for (const value of [routerAddress, hostAddress]) {
219
203
  const number = numericAddress(value);
220
204
  requireValue(number >= first && number <= last && (last - first === 1 || (number !== first && number !== last)));
221
205
  }
222
- const sourcePortRanges = list(item.sourcePortRanges, runtimeNetworkAuthorityV1Contract.maximumPortRanges, value => {
206
+ const sourcePortRanges = list(item.sourcePortRanges, runtimeNetworkAuthorityContract.maximumPortRanges, value => {
223
207
  const range = record(value, ['protocol', 'first', 'last']);
224
208
  const result = { protocol: protocol(range.protocol), first: integer(range.first, 65535), last: integer(range.last, 65535) };
225
209
  requireValue(result.first <= result.last);
@@ -232,7 +216,7 @@ export const snapshotRuntimeNetworkHandoffLeaseV1 = (value: unknown): IRuntimeNe
232
216
  }
233
217
  requireValue(typeof item.conntrackLabel === 'string' && /^[a-f0-9]{32}$/.test(item.conntrackLabel)
234
218
  && item.conntrackLabel !== '0'.repeat(32));
235
- return { schemaVersion: 1, id: id(item.id), generation: integer(item.generation), controller: controller(item.controller),
219
+ return { id: id(item.id), generation: integer(item.generation), controller: controller(item.controller),
236
220
  nodeId: id(item.nodeId), runtimeNamespace: id(item.runtimeNamespace), protectedAuthority: reference(item.protectedAuthority),
237
221
  routerIncarnationId: id(item.routerIncarnationId), transit: { poolId: id(transit.poolId), prefix: transitPrefix, routerAddress, hostAddress },
238
222
  sourcePortRanges, conntrackZone: integer(item.conntrackZone, 65535), conntrackLabel: item.conntrackLabel, digest: digest(item.digest) };
@@ -242,19 +226,19 @@ const computeDigest = async (domain: string, value: { digest: TSha256Digest }):
242
226
  const { digest: omitted, ...payload } = value;
243
227
  return `sha256:${await createCanonicalJsonSha256Hex(canonical({ domain, payload }), fail)}`;
244
228
  };
245
- export const computeRuntimeNetworkProtectedAuthorityV1Digest = (value: IRuntimeNetworkProtectedAuthorityV1): Promise<TSha256Digest> =>
246
- computeDigest(runtimeNetworkAuthorityV1Contract.protectedDigestDomain, snapshotRuntimeNetworkProtectedAuthorityV1(value));
247
- export const computeRuntimeNetworkHandoffLeaseV1Digest = (value: IRuntimeNetworkHandoffLeaseV1): Promise<TSha256Digest> =>
248
- computeDigest(runtimeNetworkAuthorityV1Contract.handoffDigestDomain, snapshotRuntimeNetworkHandoffLeaseV1(value));
229
+ export const computeRuntimeNetworkProtectedAuthorityDigest = (value: IRuntimeNetworkProtectedAuthority): Promise<TSha256Digest> =>
230
+ computeDigest(runtimeNetworkAuthorityContract.protectedDigestDomain, snapshotRuntimeNetworkProtectedAuthority(value));
231
+ export const computeRuntimeNetworkHandoffLeaseDigest = (value: IRuntimeNetworkHandoffLease): Promise<TSha256Digest> =>
232
+ computeDigest(runtimeNetworkAuthorityContract.handoffDigestDomain, snapshotRuntimeNetworkHandoffLease(value));
249
233
 
250
234
  /** Detached, digest-verified allocation binding. Does not establish pool activation or live link identity. */
251
- export const bindRuntimeNetworkHandoffLeaseV1 = async (leaseValue: unknown, authorityValue: unknown): Promise<{
252
- lease: IRuntimeNetworkHandoffLeaseV1; authority: IRuntimeNetworkProtectedAuthorityV1;
235
+ export const bindRuntimeNetworkHandoffLease = async (leaseValue: unknown, authorityValue: unknown): Promise<{
236
+ lease: IRuntimeNetworkHandoffLease; authority: IRuntimeNetworkProtectedAuthority;
253
237
  }> => {
254
- const lease = snapshotRuntimeNetworkHandoffLeaseV1(leaseValue);
255
- const authority = snapshotRuntimeNetworkProtectedAuthorityV1(authorityValue);
256
- requireValue(lease.digest === await computeRuntimeNetworkHandoffLeaseV1Digest(lease));
257
- requireValue(authority.digest === await computeRuntimeNetworkProtectedAuthorityV1Digest(authority));
238
+ const lease = snapshotRuntimeNetworkHandoffLease(leaseValue);
239
+ const authority = snapshotRuntimeNetworkProtectedAuthority(authorityValue);
240
+ requireValue(lease.digest === await computeRuntimeNetworkHandoffLeaseDigest(lease));
241
+ requireValue(authority.digest === await computeRuntimeNetworkProtectedAuthorityDigest(authority));
258
242
  requireValue(equals(lease.controller, authority.controller)
259
243
  && equals(lease.protectedAuthority, { id: authority.id, generation: authority.generation, digest: authority.digest })
260
244
  && authority.egressAuthorities.some(value => value.nodeId === lease.nodeId && value.runtimeNamespace === lease.runtimeNamespace));
@@ -268,12 +252,12 @@ export const bindRuntimeNetworkHandoffLeaseV1 = async (leaseValue: unknown, auth
268
252
  * The owning transactional ledger must supply its complete history and serialize reservations.
269
253
  * Namespace replacement, an empty CT dump or process exit never removes an entry from this set.
270
254
  */
271
- export const snapshotRuntimeNetworkHandoffLedgerV1 = async (value: unknown): Promise<IRuntimeNetworkHandoffLeaseV1[]> => {
272
- const leases = safe(() => list(value, runtimeNetworkAuthorityV1Contract.maximumRetainedHandoffLeases,
273
- snapshotRuntimeNetworkHandoffLeaseV1));
255
+ export const snapshotRuntimeNetworkHandoffLedger = async (value: unknown): Promise<IRuntimeNetworkHandoffLease[]> => {
256
+ const leases = safe(() => list(value, runtimeNetworkAuthorityContract.maximumRetainedHandoffLeases,
257
+ snapshotRuntimeNetworkHandoffLease));
274
258
  for (let index = 0; index < leases.length; index++) {
275
259
  const lease = leases[index];
276
- requireValue(lease.digest === await computeRuntimeNetworkHandoffLeaseV1Digest(lease));
260
+ requireValue(lease.digest === await computeRuntimeNetworkHandoffLeaseDigest(lease));
277
261
  for (let other = 0; other < index; other++) {
278
262
  const previous = leases[other];
279
263
  requireValue(lease.nodeId === previous.nodeId && equals(lease.controller, previous.controller));
@@ -1,19 +1,19 @@
1
- import type { IRuntimeAuthorityReferenceV1 } from './runtimeassignment.js';
2
- import { snapshotRuntimeSessionBindingV1, type IRuntimeSessionBindingV1 } from './runtimesession.js';
3
- import { validateRuntimeNetworkProjectionV1, type IRuntimeNetworkProjectionV1 } from './networkprojection.js';
1
+ import type { IRuntimeAuthorityReference } from './runtimeassignment.js';
2
+ import { snapshotRuntimeSessionBinding, type IRuntimeSessionBinding } from './runtimesession.js';
3
+ import { validateRuntimeNetworkProjection, type IRuntimeNetworkProjection } from './networkprojection.js';
4
4
  import { snapshotRuntimeNetworkDnsLeaseRenewal, validateRuntimeNetworkDnsLeaseRenewal } from './networklease.js';
5
5
  import { captureNetwork, failNetwork, networkCounter, networkEffectiveDnsWindow, networkEqual, networkId, networkIpv4,
6
6
  networkRecord, networkReference, networkReferenceOf, networkSafe, networkSameScope, requireNetwork } from '../private/networkcontract.js';
7
7
 
8
- export interface IGetRuntimeManagedVpnCredentialRequestV1 {
9
- session: IRuntimeSessionBindingV1;
10
- projection: IRuntimeAuthorityReferenceV1;
8
+ export interface IGetRuntimeManagedVpnCredentialRequest {
9
+ session: IRuntimeSessionBinding;
10
+ projection: IRuntimeAuthorityReference;
11
11
  }
12
12
 
13
13
  /** Secret response over the current authenticated physical peer only. Never
14
14
  * persist, hash, log, or include it in a signed network projection. The native
15
15
  * Noise owner validates and uses the keys; these shapes confer no TUN readiness. */
16
- export interface IGetRuntimeManagedVpnCredentialResponseV1 extends IGetRuntimeManagedVpnCredentialRequestV1 {
16
+ export interface IGetRuntimeManagedVpnCredentialResponse extends IGetRuntimeManagedVpnCredentialRequest {
17
17
  transport: 'quic';
18
18
  relay: { id: string; address: string; port: number };
19
19
  authorityId: string;
@@ -36,35 +36,35 @@ const key = (value: unknown): string => {
36
36
  return value;
37
37
  };
38
38
 
39
- export const snapshotGetRuntimeManagedVpnCredentialRequestV1 = (value: unknown): IGetRuntimeManagedVpnCredentialRequestV1 => networkSafe(() => {
39
+ export const snapshotGetRuntimeManagedVpnCredentialRequest = (value: unknown): IGetRuntimeManagedVpnCredentialRequest => networkSafe(() => {
40
40
  const item = networkRecord(captureNetwork(value), ['session', 'projection']);
41
- return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection) };
41
+ return { session: snapshotRuntimeSessionBinding(item.session), projection: networkReference(item.projection) };
42
42
  });
43
43
 
44
- export const snapshotGetRuntimeManagedVpnCredentialResponseV1 = (value: unknown): IGetRuntimeManagedVpnCredentialResponseV1 => networkSafe(() => {
44
+ export const snapshotGetRuntimeManagedVpnCredentialResponse = (value: unknown): IGetRuntimeManagedVpnCredentialResponse => networkSafe(() => {
45
45
  const item = networkRecord(captureNetwork(value), ['session', 'projection', 'transport', 'relay', 'authorityId',
46
46
  'serverPublicKey', 'clientPublicKey', 'clientPrivateKey', 'expiresAt']);
47
47
  const relay = networkRecord(item.relay, ['id', 'address', 'port']); requireNetwork(item.transport === 'quic');
48
- return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection), transport: 'quic',
48
+ return { session: snapshotRuntimeSessionBinding(item.session), projection: networkReference(item.projection), transport: 'quic',
49
49
  relay: { id: networkId(relay.id), address: networkIpv4(relay.address), port: networkCounter(relay.port, 65535) },
50
50
  authorityId: networkId(item.authorityId), serverPublicKey: key(item.serverPublicKey), clientPublicKey: key(item.clientPublicKey),
51
51
  clientPrivateKey: key(item.clientPrivateKey), expiresAt: networkCounter(item.expiresAt) };
52
52
  });
53
53
 
54
- const bindRequest = (request: IGetRuntimeManagedVpnCredentialRequestV1,
55
- projection: IRuntimeNetworkProjectionV1, trusted: IRuntimeSessionBindingV1): void => {
54
+ const bindRequest = (request: IGetRuntimeManagedVpnCredentialRequest,
55
+ projection: IRuntimeNetworkProjection, trusted: IRuntimeSessionBinding): void => {
56
56
  requireNetwork(networkEqual(request.session, trusted) && networkEqual(request.projection, networkReferenceOf(projection))
57
57
  && networkSameScope(projection, trusted) && projection.handoff);
58
58
  };
59
59
 
60
60
  /** Content binding only. The caller must resolve the exact current projection
61
61
  * and authenticate/fence the current physical peer before and after native work. */
62
- export const bindGetRuntimeManagedVpnCredentialRequestV1 = async (value: unknown, projectionValue: unknown,
63
- trustedSessionValue: unknown): Promise<IGetRuntimeManagedVpnCredentialRequestV1> => {
62
+ export const bindGetRuntimeManagedVpnCredentialRequest = async (value: unknown, projectionValue: unknown,
63
+ trustedSessionValue: unknown): Promise<IGetRuntimeManagedVpnCredentialRequest> => {
64
64
  try {
65
- const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(value);
66
- const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue);
67
- const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
65
+ const request = snapshotGetRuntimeManagedVpnCredentialRequest(value);
66
+ const trusted = snapshotRuntimeSessionBinding(trustedSessionValue);
67
+ const projection = await validateRuntimeNetworkProjection(projectionValue);
68
68
  bindRequest(request, projection, trusted);
69
69
  return request;
70
70
  } catch { return failNetwork(); }
@@ -76,15 +76,15 @@ export const bindGetRuntimeManagedVpnCredentialRequestV1 = async (value: unknown
76
76
  * projection, or null; this helper verifies no signature. Time is caller-qualified;
77
77
  * this helper does not sample a clock, authenticate a transport, admit policy or
78
78
  * prove a running managed connection. */
79
- export const bindGetRuntimeManagedVpnCredentialResponseV1 = async (value: unknown, requestValue: unknown,
79
+ export const bindGetRuntimeManagedVpnCredentialResponse = async (value: unknown, requestValue: unknown,
80
80
  projectionValue: unknown, trustedSessionValue: unknown, nowValue: unknown,
81
- renewalValue: unknown | null = null): Promise<IGetRuntimeManagedVpnCredentialResponseV1> => {
81
+ renewalValue: unknown | null = null): Promise<IGetRuntimeManagedVpnCredentialResponse> => {
82
82
  try {
83
- const response = snapshotGetRuntimeManagedVpnCredentialResponseV1(value);
84
- const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(requestValue);
85
- const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue), now = networkCounter(nowValue);
83
+ const response = snapshotGetRuntimeManagedVpnCredentialResponse(value);
84
+ const request = snapshotGetRuntimeManagedVpnCredentialRequest(requestValue);
85
+ const trusted = snapshotRuntimeSessionBinding(trustedSessionValue), now = networkCounter(nowValue);
86
86
  const renewalInput = renewalValue === null ? null : snapshotRuntimeNetworkDnsLeaseRenewal(renewalValue);
87
- const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
87
+ const projection = await validateRuntimeNetworkProjection(projectionValue);
88
88
  const renewal = renewalInput === null ? null : await validateRuntimeNetworkDnsLeaseRenewal(renewalInput);
89
89
  const window = networkEffectiveDnsWindow(projection, renewal);
90
90
  bindRequest(request, projection, trusted);
@@ -1,29 +1,29 @@
1
- import type { IRuntimeAuthorityReferenceV1 } from './runtimeassignment.js';
2
- import type { IRuntimeSessionBindingV1 } from './runtimesession.js';
3
- import { snapshotRuntimeSessionBindingV1 } from './runtimesession.js';
4
- import type { IRuntimeNetworkSigningAuthorityV1, ISignedRuntimeNetworkProjectionV1 } from './networksigning.js';
5
- import { snapshotRuntimeNetworkSigningAuthorityV1, snapshotSignedRuntimeNetworkProjectionV1 } from './networksigning.js';
1
+ import type { IRuntimeAuthorityReference } from './runtimeassignment.js';
2
+ import type { IRuntimeSessionBinding } from './runtimesession.js';
3
+ import { snapshotRuntimeSessionBinding } from './runtimesession.js';
4
+ import type { IRuntimeNetworkSigningAuthority, ISignedRuntimeNetworkProjection } from './networksigning.js';
5
+ import { snapshotRuntimeNetworkSigningAuthority, snapshotSignedRuntimeNetworkProjection } from './networksigning.js';
6
6
  import type { IRuntimeNetworkDnsLeaseRenewalReference, ISignedRuntimeNetworkDnsLeaseRenewal } from './networklease.js';
7
7
  import { getRuntimeNetworkDnsLeaseRenewalReference, snapshotRuntimeNetworkDnsLeaseRenewal,
8
8
  snapshotRuntimeNetworkDnsLeaseRenewalReference, snapshotSignedRuntimeNetworkDnsLeaseRenewal } from './networklease.js';
9
9
  import { captureNetwork, networkEqual, networkRecord, networkReference, networkReferenceOf, networkSafe, networkSameScope,
10
10
  requireNetwork } from '../private/networkcontract.js';
11
11
 
12
- export interface IApplyRuntimeNetworkSigningAuthorityRequestV1 {
13
- session: IRuntimeSessionBindingV1;
14
- authority: IRuntimeNetworkSigningAuthorityV1;
12
+ export interface IApplyRuntimeNetworkSigningAuthorityRequest {
13
+ session: IRuntimeSessionBinding;
14
+ authority: IRuntimeNetworkSigningAuthority;
15
15
  }
16
- export interface IApplyRuntimeNetworkProjectionRequestV1 {
17
- session: IRuntimeSessionBindingV1;
18
- signed: ISignedRuntimeNetworkProjectionV1;
16
+ export interface IApplyRuntimeNetworkProjectionRequest {
17
+ session: IRuntimeSessionBinding;
18
+ signed: ISignedRuntimeNetworkProjection;
19
19
  }
20
20
  /** Durable admission only. No packet, DNS, pool-activation, fencing or readiness assertion. */
21
- export interface IApplyRuntimeNetworkAuthorityResponseV1 {
21
+ export interface IApplyRuntimeNetworkAuthorityResponse {
22
22
  status: 'accepted' | 'replay';
23
- authority: IRuntimeAuthorityReferenceV1;
23
+ authority: IRuntimeAuthorityReference;
24
24
  }
25
25
  export interface IApplyRuntimeNetworkDnsLeaseRenewalRequest {
26
- session: IRuntimeSessionBindingV1;
26
+ session: IRuntimeSessionBinding;
27
27
  signed: ISignedRuntimeNetworkDnsLeaseRenewal;
28
28
  }
29
29
  /** Durable admission only. It does not assert that the node converted the window or serves DNS. */
@@ -36,22 +36,22 @@ const admissionStatus = (value: unknown): 'accepted' | 'replay' => {
36
36
  requireNetwork(value === 'accepted' || value === 'replay'); return value;
37
37
  };
38
38
 
39
- export const snapshotApplyRuntimeNetworkSigningAuthorityRequestV1 = (value: unknown): IApplyRuntimeNetworkSigningAuthorityRequestV1 => networkSafe(() => {
39
+ export const snapshotApplyRuntimeNetworkSigningAuthorityRequest = (value: unknown): IApplyRuntimeNetworkSigningAuthorityRequest => networkSafe(() => {
40
40
  const item = networkRecord(captureNetwork(value), ['session', 'authority']);
41
- return { session: snapshotRuntimeSessionBindingV1(item.session), authority: snapshotRuntimeNetworkSigningAuthorityV1(item.authority) };
41
+ return { session: snapshotRuntimeSessionBinding(item.session), authority: snapshotRuntimeNetworkSigningAuthority(item.authority) };
42
42
  });
43
- export const snapshotApplyRuntimeNetworkProjectionRequestV1 = (value: unknown): IApplyRuntimeNetworkProjectionRequestV1 => networkSafe(() => {
43
+ export const snapshotApplyRuntimeNetworkProjectionRequest = (value: unknown): IApplyRuntimeNetworkProjectionRequest => networkSafe(() => {
44
44
  const item = networkRecord(captureNetwork(value), ['session', 'signed']);
45
- return { session: snapshotRuntimeSessionBindingV1(item.session), signed: snapshotSignedRuntimeNetworkProjectionV1(item.signed) };
45
+ return { session: snapshotRuntimeSessionBinding(item.session), signed: snapshotSignedRuntimeNetworkProjection(item.signed) };
46
46
  });
47
- export const snapshotApplyRuntimeNetworkAuthorityResponseV1 = (value: unknown): IApplyRuntimeNetworkAuthorityResponseV1 => networkSafe(() => {
47
+ export const snapshotApplyRuntimeNetworkAuthorityResponse = (value: unknown): IApplyRuntimeNetworkAuthorityResponse => networkSafe(() => {
48
48
  const item = networkRecord(captureNetwork(value), ['status', 'authority']);
49
49
  return { status: admissionStatus(item.status), authority: networkReference(item.authority) };
50
50
  });
51
51
 
52
52
  export const snapshotApplyRuntimeNetworkDnsLeaseRenewalRequest = (value: unknown): IApplyRuntimeNetworkDnsLeaseRenewalRequest => networkSafe(() => {
53
53
  const item = networkRecord(captureNetwork(value), ['session', 'signed']);
54
- return { session: snapshotRuntimeSessionBindingV1(item.session), signed: snapshotSignedRuntimeNetworkDnsLeaseRenewal(item.signed) };
54
+ return { session: snapshotRuntimeSessionBinding(item.session), signed: snapshotSignedRuntimeNetworkDnsLeaseRenewal(item.signed) };
55
55
  });
56
56
  export const snapshotApplyRuntimeNetworkDnsLeaseRenewalResponse = (value: unknown): IApplyRuntimeNetworkDnsLeaseRenewalResponse => networkSafe(() => {
57
57
  const item = networkRecord(captureNetwork(value), ['status', 'renewal']);
@@ -59,22 +59,22 @@ export const snapshotApplyRuntimeNetworkDnsLeaseRenewalResponse = (value: unknow
59
59
  });
60
60
 
61
61
  /** trustedSessionValue must come from the receiving CURRENT physical connection. */
62
- export const bindApplyRuntimeNetworkSigningAuthorityRequestV1 = (value: unknown, trustedSessionValue: unknown): IApplyRuntimeNetworkSigningAuthorityRequestV1 => networkSafe(() => {
63
- const request = snapshotApplyRuntimeNetworkSigningAuthorityRequestV1(value), session = snapshotRuntimeSessionBindingV1(trustedSessionValue);
62
+ export const bindApplyRuntimeNetworkSigningAuthorityRequest = (value: unknown, trustedSessionValue: unknown): IApplyRuntimeNetworkSigningAuthorityRequest => networkSafe(() => {
63
+ const request = snapshotApplyRuntimeNetworkSigningAuthorityRequest(value), session = snapshotRuntimeSessionBinding(trustedSessionValue);
64
64
  requireNetwork(networkEqual(request.session, session) && networkEqual(request.authority.controller, session.controller));
65
65
  return request;
66
66
  });
67
67
 
68
68
  /** Content binding only. Verify signature with stored trust and atomically fence admission. */
69
- export const bindApplyRuntimeNetworkProjectionRequestV1 = (value: unknown, trustedSessionValue: unknown): IApplyRuntimeNetworkProjectionRequestV1 => networkSafe(() => {
70
- const request = snapshotApplyRuntimeNetworkProjectionRequestV1(value), session = snapshotRuntimeSessionBindingV1(trustedSessionValue);
69
+ export const bindApplyRuntimeNetworkProjectionRequest = (value: unknown, trustedSessionValue: unknown): IApplyRuntimeNetworkProjectionRequest => networkSafe(() => {
70
+ const request = snapshotApplyRuntimeNetworkProjectionRequest(value), session = snapshotRuntimeSessionBinding(trustedSessionValue);
71
71
  requireNetwork(networkEqual(request.session, session) && networkSameScope(request.signed.projection, session));
72
72
  return request;
73
73
  });
74
74
 
75
75
  /** Compare ACK with the exact SENT key or projection reference, never with a response-derived value. */
76
- export const bindApplyRuntimeNetworkAuthorityResponseV1 = (value: unknown, sentReferenceValue: unknown): IApplyRuntimeNetworkAuthorityResponseV1 => networkSafe(() => {
77
- const response = snapshotApplyRuntimeNetworkAuthorityResponseV1(value);
76
+ export const bindApplyRuntimeNetworkAuthorityResponse = (value: unknown, sentReferenceValue: unknown): IApplyRuntimeNetworkAuthorityResponse => networkSafe(() => {
77
+ const response = snapshotApplyRuntimeNetworkAuthorityResponse(value);
78
78
  const expected = networkReference(captureNetwork(sentReferenceValue));
79
79
  requireNetwork(networkEqual(response.authority, networkReferenceOf(expected)));
80
80
  return response;
@@ -87,7 +87,7 @@ export const bindApplyRuntimeNetworkAuthorityResponseV1 = (value: unknown, sentR
87
87
  * stored trust, then admit and fence atomically.
88
88
  */
89
89
  export const bindApplyRuntimeNetworkDnsLeaseRenewalRequest = (value: unknown, trustedSessionValue: unknown): IApplyRuntimeNetworkDnsLeaseRenewalRequest => networkSafe(() => {
90
- const request = snapshotApplyRuntimeNetworkDnsLeaseRenewalRequest(value), session = snapshotRuntimeSessionBindingV1(trustedSessionValue);
90
+ const request = snapshotApplyRuntimeNetworkDnsLeaseRenewalRequest(value), session = snapshotRuntimeSessionBinding(trustedSessionValue);
91
91
  requireNetwork(networkEqual(request.session, session) && networkSameScope(request.signed.renewal, session));
92
92
  return request;
93
93
  });