@agentplat/mesh-protocol 0.3.0-alpha.1 → 0.3.0-alpha.3

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/README.md CHANGED
@@ -2,12 +2,27 @@
2
2
 
3
3
  Closed, bounded and transport-neutral wire contracts for AgentPlat Mesh peers.
4
4
 
5
- The Alpha 1 implementation provides:
5
+ The implementation provides:
6
6
 
7
7
  - strict UTF-8 and JSON parsing that rejects duplicate decoded keys, malformed
8
8
  Unicode, ambiguous syntax and documents outside explicit structural limits;
9
9
  - deterministic JSON canonicalization for hashing and signing;
10
10
  - closed-schema validation for `peer.hello`, `peer.ping` and `peer.ping_ack`;
11
+ - closed, bounded Alpha 2 discovery and capability records for `peer.card`,
12
+ `peer.goodbye`, `capability.advertise` and `capability.withdraw`;
13
+ - closed, bounded Alpha 2 Objective records for `objective.announce`,
14
+ `objective.revise` and `objective.cancel`;
15
+ - closed, bounded Alpha 2 Work Offer and Work Bid records for `work.offer` and
16
+ `work.bid`;
17
+ - closed, bounded Alpha 2 award-response records for `work.award`,
18
+ `work.accept` and `work.decline`;
19
+ - closed, bounded Alpha 2 execution records for `work.progress`,
20
+ `work.checkpoint` and `work.result`;
21
+ - closed, bounded Alpha 2 Work Release and Work Cancel records for
22
+ `work.release` and `work.cancel`;
23
+ - a closed, bounded Alpha 2 Lease Renewal record for `lease.renew`;
24
+ - a closed, bounded Alpha 2 Lease Takeover Proposal record for
25
+ `lease.takeover_proposal`;
11
26
  - exact representations for message IDs, SHA-256 payload digests and Ed25519
12
27
  proofs;
13
28
  - receiver-context checks for tenant and Mesh scope, audience, freshness and
@@ -31,5 +46,283 @@ keys, verify signatures, perform replay admission, or mutate peer state. Those
31
46
  are separate stages so callers cannot confuse structural validity with
32
47
  cryptographic authenticity or local acceptance.
33
48
 
