Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ dist/*
!dist/*.mjs
*.log
.DS_Store
package-lock.json
progress.md
128 changes: 128 additions & 0 deletions broker/authorization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import assert from "node:assert/strict";
import test from "node:test";
import { authorizeSessionAction, visibleSessions } from "./authorization.ts";
import type { SessionInfo } from "../types.ts";
import {
BOSS_CAPABILITY_FEATURE_DIGEST,
BOSS_PARTICIPANT_BINDING_VERSION,
BOSS_POLICY_PRINCIPAL_VERSION,
BOSS_POLICY_SEMANTICS_HASH,
BOSS_RUN_FEATURE_CONTRACT,
type BossPolicyRole,
} from "@dataforxyz/agent-intercom-core/boss";
import { brokerGeneration, participantBindingEpoch } from "@dataforxyz/agent-intercom-core/canonical";

function local(id: string): SessionInfo {
return { id, name: id, cwd: "/tmp", model: "test", pid: 1, startedAt: 1, lastActivity: 1, origin: "local" };
Expand Down Expand Up @@ -32,6 +41,70 @@ const sessions = [
remote("child-b", "manager"),
];

function bossSession(
id: string,
role: BossPolicyRole,
bossRunId: string,
options: { managerId?: string; assignedIds?: string[] } = {},
): SessionInfo {
const bindingEpoch = participantBindingEpoch(1);
const participantId = `participant-${id}`;
const assignedManagerParticipantId = options.managerId === undefined ? undefined : `participant-${options.managerId}`;
const assignedParticipantIds = options.assignedIds?.map((assignedId) => `participant-${assignedId}`);
const principal = {
version: BOSS_POLICY_PRINCIPAL_VERSION,
principalId: id,
principalClass: "boss-private" as const,
state: "active" as const,
bossRunId,
participantId,
role,
bindingEpoch,
...(assignedManagerParticipantId === undefined ? {} : { assignedManagerParticipantId }),
...(assignedParticipantIds === undefined ? {} : { assignedParticipantIds }),
};
const binding = role === "controller" ? undefined : {
version: BOSS_PARTICIPANT_BINDING_VERSION,
bossRunId,
participantId,
role,
communicationProfile: role,
bindingEpoch,
sessionId: id,
brokerGeneration: brokerGeneration(1),
brokerBootInstance: "boot-1",
state: "active" as const,
...(assignedManagerParticipantId === undefined ? {} : { assignedManagerParticipantId }),
authorityTransitionId: `transition-${id}`,
};
return {
id,
name: id,
cwd: "/tmp",
model: "test",
pid: 3,
startedAt: 1,
lastActivity: 1,
origin: "local",
boss: {
registration: {
principalId: id,
principalClass: "boss-bound",
state: "active",
bossRunId,
participantId,
bindingEpoch,
featureContract: BOSS_RUN_FEATURE_CONTRACT,
policySemanticsHash: BOSS_POLICY_SEMANTICS_HASH,
capabilityDigest: BOSS_CAPABILITY_FEATURE_DIGEST,
brokerIdentityVerified: true,
},
principal,
...(binding === undefined ? {} : { binding }),
},
};
}

test("phase one discovery and communication use the same ancestor-chain policy", () => {
assert.equal(authorizeSessionAction(sessions, "root", "send", "manager").allowed, true);
assert.equal(authorizeSessionAction(sessions, "manager", "ask", "root").allowed, true);
Expand All @@ -47,3 +120,58 @@ test("visibility hides unauthorized sessions rather than revealing denial detail
assert.deepEqual(visibleSessions(sessions, "root").map((session) => session.id).sort(), ["child-a", "child-b", "manager", "root", "unrelated"]);
assert.deepEqual(visibleSessions(sessions, "unrelated").map((session) => session.id).sort(), ["root", "unrelated"]);
});

test("Boss discovery is run-scoped and never downgrades into ordinary local-public routing", () => {
const mixed = [
local("ordinary"),
bossSession("manager-a", "manager", "run-a", { assignedIds: ["worker-a"] }),
bossSession("worker-a", "worker", "run-a", { managerId: "manager-a" }),
bossSession("manager-b", "manager", "run-b", { assignedIds: [] }),
];

assert.deepEqual(authorizeSessionAction(mixed, "manager-a", "discover", "worker-a"), {
allowed: true,
reason: "communication-profile",
});
assert.deepEqual(authorizeSessionAction(mixed, "manager-a", "send", "manager-b"), {
allowed: false,
code: "CROSS_RUN_DENIED",
});
assert.deepEqual(authorizeSessionAction(mixed, "ordinary", "send", "manager-a"), {
allowed: false,
code: "FEATURE_CLASS_DENIED",
});
assert.deepEqual(visibleSessions(mixed, "manager-a").map((session) => session.id).sort(), ["manager-a", "worker-a"]);
});

test("Boss typed control uses the directional Core matrix and exact binding epochs", () => {
const run = [
bossSession("manager", "manager", "run-a", { assignedIds: ["worker"] }),
bossSession("worker", "worker", "run-a", { managerId: "manager" }),
];
assert.deepEqual(authorizeSessionAction(run, "manager", "control", "worker", {
actorBindingEpoch: participantBindingEpoch(1),
targetBindingEpoch: participantBindingEpoch(1),
controlKind: "assignment_request",
correlated: true,
}), { allowed: true, reason: "structured-control" });
assert.deepEqual(authorizeSessionAction(run, "manager", "control", "worker", {
actorBindingEpoch: participantBindingEpoch(1),
targetBindingEpoch: participantBindingEpoch(1),
controlKind: "decision",
correlated: true,
}), { allowed: false, code: "CONTROL_KIND_DENIED" });
assert.deepEqual(authorizeSessionAction(run, "manager", "control", "worker", {
actorBindingEpoch: participantBindingEpoch(1),
targetBindingEpoch: participantBindingEpoch(1),
controlKind: "assignment_request",
correlated: false,
}), { allowed: false, code: "CONTROL_REQUIRES_CORRELATION" });
});

test("invalid Boss metadata fails closed instead of becoming an ordinary session", () => {
const corrupt = bossSession("worker", "worker", "run-a", { managerId: "manager" });
corrupt.boss!.registration.brokerIdentityVerified = false;
const manager = bossSession("manager", "manager", "run-a", { assignedIds: ["worker"] });
assert.equal(authorizeSessionAction([manager, corrupt], "manager", "discover", "worker").allowed, false);
});
73 changes: 62 additions & 11 deletions broker/authorization.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { authorize, type AuthorizationDecision, type PolicyAction, type PolicyPrincipal, type PolicyState } from "@dataforxyz/agent-intercom-core";
import {
authorizeFeatureAware,
type BossAuthorizationContext,
type BossPolicyAction,
type FeatureAwareAuthorizationDecision,
type FeatureAwarePolicyState,
} from "@dataforxyz/agent-intercom-core/boss";
import type { PolicyAction, PolicyPrincipal, PolicyState } from "@dataforxyz/agent-intercom-core/policy";
import { validatedBossMetadata } from "./boss.ts";
import type { SessionInfo } from "../types.ts";

export function policyPrincipalForSession(session: SessionInfo): PolicyPrincipal {
Expand Down Expand Up @@ -28,23 +36,66 @@ export function policyPrincipalForSession(session: SessionInfo): PolicyPrincipal

export function policyStateForSessions(sessions: Iterable<SessionInfo>): PolicyState {
const principals: Record<string, PolicyPrincipal> = {};
for (const session of sessions) principals[session.id] = policyPrincipalForSession(session);
for (const session of sessions) {
if (session.boss === undefined) principals[session.id] = policyPrincipalForSession(session);
}
return { principals };
}

export function featurePolicyStateForSessions(sessions: Iterable<SessionInfo>): FeatureAwarePolicyState {
const values = Array.from(sessions);
const legacy = policyStateForSessions(values);
const registrations: FeatureAwarePolicyState["registrations"] = {};
const boss: FeatureAwarePolicyState["boss"] = { principals: {} };

for (const session of values) {
let metadata;
try {
metadata = validatedBossMetadata(session);
} catch {
// Boss-marked metadata is broker-owned. Corruption must stay in the
// Boss namespace and fail closed rather than downgrade to ordinary.
registrations[session.id] = {} as FeatureAwarePolicyState["registrations"][string];
continue;
}
if (metadata) {
registrations[session.id] = metadata.registration;
boss.principals[session.id] = metadata.principal;
} else {
registrations[session.id] = {
principalId: session.id,
principalClass: "ordinary",
state: "active",
};
}
}
return { legacy, boss, registrations };
}

export function authorizeSessionAction(
sessions: Iterable<SessionInfo>,
actorId: string,
action: PolicyAction,
action: PolicyAction | BossPolicyAction,
targetId: string,
): AuthorizationDecision {
const state = policyStateForSessions(sessions);
const actor = state.principals[actorId];
const target = state.principals[targetId];
return authorize(state, actorId, action, targetId, {
actorGeneration: actor?.generation,
targetGeneration: target?.generation,
});
bossContext?: BossAuthorizationContext,
): FeatureAwareAuthorizationDecision {
const state = featurePolicyStateForSessions(sessions);
const actorRegistration = state.registrations[actorId];
const targetRegistration = state.registrations[targetId];
const request = {
actorId,
action,
targetId,
...(actorRegistration?.principalClass === "boss-bound" || targetRegistration?.principalClass === "boss-bound"
? { bossContext }
: {
legacyContext: {
actorGeneration: state.legacy.principals[actorId]?.generation,
targetGeneration: state.legacy.principals[targetId]?.generation,
},
}),
};
return authorizeFeatureAware(state, request);
}

export function visibleSessions(sessions: Iterable<SessionInfo>, actorId: string): SessionInfo[] {
Expand Down
Loading
Loading