@serve.zone/interfaces 32.42.0 → 32.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-10-02 - 32.43.0
4
+
5
+ ### Features
6
+
7
+ - An egress owner that is lost no longer freezes the retirement of every other owner.
8
+ `IRuntimeNetworkEgressRetirement.clearedProjections` names every remaining owner except those
9
+ whose own `lost` fence is recorded against the same authority, and
10
+ `bindRuntimeNetworkProtectedAuthorityRetirement` takes an optional fifth argument `exemptions`
11
+ (default none) and answers them beside the fences: the `lost` fences of owners the step keeps,
12
+ each verified by its digest and recorded under the same controller against the exact `previous`,
13
+ for an owner both sides name and no fence or other exemption names, at most
14
+ `runtimeNetworkEgressRetirementContract.maximumExemptionsPerStep` (255). Every consumed fence's
15
+ clearance must name exactly the kept owners less the exempt ones. Lost owners can be fenced in
16
+ parallel and leave 16 per step, however many there are. `retiredOwners` is now the caller's
17
+ retired-owner history restricted to the owners `previous` or `next` names, and any entry refuses
18
+ the step; `maximumRetiredOwners` bounds that restriction at 512 instead of a lifetime history of
19
+ 4096 owners, so a long-lived authority never runs out of retirements.
20
+
21
+ ### Maintenance
22
+
23
+ - Release tooling: `@git.zone/tstest` 6.3.4.
24
+
3
25
  ## 2026-10-02 - 32.42.0
4
26
 
5
27
  ### Features
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.42.0',
6
+ version: '32.43.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
@@ -29,7 +29,9 @@ export interface IRuntimeNetworkEgressRetirementClearance extends IRuntimeNetwor
29
29
  * 4. every handoff and workload lease the node was granted is quarantined (`quarantinedHandoffs`,
30
30
  * `quarantinedWorkloads`) and is never handed out again;
31
31
  * 5. every remaining owner of `protectedAuthority` acknowledged a projection head that carries no
32
- * endpoint of the node (`clearedProjections`).
32
+ * endpoint of the node (`clearedProjections`). An owner whose own `lost` fence is recorded
33
+ * against the same authority is not a remaining owner here: it never acknowledges anything again,
34
+ * so it can never clear another owner's endpoints, and it leaves behind its own fence.
33
35
  *
34
36
  * `lastReceipt` is the node's last accepted protection receipt. A `withdrawn` node took part in its
35
37
  * retirement, so it always has one — its null withdrawal; a `lost` node may never have reported.
@@ -60,7 +62,10 @@ export interface IRuntimeNetworkEgressRetirement extends IRuntimeNetworkNodeScop
60
62
  quarantinedHandoffs: IRuntimeAuthorityReference[];
61
63
  /** Every workload lease the node was granted, each quarantined, in canonical order. */
62
64
  quarantinedWorkloads: IRuntimeAuthorityReference[];
63
- /** One entry per remaining owner of `protectedAuthority`, in canonical owner order. */
65
+ /**
66
+ * One entry per remaining owner of `protectedAuthority` whose own `lost` fence is not recorded
67
+ * against that authority, in canonical owner order.
68
+ */
64
69
  clearedProjections: IRuntimeNetworkEgressRetirementClearance[];
65
70
  digest: TSha256Digest;
66
71
  }
@@ -71,8 +76,16 @@ export declare const runtimeNetworkEgressRetirementContract: Readonly<{
71
76
  readonly maximumClearedProjections: number;
72
77
  /** Fences one step may consume. Each is read on its own, so one step stays bounded. */
73
78
  readonly maximumFencesPerStep: 16;
74
- /** Owners every earlier step fenced, over the lifetime of one protected authority. */
75
- readonly maximumRetiredOwners: 4096;
79
+ /**
80
+ * Lost fences one step may hold as exemptions: owners it keeps that no consumed fence's clearance
81
+ * has to name. At least one owner is kept, so this is one fewer than the owners an authority has.
82
+ */
83
+ readonly maximumExemptionsPerStep: number;
84
+ /**
85
+ * Retired owners one step may be given: the caller's history restricted to owners `previous` or
86
+ * `next` names, which is at most every owner of both.
87
+ */
88
+ readonly maximumRetiredOwners: number;
76
89
  readonly removal: "absent-owner-requires-fence-bound-to-exact-previous-authority";
77
90
  readonly reentry: "a-fenced-owner-never-returns";
78
91
  }>;
