@ctliz/agent-intercom-pi 0.11.0-connect.2
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/COPYRIGHT +6 -0
- package/LICENSE +661 -0
- package/LICENSE_TRANSITION.md +26 -0
- package/README.md +693 -0
- package/THIRD_PARTY_NOTICES.md +17 -0
- package/banner.png +0 -0
- package/boss-team-scope.ts +241 -0
- package/broker/access-credential.ts +76 -0
- package/broker/access-registry.ts +460 -0
- package/broker/audit.ts +60 -0
- package/broker/authorization.ts +140 -0
- package/broker/boss-adapter.ts +383 -0
- package/broker/broker-impl.ts +2019 -0
- package/broker/broker.ts +7 -0
- package/broker/client.ts +932 -0
- package/broker/framing.ts +87 -0
- package/broker/ownership.ts +61 -0
- package/broker/paths.ts +161 -0
- package/broker/protected-service.ts +158 -0
- package/broker/registration.ts +173 -0
- package/broker/spawn.ts +448 -0
- package/config.ts +183 -0
- package/control.ts +150 -0
- package/durable-json.ts +25 -0
- package/inbound-inbox.ts +296 -0
- package/index.ts +2826 -0
- package/licenses/MIT-pi-intercom.txt +21 -0
- package/outbound-outbox.ts +116 -0
- package/package.json +72 -0
- package/protocol-v4/contract.ts +39 -0
- package/provider/provider.mjs +34 -0
- package/reply-tracker.ts +231 -0
- package/skills/pi-intercom/SKILL.md +537 -0
- package/team.ts +192 -0
- package/types.ts +183 -0
- package/ui/compose.ts +229 -0
- package/ui/inline-message.ts +126 -0
- package/ui/session-identity.ts +55 -0
- package/ui/session-list.ts +205 -0
- package/ui/timestamps.ts +50 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { types as nodeUtilTypes } from "node:util";
|
|
2
|
+
import {
|
|
3
|
+
BOSS_CAPABILITY_FEATURE_DIGEST,
|
|
4
|
+
BOSS_CONTROL_ENVELOPE_VERSION,
|
|
5
|
+
BOSS_POLICY_SEMANTICS_HASH,
|
|
6
|
+
BOSS_RUN_FEATURE,
|
|
7
|
+
BOSS_RUN_FEATURE_CONTRACT,
|
|
8
|
+
BOSS_RUN_FEATURE_SEMANTICS_HASH,
|
|
9
|
+
BOSS_RUN_FEATURE_VERSION,
|
|
10
|
+
BOSS_RUN_PROTOCOL_FEATURE_CONTRACT_HASH,
|
|
11
|
+
BROKER_FEATURE_ATTESTATION_VERSION,
|
|
12
|
+
INTERCOM_BASE_PROTOCOL_VERSION,
|
|
13
|
+
brokerFeatureSetHash,
|
|
14
|
+
evaluateBrokerCompatibility,
|
|
15
|
+
parseBossControlEnvelope,
|
|
16
|
+
parseBossParticipantBinding,
|
|
17
|
+
parseBossParticipantCredentialEnvelope,
|
|
18
|
+
parseBossRunFeatureContract,
|
|
19
|
+
parseBrokerCapabilityAdvertisement,
|
|
20
|
+
type BossControlEnvelope,
|
|
21
|
+
type BossFeatureRegistration,
|
|
22
|
+
type BossParticipantBinding,
|
|
23
|
+
type BossParticipantCredentialEnvelope,
|
|
24
|
+
type BossRunFeatureContract,
|
|
25
|
+
type BrokerCapabilityAdvertisement,
|
|
26
|
+
} from "@ctliz/agent-intercom-core/boss";
|
|
27
|
+
import {
|
|
28
|
+
parseBossPolicyPrincipal,
|
|
29
|
+
type BossAuthorizationContext,
|
|
30
|
+
type BossControlKind,
|
|
31
|
+
type BossPrivatePrincipal,
|
|
32
|
+
} from "@ctliz/agent-intercom-core/boss/policy";
|
|
33
|
+
import {
|
|
34
|
+
assertExactKeys,
|
|
35
|
+
assertRecord,
|
|
36
|
+
canonicalJson,
|
|
37
|
+
ContractValidationError,
|
|
38
|
+
readHexDigest,
|
|
39
|
+
} from "@ctliz/agent-intercom-core/canonical";
|
|
40
|
+
|
|
41
|
+
/** Gates which must all be implemented before Pi may advertise boss-run-v1. */
|
|
42
|
+
export interface BossReadinessPredicates {
|
|
43
|
+
providerAttested: boolean;
|
|
44
|
+
brokerIdentityVerified: boolean;
|
|
45
|
+
credentialsAuthoritative: boolean;
|
|
46
|
+
authorityTransitionsDurable: boolean;
|
|
47
|
+
participantHealthIntegrated: boolean;
|
|
48
|
+
recipientIngressIntegrated: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const BOSS_READINESS_PREDICATE_KEYS = [
|
|
52
|
+
"providerAttested",
|
|
53
|
+
"brokerIdentityVerified",
|
|
54
|
+
"credentialsAuthoritative",
|
|
55
|
+
"authorityTransitionsDurable",
|
|
56
|
+
"participantHealthIntegrated",
|
|
57
|
+
"recipientIngressIntegrated",
|
|
58
|
+
] as const satisfies ReadonlyArray<keyof BossReadinessPredicates>;
|
|
59
|
+
|
|
60
|
+
function assertNoProxyGraph(value: unknown, path: string): void {
|
|
61
|
+
const seen = new WeakSet<object>();
|
|
62
|
+
const visit = (candidate: unknown, candidatePath: string): void => {
|
|
63
|
+
if (typeof candidate !== "object" || candidate === null) return;
|
|
64
|
+
if (nodeUtilTypes.isProxy(candidate)) {
|
|
65
|
+
throw new ContractValidationError(candidatePath, "proxies are not supported");
|
|
66
|
+
}
|
|
67
|
+
if (seen.has(candidate)) return;
|
|
68
|
+
seen.add(candidate);
|
|
69
|
+
for (const key of Reflect.ownKeys(candidate)) {
|
|
70
|
+
const descriptor = Object.getOwnPropertyDescriptor(candidate, key);
|
|
71
|
+
if (descriptor && Object.hasOwn(descriptor, "value")) {
|
|
72
|
+
visit(descriptor.value, `${candidatePath}.${typeof key === "symbol" ? String(key) : key}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
visit(value, path);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseBossReadinessPredicates(value: unknown): BossReadinessPredicates {
|
|
80
|
+
if (
|
|
81
|
+
typeof value !== "object"
|
|
82
|
+
|| value === null
|
|
83
|
+
|| nodeUtilTypes.isProxy(value)
|
|
84
|
+
|| Array.isArray(value)
|
|
85
|
+
|| Object.getPrototypeOf(value) !== Object.prototype
|
|
86
|
+
) {
|
|
87
|
+
throw new ContractValidationError("$.readiness", "must be a non-proxy plain object");
|
|
88
|
+
}
|
|
89
|
+
if (
|
|
90
|
+
Object.getOwnPropertyNames(value).length !== BOSS_READINESS_PREDICATE_KEYS.length
|
|
91
|
+
|| Object.getOwnPropertySymbols(value).length !== 0
|
|
92
|
+
) {
|
|
93
|
+
throw new ContractValidationError("$.readiness", "must contain exactly the six readiness predicates");
|
|
94
|
+
}
|
|
95
|
+
for (const key of BOSS_READINESS_PREDICATE_KEYS) {
|
|
96
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
97
|
+
if (
|
|
98
|
+
descriptor === undefined
|
|
99
|
+
|| !descriptor.enumerable
|
|
100
|
+
|| !Object.hasOwn(descriptor, "value")
|
|
101
|
+
|| typeof descriptor.value !== "boolean"
|
|
102
|
+
) {
|
|
103
|
+
throw new ContractValidationError(`$.readiness.${key}`, "must be an own enumerable boolean data property");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return value as BossReadinessPredicates;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const DORMANT_BOSS_READINESS: Readonly<BossReadinessPredicates> = Object.freeze({
|
|
110
|
+
providerAttested: false,
|
|
111
|
+
brokerIdentityVerified: false,
|
|
112
|
+
credentialsAuthoritative: false,
|
|
113
|
+
authorityTransitionsDurable: false,
|
|
114
|
+
participantHealthIntegrated: false,
|
|
115
|
+
recipientIngressIntegrated: false,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const COMPLETE_BOSS_READINESS: Readonly<BossReadinessPredicates> = Object.freeze({
|
|
119
|
+
providerAttested: true,
|
|
120
|
+
brokerIdentityVerified: true,
|
|
121
|
+
credentialsAuthoritative: true,
|
|
122
|
+
authorityTransitionsDurable: true,
|
|
123
|
+
participantHealthIntegrated: true,
|
|
124
|
+
recipientIngressIntegrated: true,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
export function missingBossReadinessPredicates(readiness: BossReadinessPredicates): Array<keyof BossReadinessPredicates> {
|
|
128
|
+
const parsed = parseBossReadinessPredicates(readiness);
|
|
129
|
+
return BOSS_READINESS_PREDICATE_KEYS.filter((predicate) => parsed[predicate] !== true);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function isBossReady(readiness: BossReadinessPredicates): boolean {
|
|
133
|
+
return missingBossReadinessPredicates(readiness).length === 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Untrusted client request. A client never gets to assert its own binding. */
|
|
137
|
+
export interface BossParticipantRegistrationMetadata {
|
|
138
|
+
featureContract: BossRunFeatureContract;
|
|
139
|
+
capabilityDigest: string;
|
|
140
|
+
credential: BossParticipantCredentialEnvelope;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Broker-owned metadata returned only after protected credential binding. */
|
|
144
|
+
export interface BossSessionMetadata {
|
|
145
|
+
binding: BossParticipantBinding;
|
|
146
|
+
principal: BossPrivatePrincipal;
|
|
147
|
+
featureContract: BossRunFeatureContract;
|
|
148
|
+
policySemanticsHash: string;
|
|
149
|
+
capabilityDigest: string;
|
|
150
|
+
brokerIdentityVerified: true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Exact, descriptor-safe projection of an optional Boss registration request. */
|
|
154
|
+
export function parseBossParticipantRegistrationMetadata(value: unknown): BossParticipantRegistrationMetadata {
|
|
155
|
+
assertNoProxyGraph(value, "$.boss");
|
|
156
|
+
assertRecord(value, "$.boss");
|
|
157
|
+
assertExactKeys(value, ["featureContract", "capabilityDigest", "credential"], [], "$.boss");
|
|
158
|
+
const featureContract = parseBossRunFeatureContract(Object.getOwnPropertyDescriptor(value, "featureContract")!.value);
|
|
159
|
+
const capabilityDigest = readHexDigest(
|
|
160
|
+
Object.getOwnPropertyDescriptor(value, "capabilityDigest")!.value,
|
|
161
|
+
"$.boss.capabilityDigest",
|
|
162
|
+
);
|
|
163
|
+
const credential = parseBossParticipantCredentialEnvelope(
|
|
164
|
+
Object.getOwnPropertyDescriptor(value, "credential")!.value,
|
|
165
|
+
);
|
|
166
|
+
if (
|
|
167
|
+
canonicalJson(featureContract) !== canonicalJson(BOSS_RUN_FEATURE_CONTRACT)
|
|
168
|
+
|| capabilityDigest !== BOSS_CAPABILITY_FEATURE_DIGEST
|
|
169
|
+
|| credential.namespace !== BOSS_RUN_FEATURE
|
|
170
|
+
) {
|
|
171
|
+
throw new ContractValidationError("$.boss", "must exactly request boss-run-v1 over base protocol v4");
|
|
172
|
+
}
|
|
173
|
+
return { featureContract, capabilityDigest, credential };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Exact, descriptor-safe parser for broker-owned live-session metadata. */
|
|
177
|
+
export function parseBossSessionMetadata(value: unknown, expectedSessionId?: string): BossSessionMetadata {
|
|
178
|
+
assertNoProxyGraph(value, "$.boss");
|
|
179
|
+
assertRecord(value, "$.boss");
|
|
180
|
+
assertExactKeys(value, [
|
|
181
|
+
"binding",
|
|
182
|
+
"principal",
|
|
183
|
+
"featureContract",
|
|
184
|
+
"policySemanticsHash",
|
|
185
|
+
"capabilityDigest",
|
|
186
|
+
"brokerIdentityVerified",
|
|
187
|
+
], [], "$.boss");
|
|
188
|
+
const binding = parseBossParticipantBinding(Object.getOwnPropertyDescriptor(value, "binding")!.value);
|
|
189
|
+
const parsedPrincipal = parseBossPolicyPrincipal(Object.getOwnPropertyDescriptor(value, "principal")!.value);
|
|
190
|
+
if (parsedPrincipal.principalClass !== "boss-private") {
|
|
191
|
+
throw new ContractValidationError("$.boss.principal", "must be boss-private");
|
|
192
|
+
}
|
|
193
|
+
const principal: BossPrivatePrincipal = parsedPrincipal;
|
|
194
|
+
const featureContract = parseBossRunFeatureContract(Object.getOwnPropertyDescriptor(value, "featureContract")!.value);
|
|
195
|
+
const policySemanticsHash = readHexDigest(
|
|
196
|
+
Object.getOwnPropertyDescriptor(value, "policySemanticsHash")!.value,
|
|
197
|
+
"$.boss.policySemanticsHash",
|
|
198
|
+
);
|
|
199
|
+
const capabilityDigest = readHexDigest(
|
|
200
|
+
Object.getOwnPropertyDescriptor(value, "capabilityDigest")!.value,
|
|
201
|
+
"$.boss.capabilityDigest",
|
|
202
|
+
);
|
|
203
|
+
if (Object.getOwnPropertyDescriptor(value, "brokerIdentityVerified")!.value !== true) {
|
|
204
|
+
throw new ContractValidationError("$.boss.brokerIdentityVerified", "must be true");
|
|
205
|
+
}
|
|
206
|
+
if (expectedSessionId !== undefined && binding.sessionId !== expectedSessionId) {
|
|
207
|
+
throw new ContractValidationError("$.boss.binding.sessionId", "must match the broker session ID");
|
|
208
|
+
}
|
|
209
|
+
if (
|
|
210
|
+
binding.state !== "active"
|
|
211
|
+
|| principal.state !== "active"
|
|
212
|
+
|| binding.sessionId !== principal.principalId
|
|
213
|
+
|| binding.bossRunId !== principal.bossRunId
|
|
214
|
+
|| binding.participantId !== principal.participantId
|
|
215
|
+
|| binding.role !== principal.role
|
|
216
|
+
|| binding.bindingEpoch !== principal.bindingEpoch
|
|
217
|
+
|| binding.assignedManagerParticipantId !== principal.assignedManagerParticipantId
|
|
218
|
+
|| canonicalJson(featureContract) !== canonicalJson(BOSS_RUN_FEATURE_CONTRACT)
|
|
219
|
+
|| policySemanticsHash !== BOSS_POLICY_SEMANTICS_HASH
|
|
220
|
+
|| capabilityDigest !== BOSS_CAPABILITY_FEATURE_DIGEST
|
|
221
|
+
) throw new ContractValidationError("$.boss", "does not describe one active, canonically attested participant");
|
|
222
|
+
return {
|
|
223
|
+
binding,
|
|
224
|
+
principal,
|
|
225
|
+
featureContract,
|
|
226
|
+
policySemanticsHash,
|
|
227
|
+
capabilityDigest,
|
|
228
|
+
brokerIdentityVerified: true,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function brokerCapabilityAdvertisement(
|
|
233
|
+
readiness: BossReadinessPredicates = DORMANT_BOSS_READINESS,
|
|
234
|
+
): BrokerCapabilityAdvertisement {
|
|
235
|
+
if (!isBossReady(readiness)) {
|
|
236
|
+
return parseBrokerCapabilityAdvertisement({
|
|
237
|
+
baseProtocolVersion: INTERCOM_BASE_PROTOCOL_VERSION,
|
|
238
|
+
features: [],
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
const features = [{
|
|
242
|
+
version: BROKER_FEATURE_ATTESTATION_VERSION,
|
|
243
|
+
feature: BOSS_RUN_FEATURE,
|
|
244
|
+
featureVersion: BOSS_RUN_FEATURE_VERSION,
|
|
245
|
+
semanticsHash: BOSS_RUN_FEATURE_SEMANTICS_HASH,
|
|
246
|
+
controlEnvelopeVersion: BOSS_CONTROL_ENVELOPE_VERSION,
|
|
247
|
+
capabilityDigest: BOSS_CAPABILITY_FEATURE_DIGEST,
|
|
248
|
+
}];
|
|
249
|
+
return parseBrokerCapabilityAdvertisement({
|
|
250
|
+
baseProtocolVersion: INTERCOM_BASE_PROTOCOL_VERSION,
|
|
251
|
+
features,
|
|
252
|
+
protocolFeatureContractHash: BOSS_RUN_PROTOCOL_FEATURE_CONTRACT_HASH,
|
|
253
|
+
featureSetHash: brokerFeatureSetHash(features),
|
|
254
|
+
controlEnvelopeVersion: BOSS_CONTROL_ENVELOPE_VERSION,
|
|
255
|
+
capabilityDigest: BOSS_CAPABILITY_FEATURE_DIGEST,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export type BossNegotiationDecision =
|
|
260
|
+
| { accepted: true; featureContract: BossRunFeatureContract }
|
|
261
|
+
| { accepted: false; code: "BOSS_FEATURE_NOT_ADVERTISED" | "BOSS_FEATURE_DIVERGENCE" };
|
|
262
|
+
|
|
263
|
+
/** Exact boss-run-v1/base-protocol-3 negotiation; no legacy downgrade exists. */
|
|
264
|
+
export function negotiateBossRegistration(
|
|
265
|
+
metadataValue: unknown,
|
|
266
|
+
advertisementValue: unknown,
|
|
267
|
+
): BossNegotiationDecision {
|
|
268
|
+
let metadata: BossParticipantRegistrationMetadata;
|
|
269
|
+
let advertisement: BrokerCapabilityAdvertisement;
|
|
270
|
+
try {
|
|
271
|
+
metadata = parseBossParticipantRegistrationMetadata(metadataValue);
|
|
272
|
+
assertNoProxyGraph(advertisementValue, "$.capabilities");
|
|
273
|
+
advertisement = parseBrokerCapabilityAdvertisement(advertisementValue);
|
|
274
|
+
} catch {
|
|
275
|
+
return { accepted: false, code: "BOSS_FEATURE_DIVERGENCE" };
|
|
276
|
+
}
|
|
277
|
+
const ordinaryCompatibility = evaluateBrokerCompatibility({
|
|
278
|
+
clientKind: "ordinary",
|
|
279
|
+
supportedBaseProtocolVersions: [INTERCOM_BASE_PROTOCOL_VERSION],
|
|
280
|
+
}, advertisement);
|
|
281
|
+
if (!ordinaryCompatibility.compatible || ordinaryCompatibility.mode !== "ordinary") {
|
|
282
|
+
return { accepted: false, code: "BOSS_FEATURE_DIVERGENCE" };
|
|
283
|
+
}
|
|
284
|
+
const feature = advertisement.features.find((entry) => entry.feature === BOSS_RUN_FEATURE);
|
|
285
|
+
if (!feature) return { accepted: false, code: "BOSS_FEATURE_NOT_ADVERTISED" };
|
|
286
|
+
if (
|
|
287
|
+
canonicalJson(advertisement) !== canonicalJson(brokerCapabilityAdvertisement(COMPLETE_BOSS_READINESS))
|
|
288
|
+
|| canonicalJson(metadata.featureContract) !== canonicalJson(BOSS_RUN_FEATURE_CONTRACT)
|
|
289
|
+
|| metadata.capabilityDigest !== BOSS_CAPABILITY_FEATURE_DIGEST
|
|
290
|
+
) return { accepted: false, code: "BOSS_FEATURE_DIVERGENCE" };
|
|
291
|
+
return { accepted: true, featureContract: metadata.featureContract };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function bossFeatureRegistration(
|
|
295
|
+
principalId: string,
|
|
296
|
+
metadata: BossSessionMetadata,
|
|
297
|
+
brokerIdentityVerified: boolean,
|
|
298
|
+
): BossFeatureRegistration {
|
|
299
|
+
const parsed = parseBossSessionMetadata(metadata, principalId);
|
|
300
|
+
return {
|
|
301
|
+
principalId,
|
|
302
|
+
principalClass: "boss-bound",
|
|
303
|
+
state: parsed.binding.state,
|
|
304
|
+
bossRunId: parsed.binding.bossRunId,
|
|
305
|
+
participantId: parsed.binding.participantId,
|
|
306
|
+
bindingEpoch: parsed.binding.bindingEpoch,
|
|
307
|
+
featureContract: parsed.featureContract,
|
|
308
|
+
policySemanticsHash: parsed.policySemanticsHash,
|
|
309
|
+
capabilityDigest: parsed.capabilityDigest,
|
|
310
|
+
brokerIdentityVerified,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const BOSS_CONTROL_KIND_BY_TYPE = {
|
|
315
|
+
"boss.assignment.created": "assignment_request",
|
|
316
|
+
"boss.assignment.accepted": "assignment_response",
|
|
317
|
+
"boss.assignment.checkpoint": "assignment_response",
|
|
318
|
+
"boss.assignment.submitted": "assignment_response",
|
|
319
|
+
"boss.assignment.rejected": "assignment_response",
|
|
320
|
+
"boss.assignment.cancelled": "lifecycle",
|
|
321
|
+
"boss.staffing.requested": "staffing",
|
|
322
|
+
"boss.staffing.resolved": "staffing",
|
|
323
|
+
"boss.review.requested": "review_request",
|
|
324
|
+
"boss.review.submitted": "review_result",
|
|
325
|
+
"boss.council.requested": "review_request",
|
|
326
|
+
"boss.council.submitted": "review_result",
|
|
327
|
+
"boss.proof.submitted": "proof",
|
|
328
|
+
"boss.worker.health": "health",
|
|
329
|
+
"boss.worker.blocked": "health",
|
|
330
|
+
"boss.worker.failed": "health",
|
|
331
|
+
"boss.worker.notice": "lifecycle",
|
|
332
|
+
"boss.worker.notice_delivery_failed": "lifecycle",
|
|
333
|
+
"boss.decision.required": "decision",
|
|
334
|
+
} as const satisfies Readonly<Record<BossControlEnvelope["type"], BossControlKind>>;
|
|
335
|
+
|
|
336
|
+
export function bossControlKind(control: BossControlEnvelope): BossControlKind {
|
|
337
|
+
return BOSS_CONTROL_KIND_BY_TYPE[control.type];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function parseBossControl(value: unknown): BossControlEnvelope | null {
|
|
341
|
+
try {
|
|
342
|
+
assertNoProxyGraph(value, "$.control");
|
|
343
|
+
return parseBossControlEnvelope(value);
|
|
344
|
+
} catch {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export interface CorrelatedBossControl {
|
|
350
|
+
envelope: BossControlEnvelope;
|
|
351
|
+
context: BossAuthorizationContext;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function correlateBossControl(
|
|
355
|
+
metadataValue: unknown,
|
|
356
|
+
envelopeValue: unknown,
|
|
357
|
+
transportMessageId: string,
|
|
358
|
+
): CorrelatedBossControl | null {
|
|
359
|
+
try {
|
|
360
|
+
const metadata = parseBossSessionMetadata(metadataValue);
|
|
361
|
+
assertNoProxyGraph(envelopeValue, "$.control");
|
|
362
|
+
const envelope = parseBossControlEnvelope(envelopeValue);
|
|
363
|
+
if (
|
|
364
|
+
envelope.messageId !== transportMessageId
|
|
365
|
+
|| envelope.bossRunId !== metadata.binding.bossRunId
|
|
366
|
+
|| envelope.participantId !== metadata.binding.participantId
|
|
367
|
+
|| envelope.bindingEpoch !== metadata.binding.bindingEpoch
|
|
368
|
+
) return null;
|
|
369
|
+
return {
|
|
370
|
+
envelope,
|
|
371
|
+
context: {
|
|
372
|
+
actorBindingEpoch: metadata.binding.bindingEpoch,
|
|
373
|
+
controlKind: bossControlKind(envelope),
|
|
374
|
+
// Transport/envelope agreement proves identity consistency only. Pi
|
|
375
|
+
// has no assignment/review/lifecycle evidence authority, so it must
|
|
376
|
+
// never manufacture authoritative correlation from these fields.
|
|
377
|
+
correlated: false,
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
} catch {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|