Files
quixos-protocol/src/capability-model/forwarding.ts
T
Timothy J. Aveni 1aa55f7a35 Add composable interface operation forwarding
Support bind member.operation to interface Target<Args>.member.operation.
Check exact signatures and scopes, same-receiver conformances, cycles and
watch pairing. Resolve chains for native queries, editing and dispatch while
retaining the terminal conformance owner and injected package dependencies.
Track forwarded providers in dependency and semantic-major review machinery.

Cover native get/set/watch chains, generic targets, invalid bindings, package
forwarding, runtime owner authority and watch cancellation. Document the
language feature and keep Studio search adoption explicitly pending.
No push or deployment.
2026-09-19 10:18:47 -07:00

37 lines
1.4 KiB
TypeScript

import type {
AtomId,
Binding,
Conformance,
InterfaceRevisionId,
OperationBinding,
OperationId,
WorkspaceRevision,
} from "./types.js";
export type ConcreteBinding = Exclude<Binding, { kind: "interface" }>;
export type ResolvedBinding = { conformance: Conformance; entry: OperationBinding; binding: ConcreteBinding };
/** Follow public operations on the same receiver, never private attachment names. */
export function resolveForwardedBinding(
workspace: Pick<WorkspaceRevision, "conformances">,
atomId: AtomId,
interfaceRevisionId: InterfaceRevisionId,
operationId: OperationId,
): ResolvedBinding {
const visited = new Set<string>();
for (;;) {
const key = `${interfaceRevisionId}\0${operationId}`;
if (visited.has(key)) throw new Error(`Forwarding cycle at ${interfaceRevisionId}/${operationId}`);
visited.add(key);
const conformance = workspace.conformances.find(
(c) => c.atomId === atomId && c.interfaceRevisionId === interfaceRevisionId,
);
const entry = conformance?.operationBindings.find((b) => b.operationId === operationId);
if (!conformance || !entry)
throw new Error(`Missing forwarding target ${atomId} as ${interfaceRevisionId}/${operationId}`);
if (entry.binding.kind !== "interface") return { conformance, entry, binding: entry.binding };
interfaceRevisionId = entry.binding.interfaceRevisionId;
operationId = entry.binding.operationId;
}
}