@@ -82,24 +95,35 @@ export declare const computeRuntimeNetworkEgressRetirementDigest: (value: IRunti
82
95
  /**
83
96
  * Whether `next` may succeed `previous`, judged on its egress owners and the address space it keeps.
84
97
  *
85
- * Pure and fail-closed. `fences` are the egress retirements this step consumes; `retiredOwners` is
86
- * the complete list of owners every earlier step fenced, which the caller's durable history must
87
- * supply in canonical owner order. The step is accepted only when:
98
+ * Pure and fail-closed. `fences` are the egress retirements this step consumes. `exemptions` are
99
+ * `lost` fences of owners this step keeps, recorded against the same `previous`: such an owner never
100
+ * acknowledges another projection head, so no consumed fence's clearance can wait for it. They are
101
+ * read, not consumed, and default to none. `retiredOwners` is the caller's durable history of
102
+ * fenced owners restricted to the owners `previous` or `next` names, in canonical owner order. The
103
+ * step is accepted only when:
88
104
  *
89
105
  * - `next` is the exact successor of `previous` under the same controller, and both digests verify;
90
106
  * - an owner of `previous` is absent from `next` only when exactly one fence, recorded against the
91
107
  * exact `previous` reference and verified by its digest, names it — a fence for an owner `next`
92
108
  * still names, or for an owner `previous` does not name, refuses the step;
93
- * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps;
94
- * - no owner in `retiredOwners` is named by `previous` or `next`, so a fenced owner never returns;
109
+ * - every exemption verifies by its digest, is `lost`, is recorded under the same controller against
110
+ * the exact `previous` reference, and names an owner both `previous` and `next` name, no fence
111
+ * names and no other exemption names; at most `maximumExemptionsPerStep`, in canonical owner order;
112
+ * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps, less
113
+ * the exempt owners; an exemption's own clearance is not judged here, only when its owner leaves;
114
+ * - `retiredOwners` is empty: any entry is either an owner a side names that was fenced before, or
115
+ * not part of the restriction at all, so a fenced owner never returns;
95
116
  * - every pool of `previous` is kept unchanged and the prefixes of `next` cover those of `previous`;
96
117
  * a step that removes an owner also keeps every resolver of `previous` unchanged.
97
118
  *
98
119
  * Owners that join in the same step are admitted. With no fence this is the additive owner rule:
99
- * nobody leaves. It verifies no fence evidence against live state and fences no record.
120
+ * nobody leaves, and exemptions relax nothing. It verifies no fence evidence against live state and
121
+ * fences no record: the caller fences every fence and exemption it read together with the authority
122
+ * it stages.
100
123
  */
101
- export declare const bindRuntimeNetworkProtectedAuthorityRetirement: (previousValue: unknown, nextValue: unknown, fencesValue: unknown, retiredOwnersValue: unknown) => Promise<{
124
+ export declare const bindRuntimeNetworkProtectedAuthorityRetirement: (previousValue: unknown, nextValue: unknown, fencesValue: unknown, retiredOwnersValue: unknown, exemptionsValue?: unknown) => Promise<{
102
125
  previous: IRuntimeNetworkProtectedAuthority;
103
126
  next: IRuntimeNetworkProtectedAuthority;
104
127
  fences: IRuntimeNetworkEgressRetirement[];
128
+ exemptions: IRuntimeNetworkEgressRetirement[];
105
129
  }>;
@@ -10,8 +10,16 @@ export const runtimeNetworkEgressRetirementContract = Object.freeze({
10
10
  maximumClearedProjections: runtimeNetworkAuthorityContract.maximumEgressAuthorities - 1,
11
11
  /** Fences one step may consume. Each is read on its own, so one step stays bounded. */
12
12
  maximumFencesPerStep: 16,
13
- /** Owners every earlier step fenced, over the lifetime of one protected authority. */
14
- maximumRetiredOwners: 4096,
13
+ /**
14
+ * Lost fences one step may hold as exemptions: owners it keeps that no consumed fence's clearance
15
+ * has to name. At least one owner is kept, so this is one fewer than the owners an authority has.
16
+ */
17
+ maximumExemptionsPerStep: runtimeNetworkAuthorityContract.maximumEgressAuthorities - 1,
18
+ /**
19
+ * Retired owners one step may be given: the caller's history restricted to owners `previous` or
20
+ * `next` names, which is at most every owner of both.
21
+ */
22
+ maximumRetiredOwners: 2 * runtimeNetworkAuthorityContract.maximumEgressAuthorities,
15
23
  removal: 'absent-owner-requires-fence-bound-to-exact-previous-authority',
16
24
  reentry: 'a-fenced-owner-never-returns',
17
25
  });
@@ -55,23 +63,33 @@ export const computeRuntimeNetworkEgressRetirementDigest = (value) => networkHas
55
63
  /**
56
64
  * Whether `next` may succeed `previous`, judged on its egress owners and the address space it keeps.
57
65
  *
58
- * Pure and fail-closed. `fences` are the egress retirements this step consumes; `retiredOwners` is
59
- * the complete list of owners every earlier step fenced, which the caller's durable history must
60
- * supply in canonical owner order. The step is accepted only when:
66
+ * Pure and fail-closed. `fences` are the egress retirements this step consumes. `exemptions` are
67
+ * `lost` fences of owners this step keeps, recorded against the same `previous`: such an owner never
68
+ * acknowledges another projection head, so no consumed fence's clearance can wait for it. They are
69
+ * read, not consumed, and default to none. `retiredOwners` is the caller's durable history of
70
+ * fenced owners restricted to the owners `previous` or `next` names, in canonical owner order. The
71
+ * step is accepted only when:
61
72
  *
62
73
  * - `next` is the exact successor of `previous` under the same controller, and both digests verify;
63
74
  * - an owner of `previous` is absent from `next` only when exactly one fence, recorded against the
64
75
  * exact `previous` reference and verified by its digest, names it — a fence for an owner `next`
65
76
  * still names, or for an owner `previous` does not name, refuses the step;
66
- * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps;
67
- * - no owner in `retiredOwners` is named by `previous` or `next`, so a fenced owner never returns;
77
+ * - every exemption verifies by its digest, is `lost`, is recorded under the same controller against
78
+ * the exact `previous` reference, and names an owner both `previous` and `next` name, no fence
79
+ * names and no other exemption names; at most `maximumExemptionsPerStep`, in canonical owner order;
80
+ * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps, less
81
+ * the exempt owners; an exemption's own clearance is not judged here, only when its owner leaves;
82
+ * - `retiredOwners` is empty: any entry is either an owner a side names that was fenced before, or
83
+ * not part of the restriction at all, so a fenced owner never returns;
68
84
  * - every pool of `previous` is kept unchanged and the prefixes of `next` cover those of `previous`;
69
85
  * a step that removes an owner also keeps every resolver of `previous` unchanged.
70
86
  *
71
87
  * Owners that join in the same step are admitted. With no fence this is the additive owner rule:
72
- * nobody leaves. It verifies no fence evidence against live state and fences no record.
88
+ * nobody leaves, and exemptions relax nothing. It verifies no fence evidence against live state and
89
+ * fences no record: the caller fences every fence and exemption it read together with the authority
90
+ * it stages.
73
91
  */
74
- export const bindRuntimeNetworkProtectedAuthorityRetirement = async (previousValue, nextValue, fencesValue, retiredOwnersValue) => {
92
+ export const bindRuntimeNetworkProtectedAuthorityRetirement = async (previousValue, nextValue, fencesValue, retiredOwnersValue, exemptionsValue = []) => {
75
93
  try {
76
94
  const contract = runtimeNetworkEgressRetirementContract;
77
95
  const previous = snapshotRuntimeNetworkProtectedAuthority(captureNetwork(previousValue));
@@ -79,6 +97,9 @@ export const bindRuntimeNetworkProtectedAuthorityRetirement = async (previousVal
79
97
  const elements = readDataElements(fencesValue, contract.maximumFencesPerStep);
80
98
  requireNetwork(elements);
81
99
  const fences = networkSorted(elements.map(snapshotRuntimeNetworkEgressRetirement), ownerKey);
100
+ const exemptionElements = readDataElements(exemptionsValue, contract.maximumExemptionsPerStep);
101
+ requireNetwork(exemptionElements);
102
+ const exemptions = networkSorted(exemptionElements.map(snapshotRuntimeNetworkEgressRetirement), ownerKey);
82
103
  const retiredOwners = networkSorted(networkList(captureNetwork(retiredOwnersValue), contract.maximumRetiredOwners, readOwner), ownerKey);
83
104
  requireNetwork(previous.digest === await computeRuntimeNetworkProtectedAuthorityDigest(previous)
84
105
  && next.digest === await computeRuntimeNetworkProtectedAuthorityDigest(next));
@@ -94,20 +115,28 @@ export const bindRuntimeNetworkProtectedAuthorityRetirement = async (previousVal
94
115
  && previousOwners.has(ownerKey(fence)) && !nextOwners.has(ownerKey(fence)));
95
116
  }
96
117
  requireNetwork([...previousOwners].every(owner => nextOwners.has(owner) || fenced.has(owner)));
97
- const kept = previous.egressAuthorities.filter(owner => !fenced.has(ownerKey(owner))).map(ownerKey);
118
+ for (const exemption of exemptions) {
119
+ requireNetwork(exemption.digest === await computeRuntimeNetworkEgressRetirementDigest(exemption)
120
+ && exemption.disposition === 'lost' && networkEqual(exemption.controller, previous.controller)
121
+ && networkEqual(exemption.protectedAuthority, reference) && previousOwners.has(ownerKey(exemption))
122
+ && nextOwners.has(ownerKey(exemption)));
123
+ }
124
+ // A fence's owner is never named by `next`, so no exemption names an owner a fence names.
125
+ const exempt = new Set(exemptions.map(ownerKey));
126
+ const cleared = previous.egressAuthorities.map(ownerKey).filter(owner => !fenced.has(owner) && !exempt.has(owner));
98
127
  for (const fence of fences) {
99
- requireNetwork(networkEqual(fence.clearedProjections.map(ownerKey), kept));
128
+ requireNetwork(networkEqual(fence.clearedProjections.map(ownerKey), cleared));
100
129
  }
101
- requireNetwork(retiredOwners.every(owner => !previousOwners.has(ownerKey(owner)) && !nextOwners.has(ownerKey(owner))));
130
+ requireNetwork(retiredOwners.length === 0);
102
131
  requireNetwork(previous.pools.every(pool => next.pools.some(candidate => networkEqual(candidate, pool)))
103
132
  && previous.prefixes.every(prefix => networkCoveredBy(next.prefixes, prefix)));
104
133
  if (fences.length > 0) {
105
134
  requireNetwork(previous.resolvers.every(resolver => next.resolvers.some(candidate => networkEqual(candidate, resolver))));
106
135
  }
107
- return { previous, next, fences };
136
+ return { previous, next, fences, exemptions };
108
137
  }
109
138
  catch {
110
139
  return failNetwork();
111
140
  }
112
141
  };
113
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2VncmVzc3JldGlyZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL25ldHdvcmtlZ3Jlc3NyZXRpcmVtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBRSw2Q0FBNkMsRUFBRSwrQkFBK0IsRUFDckYsd0NBQXdDLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRSxPQUFPLEVBQUUsaUNBQWlDLEVBQTBDLE1BQU0scUJBQXFCLENBQUM7QUFDaEgsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUNuSCxXQUFXLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFDcEgsWUFBWSxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQStEckYsTUFBTSxDQUFDLE1BQU0sc0NBQXNDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNsRSxZQUFZLEVBQUUsOENBQThDO0lBQzVELDBCQUEwQixFQUFFLCtCQUErQixDQUFDLDRCQUE0QjtJQUN4RiwyQkFBMkIsRUFBRSxHQUFHO0lBQ2hDLHlCQUF5QixFQUFFLCtCQUErQixDQUFDLHdCQUF3QixHQUFHLENBQUM7SUFDdkYsdUZBQXVGO0lBQ3ZGLG9CQUFvQixFQUFFLEVBQUU7SUFDeEIsc0ZBQXNGO0lBQ3RGLG9CQUFvQixFQUFFLElBQUk7SUFDMUIsT0FBTyxFQUFFLCtEQUErRDtJQUN4RSxPQUFPLEVBQUUsOEJBQThCO0NBQy9CLENBQUMsQ0FBQztBQUVaLE1BQU0sUUFB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
142
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2VncmVzc3JldGlyZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL25ldHdvcmtlZ3Jlc3NyZXRpcmVtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBRSw2Q0FBNkMsRUFBRSwrQkFBK0IsRUFDckYsd0NBQXdDLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRSxPQUFPLEVBQUUsaUNBQWlDLEVBQTBDLE1BQU0scUJBQXFCLENBQUM7QUFDaEgsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUNuSCxXQUFXLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFDcEgsWUFBWSxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQW9FckYsTUFBTSxDQUFDLE1BQU0sc0NBQXNDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNsRSxZQUFZLEVBQUUsOENBQThDO0lBQzVELDBCQUEwQixFQUFFLCtCQUErQixDQUFDLDRCQUE0QjtJQUN4RiwyQkFBMkIsRUFBRSxHQUFHO0lBQ2hDLHlCQUF5QixFQUFFLCtCQUErQixDQUFDLHdCQUF3QixHQUFHLENBQUM7SUFDdkYsdUZBQXVGO0lBQ3ZGLG9CQUFvQixFQUFFLEVBQUU7SUFDeEI7OztPQUdHO0lBQ0gsd0JBQXdCLEVBQUUsK0JBQStCLENBQUMsd0JBQXdCLEdBQUcsQ0FBQztJQUN0Rjs7O09BR0c7SUFDSCxvQkFBb0IsRUFBRSxDQUFDLEdBQUcsK0JBQStCLENBQUMs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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "32.42.0",
3
+ "version": "32.43.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
@@ -30,7 +30,7 @@
30
30
  "@git.zone/tsbuild": "^5.1.1",
31
31
  "@git.zone/tsdoc": "^3.0.1",
32
32
  "@git.zone/tsrun": "^3.0.2",
33
- "@git.zone/tstest": "6.3.2",
33
+ "@git.zone/tstest": "6.3.4",
34
34
  "@types/node": "26.6.2"
35
35
  },
36
36
  "files": [
package/readme.md CHANGED
@@ -796,8 +796,11 @@ exact protected authority the owner is about to leave, once all five hold:
796
796
  (`quarantinedHandoffs`, at most 256, and `quarantinedWorkloads`, at most 512,
797
797
  both in canonical order) and is never handed out again;
798
798
  5. every remaining owner of that authority acknowledged a projection head that
799
- carries no endpoint of the node (`clearedProjections`, one per remaining owner
800
- in canonical owner order, never the node itself).
799
+ carries no endpoint of the node (`clearedProjections`, in canonical owner order,
800
+ never the node itself). A remaining owner whose own `lost` fence is recorded
801
+ against the same authority is left out: it never acknowledges anything again, so
802
+ waiting for it would freeze every other owner's retirement, and it leaves behind
803
+ its own fence. Every other remaining owner has exactly one entry.
801
804
 
802
805
  `lastReceipt` is the node's last accepted protection receipt. A `withdrawn` node
803
806
  took part in its own retirement, so it always has one (its null withdrawal); a
@@ -810,19 +813,40 @@ evidence; the controller fences the rows it read together with the authority it
810
813
  stages.
811
814
 
812
815
  `bindRuntimeNetworkProtectedAuthorityRetirement(previous, next, fences,
813
- retiredOwners)` is the pure successor rule for the egress owners and the address
814
- space of any step. `next` must be the exact successor of `previous` under the same
816
+ retiredOwners, exemptions = [])` is the pure successor rule for the egress owners
817
+ and the address space of any step, and answers `{ previous, next, fences,
818
+ exemptions }`. `next` must be the exact successor of `previous` under the same
815
819
  controller, with both digests verified. An owner of `previous` may be absent from
816
820
  `next` only when exactly one fence recorded against the exact `previous` reference,
817
821
  verified by its digest, names it; a fence for an owner `next` still names, or one
818
- `previous` never named, refuses the step, and every fence's `clearedProjections`
819
- must name exactly the owners the step keeps. `retiredOwners` is the complete,
820
- canonically ordered list of owners earlier steps fenced, which the caller's
821
- durable history supplies; neither side may name any of them, so a fenced owner
822
- never returns. Every pool of `previous` stays unchanged and the prefixes of `next`
823
- cover those of `previous`; a step that removes an owner also keeps every resolver.
824
- Owners may join in the same step, and a step without fences is the additive rule.
825
- One step consumes at most 16 fences (`runtimeNetworkEgressRetirementContract`).
822
+ `previous` never named, refuses the step.
823
+
824
+ `exemptions` are the `lost` fences of owners the step keeps, recorded against the
825
+ same `previous`. They are read and returned, not consumed: each verifies by its
826
+ digest, is recorded under the same controller against the exact `previous`
827
+ reference, and names an owner both `previous` and `next` name that no fence and no
828
+ other exemption names, in canonical owner order and at most 255 per step. A
829
+ withdrawn or stale exemption refuses the step. Every consumed fence's
830
+ `clearedProjections` must name exactly the owners the step keeps less the exempt
831
+ owners, in both directions: a clearance that names an exempt owner or misses a kept
832
+ one refuses the step. An exemption's own clearance is judged only in the step that
833
+ consumes it as a fence. Lost owners can therefore be fenced in parallel against one
834
+ authority and leave 16 per step: each step consumes up to 16 of their fences and
835
+ holds the rest as exemptions, and every later step re-records the remaining fences
836
+ against its own `previous`.
837
+
838
+ `retiredOwners` is the caller's durable history of fenced owners restricted to the
839
+ owners `previous` or `next` names, in canonical order and at most 512 entries. Any
840
+ entry refuses the step, so a fenced owner never returns, and the caller looks up
841
+ only the owners of the two authorities instead of supplying a lifetime list. The
842
+ caller must look up every owner that `previous` and `next` name: the binder cannot
843
+ tell a missed lookup from an empty history, so an omitted entry silently drops the
844
+ guarantee. Every
845
+ pool of `previous` stays unchanged and the prefixes of `next` cover those of
846
+ `previous`; a step that removes an owner also keeps every resolver. Owners may join
847
+ in the same step, and a step without fences is the additive rule, which exemptions
848
+ do not change. One step consumes at most 16 fences
849
+ (`runtimeNetworkEgressRetirementContract`).
826
850
 
827
851
  A retirement step is a new protected authority: every remaining owner reports a
828
852
  receipt citing it before anything new is allocated, while existing leases keep
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.42.0',
6
+ version: '32.43.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -39,7 +39,9 @@ export interface IRuntimeNetworkEgressRetirementClearance extends IRuntimeNetwor
39
39
  * 4. every handoff and workload lease the node was granted is quarantined (`quarantinedHandoffs`,
40
40
  * `quarantinedWorkloads`) and is never handed out again;
41
41
  * 5. every remaining owner of `protectedAuthority` acknowledged a projection head that carries no
42
- * endpoint of the node (`clearedProjections`).
42
+ * endpoint of the node (`clearedProjections`). An owner whose own `lost` fence is recorded
43
+ * against the same authority is not a remaining owner here: it never acknowledges anything again,
44
+ * so it can never clear another owner's endpoints, and it leaves behind its own fence.
43
45
  *
44
46
  * `lastReceipt` is the node's last accepted protection receipt. A `withdrawn` node took part in its
45
47
  * retirement, so it always has one — its null withdrawal; a `lost` node may never have reported.
@@ -67,7 +69,10 @@ export interface IRuntimeNetworkEgressRetirement extends IRuntimeNetworkNodeScop
67
69
  quarantinedHandoffs: IRuntimeAuthorityReference[];
68
70
  /** Every workload lease the node was granted, each quarantined, in canonical order. */
69
71
  quarantinedWorkloads: IRuntimeAuthorityReference[];
70
- /** One entry per remaining owner of `protectedAuthority`, in canonical owner order. */
72
+ /**
73
+ * One entry per remaining owner of `protectedAuthority` whose own `lost` fence is not recorded
74
+ * against that authority, in canonical owner order.
75
+ */
71
76
  clearedProjections: IRuntimeNetworkEgressRetirementClearance[];
72
77
  digest: TSha256Digest;
73
78
  }
@@ -79,8 +84,16 @@ export const runtimeNetworkEgressRetirementContract = Object.freeze({
79
84
  maximumClearedProjections: runtimeNetworkAuthorityContract.maximumEgressAuthorities - 1,
80
85
  /** Fences one step may consume. Each is read on its own, so one step stays bounded. */
81
86
  maximumFencesPerStep: 16,
82
- /** Owners every earlier step fenced, over the lifetime of one protected authority. */
83
- maximumRetiredOwners: 4096,
87
+ /**
88
+ * Lost fences one step may hold as exemptions: owners it keeps that no consumed fence's clearance
89
+ * has to name. At least one owner is kept, so this is one fewer than the owners an authority has.
90
+ */
91
+ maximumExemptionsPerStep: runtimeNetworkAuthorityContract.maximumEgressAuthorities - 1,
92
+ /**
93
+ * Retired owners one step may be given: the caller's history restricted to owners `previous` or
94
+ * `next` names, which is at most every owner of both.
95
+ */
96
+ maximumRetiredOwners: 2 * runtimeNetworkAuthorityContract.maximumEgressAuthorities,
84
97
  removal: 'absent-owner-requires-fence-bound-to-exact-previous-authority',
85
98
  reentry: 'a-fenced-owner-never-returns',
86
99
  } as const);
@@ -132,28 +145,40 @@ export const computeRuntimeNetworkEgressRetirementDigest = (value: IRuntimeNetwo
132
145
  /**
133
146
  * Whether `next` may succeed `previous`, judged on its egress owners and the address space it keeps.
134
147
  *
135
- * Pure and fail-closed. `fences` are the egress retirements this step consumes; `retiredOwners` is
136
- * the complete list of owners every earlier step fenced, which the caller's durable history must
137
- * supply in canonical owner order. The step is accepted only when:
148
+ * Pure and fail-closed. `fences` are the egress retirements this step consumes. `exemptions` are
149
+ * `lost` fences of owners this step keeps, recorded against the same `previous`: such an owner never
150
+ * acknowledges another projection head, so no consumed fence's clearance can wait for it. They are
151
+ * read, not consumed, and default to none. `retiredOwners` is the caller's durable history of
152
+ * fenced owners restricted to the owners `previous` or `next` names, in canonical owner order. The
153
+ * step is accepted only when:
138
154
  *
139
155
  * - `next` is the exact successor of `previous` under the same controller, and both digests verify;
140
156
  * - an owner of `previous` is absent from `next` only when exactly one fence, recorded against the
141
157
  * exact `previous` reference and verified by its digest, names it — a fence for an owner `next`
142
158
  * still names, or for an owner `previous` does not name, refuses the step;
143
- * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps;
144
- * - no owner in `retiredOwners` is named by `previous` or `next`, so a fenced owner never returns;
159
+ * - every exemption verifies by its digest, is `lost`, is recorded under the same controller against
160
+ * the exact `previous` reference, and names an owner both `previous` and `next` name, no fence
161
+ * names and no other exemption names; at most `maximumExemptionsPerStep`, in canonical owner order;
162
+ * - every fence's `clearedProjections` names exactly the owners of `previous` this step keeps, less
163
+ * the exempt owners; an exemption's own clearance is not judged here, only when its owner leaves;
164
+ * - `retiredOwners` is empty: any entry is either an owner a side names that was fenced before, or
165
+ * not part of the restriction at all, so a fenced owner never returns;
145
166
  * - every pool of `previous` is kept unchanged and the prefixes of `next` cover those of `previous`;
146
167
  * a step that removes an owner also keeps every resolver of `previous` unchanged.
147
168
  *
148
169
  * Owners that join in the same step are admitted. With no fence this is the additive owner rule:
149
- * nobody leaves. It verifies no fence evidence against live state and fences no record.
170
+ * nobody leaves, and exemptions relax nothing. It verifies no fence evidence against live state and
171
+ * fences no record: the caller fences every fence and exemption it read together with the authority
172
+ * it stages.
150
173
  */
151
174
  export const bindRuntimeNetworkProtectedAuthorityRetirement = async (
152
175
  previousValue: unknown, nextValue: unknown, fencesValue: unknown, retiredOwnersValue: unknown,
176
+ exemptionsValue: unknown = [],
153
177
  ): Promise<{
154
178
  previous: IRuntimeNetworkProtectedAuthority;
155
179
  next: IRuntimeNetworkProtectedAuthority;
156
180
  fences: IRuntimeNetworkEgressRetirement[];
181
+ exemptions: IRuntimeNetworkEgressRetirement[];
157
182
  }> => {
158
183
  try {
159
184
  const contract = runtimeNetworkEgressRetirementContract;
@@ -162,6 +187,9 @@ export const bindRuntimeNetworkProtectedAuthorityRetirement = async (
162
187
  const elements = readDataElements(fencesValue, contract.maximumFencesPerStep);
163
188
  requireNetwork(elements);
164
189
  const fences = networkSorted(elements.map(snapshotRuntimeNetworkEgressRetirement), ownerKey);
190
+ const exemptionElements = readDataElements(exemptionsValue, contract.maximumExemptionsPerStep);
191
+ requireNetwork(exemptionElements);
192
+ const exemptions = networkSorted(exemptionElements.map(snapshotRuntimeNetworkEgressRetirement), ownerKey);
165
193
  const retiredOwners = networkSorted(networkList(captureNetwork(retiredOwnersValue), contract.maximumRetiredOwners,
166
194
  readOwner), ownerKey);
167
195
  requireNetwork(previous.digest === await computeRuntimeNetworkProtectedAuthorityDigest(previous)
@@ -179,17 +207,25 @@ export const bindRuntimeNetworkProtectedAuthorityRetirement = async (
179
207
  && previousOwners.has(ownerKey(fence)) && !nextOwners.has(ownerKey(fence)));
180
208
  }
181
209
  requireNetwork([...previousOwners].every(owner => nextOwners.has(owner) || fenced.has(owner)));
182
- const kept = previous.egressAuthorities.filter(owner => !fenced.has(ownerKey(owner))).map(ownerKey);
210
+ for (const exemption of exemptions) {
211
+ requireNetwork(exemption.digest === await computeRuntimeNetworkEgressRetirementDigest(exemption)
212
+ && exemption.disposition === 'lost' && networkEqual(exemption.controller, previous.controller)
213
+ && networkEqual(exemption.protectedAuthority, reference) && previousOwners.has(ownerKey(exemption))
214
+ && nextOwners.has(ownerKey(exemption)));
215
+ }
216
+ // A fence's owner is never named by `next`, so no exemption names an owner a fence names.
217
+ const exempt = new Set(exemptions.map(ownerKey));
218
+ const cleared = previous.egressAuthorities.map(ownerKey).filter(owner => !fenced.has(owner) && !exempt.has(owner));
183
219
  for (const fence of fences) {
184
- requireNetwork(networkEqual(fence.clearedProjections.map(ownerKey), kept));
220
+ requireNetwork(networkEqual(fence.clearedProjections.map(ownerKey), cleared));
185
221
  }
186
- requireNetwork(retiredOwners.every(owner => !previousOwners.has(ownerKey(owner)) && !nextOwners.has(ownerKey(owner))));
222
+ requireNetwork(retiredOwners.length === 0);
187
223
 
188
224
  requireNetwork(previous.pools.every(pool => next.pools.some(candidate => networkEqual(candidate, pool)))
189
225
  && previous.prefixes.every(prefix => networkCoveredBy(next.prefixes, prefix)));
190
226
  if (fences.length > 0) {
191
227
  requireNetwork(previous.resolvers.every(resolver => next.resolvers.some(candidate => networkEqual(candidate, resolver))));
192
228
  }
193
- return { previous, next, fences };
229
+ return { previous, next, fences, exemptions };
194
230
  } catch { return failNetwork(); }
195
231
  };