49
+ Evidence, trust and peer-sync message families remain reserved until their
50
+ closed payload contracts are implemented. They fail explicitly rather than
51
+ entering a generic payload path. Implemented Objective, Work, Lease Renewal,
52
+ Lease Takeover Proposal, Lease Vote and Lease Certificate records parse, sign
53
+ and verify structurally, but remain explicitly unsupported at the Mesh runtime
54
+ boundary until their reducers and state authorization are implemented.
55
+
56
+ ## Frozen limits
57
+
58
+ Protocol v0 applies these structural limits before a payload can enter a
59
+ reducer:
60
+
61
+ | Limit | Maximum |
62
+ | -------------------------------------- | ------------------: |
63
+ | Decompressed envelope | 262,144 UTF-8 bytes |
64
+ | Payload | 196,608 UTF-8 bytes |
65
+ | Nesting depth | 32 |
66
+ | Total object keys / keys in one object | 2,048 / 256 |
67
+ | Total array items / items in one array | 4,096 / 1,024 |
68
+ | One string | 65,536 UTF-8 bytes |
69
+ | Extensions / critical extensions | 16 / 8 |
70
+ | Identifier | 256 UTF-8 bytes |
71
+ | Envelope lifetime | 10 minutes |
72
+ | Clock-skew allowance | 2 minutes |
73
+ | Replay window | 2,048 sequences |
74
+
75
+ The implemented Alpha 2 discovery and capability payloads additionally freeze
76
+ these narrower limits:
77
+
78
+ | Field | Rule |
79
+ | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
80
+ | `protocolVersions` | 1–8 sorted unique non-negative safe integers and must include `0` |
81
+ | Peer Card transport hints | At most 8 sorted unique non-empty strings; 2,048 UTF-8 bytes each and 8,192 bytes in aggregate |
82
+ | Peer Card capability IDs | At most 32 sorted unique identifiers |
83
+ | Capability key | Non-empty; at most 4,096 UTF-8 bytes |
84
+ | Capability version and optional variant | Non-empty; at most 128 UTF-8 bytes each |
85
+ | Input or output media types | At most 16 sorted unique non-empty strings per collection; 128 UTF-8 bytes each |
86
+ | Capability attributes | At most 32 entries; non-empty keys up to 128 UTF-8 bytes, non-empty values up to 1,024 bytes, and 16,384 bytes in aggregate |
87
+ | Peer Card or capability-advertisement validity | Greater than zero and at most exactly 24 hours |
88
+
89
+ Every collection marked sorted and unique uses ascending lexicographic order
90
+ over UTF-16 code units, matching the JCS/RFC 8785 property-name ordering rule.
91
+ This is intentionally not Unicode code-point order; duplicate adjacent values
92
+ are rejected.
93
+
94
+ Envelope TTL is 30 seconds for `peer.ping` and `peer.ping_ack`, 60 seconds for
95
+ `peer.goodbye`, and 120 seconds for `peer.hello`, `peer.card`,
96
+ `capability.advertise` and `capability.withdraw`. These family limits are also
97
+ bounded by the global ten-minute maximum.
98
+
99
+ Work Release and Work Cancel envelopes have a two-minute TTL. Release is a
100
+ closed `owner`/`assignee` authority and `reoffer`/`close` disposition pair;
101
+ assignee release must be sent before its declared lease expiry. Cancel is a
102
+ closed `award_pending` branch without `acceptanceId` or `active` branch with
103
+ one. These are structural limits only; local state determines recipients,
104
+ authority, terminality, idempotency and accounting.
105
+
106
+ Lease Renewal envelopes have a 30-second TTL and must expire no later than the
107
+ currently declared lease. A renewal self-binds the assignee, requires direct
108
+ delivery and extends the declared expiry by a positive duration of at most 24
109
+ hours. The accepted Objective may impose a lower duration and renewal count.
110
+
111
+ Lease Takeover Proposal envelopes have a one-minute TTL. They require one direct
112
+ peer audience, mandatory causation and Objective-header equality. The trusted
113
+ receiver clock and accepted Objective policy—not sender-declared time—determine
114
+ whether lease expiry plus recovery grace has elapsed.
115
+
116
+ Lease Vote envelopes also have a one-minute TTL. They self-bind the witness,
117
+ require direct delivery and Objective-header equality, and causally name the
118
+ accepted takeover proposal they endorse. Witness membership and vote
119
+ uniqueness require accepted local state.
120
+
121
+ Lease Certificate envelopes have a one-minute TTL and self-bind their
122
+ assembler. They carry between two and 32 sorted unique vote IDs, require direct
123
+ delivery, Objective-header equality and proposal causation. The accepted
124
+ Objective determines the actual threshold.
125
+
126
+ Alpha 2 domain-limit, ordering, validity, self-binding and predecessor
127
+ violations return `invalid_payload`. Envelope lifetime violations return
128
+ `invalid_lifetime`; generic parser structural-limit violations return
129
+ `structural_limit_exceeded`.
130
+
131
+ ## Objective limits
132
+
133
+ Objective documents are complete replacements: announce is revision 1 with no
134
+ envelope causation ID; revise is revision 2 or greater, names a different
135
+ `previousObjectiveDocumentId`, and requires envelope `causationId`; cancel names
136
+ the current document and revision and also requires envelope `causationId`.
137
+ The envelope `causationId` is a message ID, not a substitute for the payload's
138
+ previous-document ID. All three messages require an envelope `objectiveId` that
139
+ exactly matches the payload. Document issuers must self-bind to the sender.
140
+ Structural acceptance of `contentReference` does not authorize retrieval;
141
+ issuer authority, reference authorization and current-revision checks require
142
+ accepted local state and remain outside the protocol parser.
143
+
144
+ | Field | Rule |
145
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
146
+ | Summary or content reference | Exactly one non-empty representation; each at most 4,096 UTF-8 bytes |
147
+ | Success criteria | 1–32 non-empty strings, 4,096 UTF-8 bytes each and 16,384 bytes in aggregate |
148
+ | Permitted capability keys | 1–32 sorted unique non-empty strings, 4,096 UTF-8 bytes each |
149
+ | Work / concurrency | Work items 1–1,000,000; concurrency 1 through work-item maximum |
150
+ | Budget units | Non-negative safe integer |
151
+ | Timers | Bid window at most 1 hour; acceptance at most 15 minutes; lease at most 24 hours; recovery grace at most 1 hour; each must fit within validity |
152
+ | Lease renewals | Safe integer 0–100 |
153
+ | Recovery witnesses | 3–32 sorted unique identifiers and strict-majority threshold |
154
+ | Authorized observers | Optional, at most 32 sorted unique identifiers |
155
+ | Objective validity | Greater than zero and at most exactly 30 days |
156
+
157
+ Objective announce and revise have a five-minute envelope TTL; cancel has a
158
+ two-minute TTL. Objective scope, binding, closure, ordering, revision,
159
+ causation, timer and limit violations reject with `invalid_payload`; their TTL
160
+ violations reject with `invalid_lifetime`.
161
+
162
+ ## Work Offer and Bid limits
163
+
164
+ Work Offers name an immutable Objective document and work-item revision. The
165
+ first attempt has no predecessor or envelope causation; later attempts require
166
+ both and must name a different `previousOfferId`. Offers self-bind their owner
167
+ to the envelope sender and may target one peer or the `work` topic. Work Bids
168
+ name one Offer, self-bind their bidder to the sender, require causation, and
169
+ must be addressed directly to the named owner. Bid revision 1 has no predecessor;
170
+ later revisions require a different `previousBidId`.
171
+
172
+ | Field | Rule |
173
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
174
+ | Required capability keys | 1–32 sorted unique non-empty strings, at most 4,096 UTF-8 bytes each |
175
+ | Matching attributes | At most 32 entries; non-empty keys up to 128 UTF-8 bytes, non-empty values up to 1,024 bytes, and 16,384 bytes in aggregate |
176
+ | Input summary or reference | Exactly one non-empty representation; each at most 4,096 UTF-8 bytes |
177
+ | Completion criteria | 1–32 non-empty strings, at most 4,096 UTF-8 bytes each and 16,384 bytes in aggregate |
178
+ | Bid assumptions | 0–32 non-empty strings, at most 4,096 UTF-8 bytes each and 16,384 bytes in aggregate |
179
+ | Reservation and budget units | Budget values are non-negative safe integers; capacity reservation is a safe integer from 1 through 1,000,000 |
180
+ | Offer deadlines | `sentAt < bidDeadline < workDeadline`; bid deadline is at most 1 hour after send, work deadline at most 30 days after send, and envelope expiry must not exceed bid deadline |
181
+ | Bid deadlines | `sentAt < bidExpiresAt <= bidDeadline < expectedCompletionAt <= workDeadline`; the same one-hour bid and 30-day work horizons apply, and envelope expiry must not exceed bid expiry |
182
+
183
+ Offer and Bid envelope TTL is two minutes. Structural validation does not decide
184
+ whether an Objective revision is current, a Work Item is current, an offer
185
+ attempt supersedes another offer, a capability advertisement is accepted, a
186
+ bid has capacity or budget authority, or deadlines and reservations are valid
187
+ against accepted local state. Those checks require reducer authorization state
188
+ and remain deferred.
189
+
190
+ ## Work Award, Accept and Decline limits
191
+
192
+ An Award names one Offer and selected Bid and self-binds the owner sender. Any
193
+ direct peer audience is structurally valid; whether it is the assignee or a
194
+ witness is a local-state check. It carries an assignment epoch,
195
+ assignment-authority ID and fencing token. The normal `authorityKind: "award"`
196
+ branch requires both IDs to equal `awardId` and forbids recovery references. The
197
+ `authorityKind: "recovery_certificate"` branch requires `recoveryCertificateId`
198
+ and requires both IDs to equal that certificate; an optional resume checkpoint
199
+ is structural metadata only.
200
+
201
+ Accept and Decline each name the Award and self-bind the assignee sender.
202
+ Accept accepts any direct peer audience structurally; owner-or-witness
203
+ authorization is stateful. Decline is structurally directed to the owner. Both
204
+ require an envelope causation ID. Resolving Award causation to the selected Bid
205
+ envelope, and response causation to the accepted Award envelope, requires the
206
+ local causal journal and is stateful. All three records bind the envelope
207
+ Objective ID to the payload Objective ID.
208
+
209
+ | Field | Rule |
210
+ | ---------------- | ------------------------------------------------------------------------------------------ |
211
+ | Owner epoch | Positive safe integer; frozen at `1` for this protocol slice |
212
+ | Assignment epoch | Positive safe integer; recovery authority requires epoch `2` or greater |
213
+ | Award time order | `sentAt <= leaseStartsAt < acceptanceDeadline <= leaseExpiresAt <= workDeadline` |
214
+ | Award windows | Acceptance window at most 15 minutes; lease at most 24 hours; work horizon at most 30 days |
215
+ | Award expiry | At most two minutes and no later than `acceptanceDeadline` |
216
+ | Response time | `sentAt < acceptanceDeadline`; expiry at most two minutes and no later than that deadline |
217
+
218
+ These are structural contracts only. Selection of a current bid, current owner
219
+ and revision, budget reservation, acceptance uniqueness, deadline observation,
220
+ causal-reference resolution, and recovery-certificate acceptance all require
221
+ local state and remain deferred.
222
+
223
+ ## Work Progress, Checkpoint and Result limits
224
+
225
+ Execution records self-bind the assignee sender, require a direct peer audience
226
+ and causation, and bind Objective and Work Item revisions, accepted assignment
227
+ IDs, epoch, authority token and lease expiry. Each record has a stable domain
228
+ ID independent of the envelope message ID.
229
+
230
+ | Field | Rule |
231
+ | ------------------ | ----------------------------------------------------------------------------------------------- |
232
+ | Owner epoch | Positive safe integer; frozen at `1` for this protocol slice |
233
+ | Assignment binding | Positive epoch; `assignmentAuthorityId` and `fencingToken` must be identical identifiers |
234
+ | Progress | Positive sequence and non-empty summary of at most 4,096 UTF-8 bytes; checkpoint ID is optional |
235
+ | Checkpoint | Positive sequence, canonical SHA-256 digest and exactly one summary or reference |
236
+ | Checkpoint parent | Sequence `1` omits a parent; later sequences require a different `previousCheckpointId` |
237
+ | Result | Canonical SHA-256 digest, optional checkpoint ID and exactly one summary or reference |
238
+ | Content | Summaries and references are non-empty and at most 4,096 UTF-8 bytes |
239
+ | Execution expiry | At most five minutes, strictly after `sentAt` and no later than the signed `leaseExpiresAt` |
240
+
241
+ The structural parser does not prove that causation resolves to the matching
242
+ accepted `work.accept`, that the recipient is an authorized owner, observer or
243
+ witness, or that the assignment, epoch, authority, token, lease and checkpoint
244
+ head are current. It also does not enforce progress ordering or result
245
+ uniqueness. Those checks require accepted local state and remain deferred to
246
+ the Mesh runtime reducer boundary.
247
+
248
+ ## Lease Renewal limits
249
+
250
+ Lease Renewal carries the accepted assignment authority plus
251
+ `leaseRenewalId`, `leaseRenewalSequence` and `renewedLeaseExpiresAt`. The
252
+ existing `leaseExpiresAt` is the current lease that limits delivery; the renewed
253
+ timestamp is the proposed successor. Sequence `1` omits
254
+ `previousLeaseRenewalId`; later sequences require a different predecessor ID.
255
+
256
+ The sender self-binds to `assigneePeerId`, the audience is one direct peer, the
257
+ envelope Objective ID equals the payload Objective ID, and causation is
258
+ required. The first accepted renewal resolves causation to `work.accept`; later
259
+ renewals resolve it to the immediately preceding `lease.renew` envelope for
260
+ that recipient. Recipient authorization, exact predecessor and sequence,
261
+ current assignment and lease, Work deadline, Objective duration/count policy,
262
+ terminal state and idempotency remain stateful reducer checks.
263
+
264
+ ## Lease Takeover Proposal limits
265
+
266
+ Lease Takeover Proposal carries the accepted assignment authority and current
267
+ lease expiry plus a stable `takeoverProposalId`. It identifies the self-bound
268
+ `proposerPeerId`, a closed `candidate` or `witness` `proposalAuthority`, the
269
+ different `proposedAssigneePeerId`, and exactly the next declared assignment
270
+ epoch. It does not propose a fencing token; an accepted recovery certificate's
271
+ stable ID becomes that token later.
272
+
273
+ `leaseRenewalSequence` is `0` for the initial accepted lease and omits
274
+ `latestLeaseRenewalId`. Values `1` through `100` require that stable renewal ID.
275
+ Causation resolves to the accepted `work.accept` for sequence `0`, or to the
276
+ latest accepted `lease.renew` envelope for the receiving witness.
277
+
278
+ The parser enforces closed fields, role consistency, direct delivery, mandatory
279
+ causation, Objective equality and the one-minute TTL. It does not establish that
280
+ the lease head is accepted or expired, recovery grace elapsed, the proposer and
281
+ candidate are eligible, the recipient is a configured witness, or the Work Item
282
+ is current and non-terminal. Those checks require accepted local state and a
283
+ trusted receiver clock. A valid proposal records recovery intent only; it does
284
+ not advance the epoch, grant execution authority, change fencing or reserve
285
+ budget.
286
+
287
+ ## Lease Vote limits
288
+
289
+ Lease Vote is an affirmative witness endorsement of one accepted takeover
290
+ proposal. Its closed payload contains a stable `leaseVoteId`, the logical
291
+ `takeoverProposalId`, the self-bound `witnessPeerId` and the Objective ID. It
292
+ does not repeat candidate, Work Item, assignment, lease, epoch or fencing
293
+ fields; those are resolved from the causally accepted proposal so that two
294
+ signed snapshots cannot disagree.
295
+
296
+ The audience is one direct peer, the envelope Objective ID equals the payload
297
+ Objective ID, causation is required and TTL is at most one minute. The parser
298
+ does not establish that causation names the matching accepted proposal, the
299
+ sender belongs to its fixed witness set, the recipient is a recovery
300
+ participant, or the witness has not already endorsed another proposal for the
301
+ same Work Item revision and proposed epoch. Those are stateful reducer checks.
302
+ A vote alone does not advance an epoch, change fencing, grant execution
303
+ authority, activate a candidate or mutate budget.
304
+
305
+ ## Lease Certificate limits
306
+
307
+ Lease Certificate references one accepted takeover proposal and the witness
308
+ votes that certify it. Its closed payload contains a stable `certificateId`,
309
+ the self-bound `certificateAssemblerPeerId`, `takeoverProposalId`, between two
310
+ and 32 sorted unique `leaseVoteIds`, and the Objective ID. It does not repeat
311
+ candidate, Work Item, assignment, lease, epoch or fencing fields; the accepted
312
+ proposal is their canonical source.
313
+
314
+ The audience is one direct peer, the envelope Objective ID equals the payload
315
+ Objective ID, causation names the proposal envelope and TTL is at most one
316
+ minute. The parser does not prove that the proposal or votes are accepted, that
317
+ the votes endorse the same proposal, come from distinct configured witnesses
318
+ or satisfy the Objective threshold, or that the assembler and recipient are
319
+ authorized. Those are stateful reducer checks.
320
+
321
+ After stateful acceptance, `certificateId` becomes the next assignment
322
+ authority ID and fencing token, and the Work Item enters recovery. The
323
+ certificate does not itself grant execution authority or activate the
324
+ candidate; that requires the existing owner-issued recovery award and
325
+ acceptance flow.
326
+
34
327
  Importing the package performs no parsing, key resolution, network or storage
