|
|
|
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
|
|
|
|
import { test } from "node:test";
|
|
|
|
|
import {
|
|
|
|
|
compileWorkspaceRevision,
|
|
|
|
|
capabilityId,
|
|
|
|
|
computeCapabilityClosure,
|
|
|
|
|
resolveOperationPlan,
|
|
|
|
|
validateWorkspaceRevision,
|
|
|
|
@@ -197,6 +198,62 @@ test("public traversal permits a native inverse read without exporting mutation
|
|
|
|
|
expectIssue(workspace, "private-attachment-access");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("public traversal exports only the selected read-only package edge port", () => {
|
|
|
|
|
const workspace = makeValidCapabilityWorkspace();
|
|
|
|
|
const exportDefinition = workspace.packageImports
|
|
|
|
|
.flatMap((pkg) => pkg.exports)
|
|
|
|
|
.find((entry) => entry.id === fixtureId.summaryGetExport)!;
|
|
|
|
|
const port = {
|
|
|
|
|
id: capabilityId.dependencyPort("port:summary:owner"),
|
|
|
|
|
displayName: "owner",
|
|
|
|
|
requirement: {
|
|
|
|
|
kind: "edge" as const,
|
|
|
|
|
target: { kind: "interface" as const, interfaceRevisionId: fixtureId.namedV1 },
|
|
|
|
|
cardinality: "exactly-one" as const,
|
|
|
|
|
primitives: ["resolve" as const],
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
exportDefinition.dependencyPorts.push(port);
|
|
|
|
|
const binding = conformance(workspace, fixtureId.projectSummaryConformance).operationBindings[0].binding;
|
|
|
|
|
assert.ok(binding.kind === "package");
|
|
|
|
|
binding.dependencies.push({
|
|
|
|
|
portId: port.id,
|
|
|
|
|
binding: {
|
|
|
|
|
kind: "edge",
|
|
|
|
|
edgeTypeId: fixtureId.projectOwner,
|
|
|
|
|
projectionId: fixtureId.projectOwnerProjection,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const edge = conformance(workspace, fixtureId.projectOwnedConformance).privateAttachments.find(
|
|
|
|
|
(entry) => entry.id === fixtureId.projectOwner,
|
|
|
|
|
);
|
|
|
|
|
assert.ok(edge?.kind === "edge");
|
|
|
|
|
const endpoint = edge.endpoints.find((entry) => entry.projectionId === fixtureId.projectOwnerProjection)!;
|
|
|
|
|
expectIssue(workspace, "private-attachment-access");
|
|
|
|
|
|
|
|
|
|
// Publicity of the opposite projection does not grant this receiver access.
|
|
|
|
|
edge.endpoints.find((entry) => entry !== endpoint)!.publicTraversal = true;
|
|
|
|
|
expectIssue(workspace, "private-attachment-access");
|
|
|
|
|
endpoint.publicTraversal = true;
|
|
|
|
|
assert.deepEqual(validateWorkspaceRevision(workspace), []);
|
|
|
|
|
const compiled = compileWorkspaceRevision(workspace);
|
|
|
|
|
assert.ok(compiled.ok);
|
|
|
|
|
const plan = resolveOperationPlan(compiled.plan, fixtureId.project, fixtureId.summaryV1, fixtureId.summaryGet);
|
|
|
|
|
assert.ok(plan?.kind === "package");
|
|
|
|
|
assert.deepEqual(plan.dependencies.find((entry) => entry.port.id === port.id)?.port.requirement, port.requirement);
|
|
|
|
|
|
|
|
|
|
for (const primitive of ["connect", "disconnect", "watch-start", "watch-stop"] as const) {
|
|
|
|
|
const mutated = structuredClone(workspace);
|
|
|
|
|
const requirement = mutated.packageImports
|
|
|
|
|
.flatMap((pkg) => pkg.exports)
|
|
|
|
|
.find((entry) => entry.id === fixtureId.summaryGetExport)!
|
|
|
|
|
.dependencyPorts.find((entry) => entry.id === port.id)!.requirement;
|
|
|
|
|
assert.ok(requirement.kind === "edge");
|
|
|
|
|
requirement.primitives.push(primitive);
|
|
|
|
|
expectIssue(mutated, "private-attachment-access");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("native state and edge providers must match operation shape", () => {
|
|
|
|
|
const stateWorkspace = makeValidCapabilityWorkspace();
|
|
|
|
|
const state = conformance(stateWorkspace, fixtureId.projectNamedConformance).operationBindings[0]!.binding;
|
|
|
|
|