35
328
  operation.
@@ -47,6 +47,20 @@ export interface PeerHelloPayload {
47
47
  readonly peerCardId: string;
48
48
  readonly cardRevision: number;
49
49
  }
50
+ /** Publishes one bounded revision of a peer's discovery card. */
51
+ export interface PeerCardPayload {
52
+ readonly type: 'peer.card';
53
+ readonly peerCardId: string;
54
+ readonly cardRevision: number;
55
+ readonly subjectPeerId: string;
56
+ readonly instanceId: string;
57
+ readonly protocolVersions: readonly number[];
58
+ readonly transportHints: readonly string[];
59
+ readonly capabilityIds: readonly string[];
60
+ readonly validFrom: string;
61
+ readonly validUntil: string;
62
+ readonly previousPeerCardId?: string;
63
+ }
50
64
  /** Requests a direct liveness response from the audience peer. */
51
65
  export interface PeerPingPayload {
52
66
  readonly type: 'peer.ping';
@@ -55,8 +69,327 @@ export interface PeerPingPayload {
55
69
  export interface PeerPingAckPayload {
56
70
  readonly type: 'peer.ping_ack';
57
71
  }
58
- /** Payload subset implemented by the Alpha 1 vertical slice. */
59
- export type MeshMessagePayload = PeerHelloPayload | PeerPingPayload | PeerPingAckPayload;
72
+ /** Retires the sender's current peer card and process instance. */
73
+ export interface PeerGoodbyePayload {
74
+ readonly type: 'peer.goodbye';
75
+ readonly peerCardId: string;
76
+ readonly cardRevision: number;
77
+ readonly instanceId: string;
78
+ }
79
+ /** Publishes one bounded revision of a peer-owned capability. */
80
+ export interface CapabilityAdvertisePayload {
81
+ readonly type: 'capability.advertise';
82
+ readonly advertisementId: string;
83
+ readonly capabilityId: string;
84
+ readonly capabilityRevision: number;
85
+ readonly ownerPeerId: string;
86
+ readonly capabilityKey: string;
87
+ readonly version: string;
88
+ readonly variant?: string;
89
+ readonly inputMediaTypes: readonly string[];
90
+ readonly outputMediaTypes: readonly string[];
91
+ readonly attributes: Readonly<Record<string, string>>;
92
+ readonly validFrom: string;
93
+ readonly validUntil: string;
94
+ readonly maximumConcurrency?: number;
95
+ readonly maximumPayloadBytes?: number;
96
+ readonly previousAdvertisementId?: string;
97
+ }
98
+ /** Withdraws one specific advertised revision of a capability. */
99
+ export interface CapabilityWithdrawPayload {
100
+ readonly type: 'capability.withdraw';
101
+ readonly capabilityId: string;
102
+ readonly capabilityRevision: number;
103
+ readonly advertisementId: string;
104
+ }
105
+ /** Fields shared by complete Objective announcement and revision documents. */
106
+ export interface ObjectiveDocumentFields {
107
+ readonly objectiveDocumentId: string;
108
+ readonly objectiveId: string;
109
+ readonly objectiveRevision: number;
110
+ readonly issuerPeerId: string;
111
+ readonly successCriteria: readonly string[];
112
+ readonly permittedCapabilityKeys: readonly string[];
113
+ readonly maximumWorkItems: number;
114
+ readonly maximumConcurrentAssignments: number;
115
+ readonly maximumBudgetUnits: number;
116
+ readonly bidWindowMs: number;
117
+ readonly acceptanceWindowMs: number;
118
+ readonly maximumLeaseDurationMs: number;
119
+ readonly recoveryGraceMs: number;
120
+ readonly maximumLeaseRenewals: number;
121
+ readonly recoveryWitnessPeerIds: readonly string[];
122
+ readonly recoveryWitnessThreshold: number;
123
+ readonly validFrom: string;
124
+ readonly validUntil: string;
125
+ readonly authorizedObserverPeerIds?: readonly string[];
126
+ }
127
+ /** Exactly one inline summary or external content reference. */
128
+ export type ObjectiveDocumentContent = {
129
+ readonly summary: string;
130
+ readonly contentReference?: never;
131
+ } | {
132
+ readonly summary?: never;
133
+ readonly contentReference: string;
134
+ };
135
+ /** Complete first revision of an objective issued to the mesh. */
136
+ export type ObjectiveAnnouncePayload = ObjectiveDocumentFields & ObjectiveDocumentContent & {
137
+ readonly type: 'objective.announce';
138
+ };
139
+ /** Complete replacement revision of an existing objective document. */
140
+ export type ObjectiveRevisePayload = ObjectiveDocumentFields & ObjectiveDocumentContent & {
141
+ readonly type: 'objective.revise';
142
+ readonly previousObjectiveDocumentId: string;
143
+ };
144
+ /** Cancels one specific objective document revision. */
145
+ export interface ObjectiveCancelPayload {
146
+ readonly type: 'objective.cancel';
147
+ readonly cancellationId: string;
148
+ readonly objectiveId: string;
149
+ readonly objectiveRevision: number;
150
+ readonly objectiveDocumentId: string;
151
+ }
152
+ /** Fields shared by every complete work offer. */
153
+ export interface WorkOfferFields {
154
+ readonly offerId: string;
155
+ readonly objectiveId: string;
156
+ readonly objectiveDocumentId: string;
157
+ readonly objectiveRevision: number;
158
+ readonly workItemId: string;
159
+ readonly workItemRevision: number;
160
+ readonly ownerPeerId: string;
161
+ readonly ownerEpoch: number;
162
+ readonly offerAttempt: number;
163
+ readonly previousOfferId?: string;
164
+ readonly requiredCapabilityKeys: readonly string[];
165
+ readonly matchingAttributes: Readonly<Record<string, string>>;
166
+ readonly completionCriteria: readonly string[];
167
+ readonly budgetReservationUnits: number;
168
+ readonly bidDeadline: string;
169
+ readonly workDeadline: string;
170
+ }
171
+ /** Exactly one inline work input summary or external content reference. */
172
+ export type WorkOfferInput = {
173
+ readonly inputSummary: string;
174
+ readonly inputReference?: never;
175
+ } | {
176
+ readonly inputSummary?: never;
177
+ readonly inputReference: string;
178
+ };
179
+ /** Offers one bounded work item for capability-based bidding. */
180
+ export type WorkOfferPayload = WorkOfferFields & WorkOfferInput & {
181
+ readonly type: 'work.offer';
182
+ };
183
+ /** Proposes one capacity and budget reservation for an accepted work offer. */
184
+ export interface WorkBidPayload {
185
+ readonly type: 'work.bid';
186
+ readonly bidId: string;
187
+ readonly bidRevision: number;
188
+ readonly previousBidId?: string;
189
+ readonly offerId: string;
190
+ readonly objectiveId: string;
191
+ readonly objectiveDocumentId: string;
192
+ readonly objectiveRevision: number;
193
+ readonly workItemId: string;
194
+ readonly workItemRevision: number;
195
+ readonly ownerPeerId: string;
196
+ readonly ownerEpoch: number;
197
+ readonly offerAttempt: number;
198
+ readonly bidderPeerId: string;
199
+ readonly advertisementId: string;
200
+ readonly capabilityId: string;
201
+ readonly capabilityRevision: number;
202
+ readonly capacityReservationUnits: number;
203
+ readonly budgetUnits: number;
204
+ readonly bidDeadline: string;
205
+ readonly workDeadline: string;
206
+ readonly expectedCompletionAt: string;
207
+ readonly bidExpiresAt: string;
208
+ readonly assumptions: readonly string[];
209
+ }
210
+ /** Fields common to both fresh awards and recovery-certified assignments. */
211
+ export interface WorkAwardFields {
212
+ readonly type: 'work.award';
213
+ readonly awardId: string;
214
+ readonly offerId: string;
215
+ readonly bidId: string;
216
+ readonly bidRevision: number;
217
+ readonly objectiveId: string;
218
+ readonly objectiveDocumentId: string;
219
+ readonly objectiveRevision: number;
220
+ readonly workItemId: string;
221
+ readonly workItemRevision: number;
222
+ readonly ownerPeerId: string;
223
+ readonly ownerEpoch: number;
224
+ readonly offerAttempt: number;
225
+ readonly assigneePeerId: string;
226
+ readonly assignmentEpoch: number;
227
+ readonly assignmentAuthorityId: string;
228
+ readonly fencingToken: string;
229
+ readonly budgetReservationUnits: number;
230
+ readonly workDeadline: string;
231
+ readonly leaseStartsAt: string;
232
+ readonly leaseExpiresAt: string;
233
+ readonly acceptanceDeadline: string;
234
+ }
235
+ /** Assigns work under either the original award or recovery authority. */
236
+ export type WorkAwardPayload = (WorkAwardFields & {
237
+ readonly authorityKind: 'award';
238
+ readonly recoveryCertificateId?: never;
239
+ readonly resumeCheckpointId?: never;
240
+ }) | (WorkAwardFields & {
241
+ readonly authorityKind: 'recovery_certificate';
242
+ readonly recoveryCertificateId: string;
243
+ readonly resumeCheckpointId?: string;
244
+ });
245
+ /** Fields echoed by an assignee when responding to one assignment. */
246
+ export interface WorkAssignmentResponseFields {
247
+ readonly awardId: string;
248
+ readonly objectiveId: string;
249
+ readonly objectiveDocumentId: string;
250
+ readonly objectiveRevision: number;
251
+ readonly workItemId: string;
252
+ readonly workItemRevision: number;
253
+ readonly ownerPeerId: string;
254
+ readonly ownerEpoch: number;
255
+ readonly assigneePeerId: string;
256
+ readonly assignmentEpoch: number;
257
+ readonly assignmentAuthorityId: string;
258
+ readonly fencingToken: string;
259
+ readonly acceptanceDeadline: string;
260
+ }
261
+ /** Accepts one assignment before its bounded response deadline. */
262
+ export interface WorkAcceptPayload extends WorkAssignmentResponseFields {
263
+ readonly type: 'work.accept';
264
+ readonly acceptanceId: string;
265
+ }
266
+ /** Declines one assignment before its bounded response deadline. */
267
+ export interface WorkDeclinePayload extends WorkAssignmentResponseFields {
268
+ readonly type: 'work.decline';
269
+ readonly declineId: string;
270
+ }
271
+ /** Assignment authority echoed by every assignment lifecycle record. */
272
+ export interface WorkAssignmentAuthorityFields {
273
+ readonly objectiveId: string;
274
+ readonly objectiveDocumentId: string;
275
+ readonly objectiveRevision: number;
276
+ readonly workItemId: string;
277
+ readonly workItemRevision: number;
278
+ readonly ownerPeerId: string;
279
+ readonly ownerEpoch: number;
280
+ readonly assigneePeerId: string;
281
+ readonly awardId: string;
282
+ readonly assignmentEpoch: number;
283
+ readonly assignmentAuthorityId: string;
284
+ readonly fencingToken: string;
285
+ readonly leaseExpiresAt: string;
286
+ }
287
+ /** Accepted assignment authority echoed by every execution record. */
288
+ export interface WorkExecutionAuthorityFields extends WorkAssignmentAuthorityFields {
289
+ readonly acceptanceId: string;
290
+ }
291
+ /** Reports bounded incremental progress under one accepted assignment. */
292
+ export interface WorkProgressPayload extends WorkExecutionAuthorityFields {
293
+ readonly type: 'work.progress';
294
+ readonly progressId: string;
295
+ readonly progressSequence: number;
296
+ readonly progressSummary: string;
297
+ readonly checkpointId?: string;
298
+ }
299
+ /** Exactly one inline checkpoint summary or external content reference. */
300
+ export type WorkCheckpointContent = {
301
+ readonly checkpointSummary: string;
302
+ readonly checkpointReference?: never;
303
+ } | {
304
+ readonly checkpointSummary?: never;
305
+ readonly checkpointReference: string;
306
+ };
307
+ /** Persists a content-addressed checkpoint under one accepted assignment. */
308
+ export type WorkCheckpointPayload = WorkExecutionAuthorityFields & WorkCheckpointContent & {
309
+ readonly type: 'work.checkpoint';
310
+ readonly checkpointId: string;
311
+ readonly checkpointSequence: number;
312
+ readonly previousCheckpointId?: string;
313
+ readonly checkpointDigest: string;
314
+ };
315
+ /** Exactly one inline result summary or external content reference. */
316
+ export type WorkResultContent = {
317
+ readonly resultSummary: string;
318
+ readonly resultReference?: never;
319
+ } | {
320
+ readonly resultSummary?: never;
321
+ readonly resultReference: string;
322
+ };
323
+ /** Publishes a content-addressed result under one accepted assignment. */
324
+ export type WorkResultPayload = WorkExecutionAuthorityFields & WorkResultContent & {
325
+ readonly type: 'work.result';
326
+ readonly resultId: string;
327
+ readonly resultDigest: string;
328
+ readonly checkpointId?: string;
329
+ };
330
+ /** Releases an active assignment under owner or assignee authority. */
331
+ export interface WorkReleasePayload extends WorkExecutionAuthorityFields {
332
+ readonly type: 'work.release';
333
+ readonly releaseId: string;
334
+ readonly releaseAuthority: 'owner' | 'assignee';
335
+ readonly releaseDisposition: 'reoffer' | 'close';
336
+ }
337
+ /** Cancels either a pending award or an active accepted assignment. */
338
+ export type WorkCancelPayload = WorkAssignmentAuthorityFields & {
339
+ readonly type: 'work.cancel';
340
+ readonly cancellationId: string;
341
+ } & ({
342
+ readonly assignmentState: 'award_pending';
343
+ readonly acceptanceId?: never;
344
+ } | {
345
+ readonly assignmentState: 'active';
346
+ readonly acceptanceId: string;
347
+ });
348
+ /** Extends one accepted assignment lease without changing its authority. */
349
+ export interface LeaseRenewPayload extends WorkExecutionAuthorityFields {
350
+ readonly type: 'lease.renew';
351
+ readonly leaseRenewalId: string;
352
+ readonly leaseRenewalSequence: number;
353
+ readonly previousLeaseRenewalId?: string;
354
+ readonly renewedLeaseExpiresAt: string;
355
+ }
356
+ /** Assignment and lease snapshot shared by candidate and witness proposals. */
357
+ export interface LeaseTakeoverProposalFields extends WorkExecutionAuthorityFields {
358
+ readonly type: 'lease.takeover_proposal';
359
+ readonly takeoverProposalId: string;
360
+ readonly proposerPeerId: string;
361
+ readonly proposedAssigneePeerId: string;
362
+ readonly proposedAssignmentEpoch: number;
363
+ readonly leaseRenewalSequence: number;
364
+ readonly latestLeaseRenewalId?: string;
365
+ }
366
+ /** Proposes the next assignment epoch after one accepted lease expires. */
367
+ export type LeaseTakeoverProposalPayload = LeaseTakeoverProposalFields & ({
368
+ readonly proposalAuthority: 'candidate';
369
+ readonly candidateConsentProposalId?: never;
370
+ } | {
371
+ readonly proposalAuthority: 'witness';
372
+ readonly candidateConsentProposalId: string;
373
+ });
374
+ /** Endorses one accepted takeover proposal under configured witness authority. */
375
+ export interface LeaseVotePayload {
376
+ readonly type: 'lease.vote';
377
+ readonly leaseVoteId: string;
378
+ readonly takeoverProposalId: string;
379
+ readonly witnessPeerId: string;
380
+ readonly objectiveId: string;
381
+ }
382
+ /** Certifies one takeover proposal from a bounded set of witness votes. */
383
+ export interface LeaseCertificatePayload {
384
+ readonly type: 'lease.certificate';
385
+ readonly certificateId: string;
386
+ readonly certificateAssemblerPeerId: string;
387
+ readonly takeoverProposalId: string;
388
+ readonly leaseVoteIds: readonly string[];
389
+ readonly objectiveId: string;
390
+ }
391
+ /** Structurally implemented protocol payload subset. */
392
+ export type MeshMessagePayload = PeerHelloPayload | PeerCardPayload | PeerPingPayload | PeerPingAckPayload | PeerGoodbyePayload | CapabilityAdvertisePayload | CapabilityWithdrawPayload | ObjectiveAnnouncePayload | ObjectiveRevisePayload | ObjectiveCancelPayload | WorkOfferPayload | WorkBidPayload | WorkAwardPayload | WorkAcceptPayload | WorkDeclinePayload | WorkProgressPayload | WorkCheckpointPayload | WorkResultPayload | WorkReleasePayload | WorkCancelPayload | LeaseRenewPayload | LeaseTakeoverProposalPayload | LeaseVotePayload | LeaseCertificatePayload;
60
393
  /** Shared fields that participate in envelope identity and signing. */
61
394
  export interface MeshEnvelopeHeader<TPayload extends MeshMessagePayload = MeshMessagePayload> {
62
395
  readonly protocol: typeof MESH_PROTOCOL;