/** * A lift that reads part of a labeled value is labeled as one reading all of * it is. The transformer narrows the lift's capture schema to the fields the * lift reads, and keeps the labels of the value it narrows; the runner joins * the confidentiality of every label in a lift's argument schema into its * result as a `declared` entry (`applyArgumentIfcToResult`). Under `observe` * flow labels no other entry labels the result, so the declared one is all * that does. */ import { afterEach, describe, it } from "@std/testing/bdd"; import { expect } from "@std/expect"; import { Identity } from "@commonfabric/identity"; import { StorageManager } from "../src/storage/cache.deno.ts"; import { Runtime } from "../src/runtime.ts"; import type { RuntimeProgram } from "../src/harness/types.ts"; const signer = await Identity.fromPassphrase( "runner-cfc-narrowed-capture-floor", ); const space = signer.did(); type StoredEntry = { path: string[]; label: Record; origin?: string; }; /** * A pattern over `secret`, declared by `declaration`, returning `out`, beside * a module declaring the exchange rules `rules`, and `readers` and `writers`, * which are declared with one type. */ const program = (declaration: string, out: string): RuntimeProgram => ({ main: "/main.tsx", files: [{ name: "/main.tsx", contents: [ "import { computed, pattern, type Confidential } from 'commonfabric';", "import { type PolicyOf } from 'commonfabric/cfc';", "import { readers, rules, writers } from './rules.ts';", "interface Secret { a: string; b: string }", "interface Other { a: string; c: number }", "type Either = Confidential | Confidential;", `export default pattern<{ ${declaration} }>(({ secret }) => ({`, ` out: computed(() => ${out}),`, "}));", ].join("\n"), }, { name: "/rules.ts", contents: [ "import { type CfcExchangeRulesDeclaration, exchangeRule, exchangeRules, THIS_POLICY } from 'commonfabric/cfc';", "export const neverRelease = exchangeRule({", " appliesTo: THIS_POLICY,", " pre: { integrity: ['never'] },", " post: { dropClause: true },", "});", "export const rules = exchangeRules([neverRelease]);", "export const releaseToReaders = exchangeRule({", " appliesTo: THIS_POLICY,", " pre: { integrity: ['reader'] },", " post: { dropClause: true },", "});", "export const releaseToWriters = exchangeRule({", " appliesTo: THIS_POLICY,", " pre: { integrity: ['writer'] },", " post: { dropClause: true },", "});", "export const readers: CfcExchangeRulesDeclaration = exchangeRules([releaseToReaders]);", "export const writers: CfcExchangeRulesDeclaration = exchangeRules([releaseToWriters]);", ].join("\n"), }], }); describe("cfc-narrowed-capture-floor", () => { let storageManager: ReturnType | undefined; let runtime: Runtime | undefined; afterEach(async () => { await runtime?.dispose(); await storageManager?.close(); runtime = undefined; storageManager = undefined; }); /** The labels of the `declared` entries stored on the result's `out`. */ const declaredLabelsOfOut = async ( declaration: string, out: string, ): Promise[]> => { storageManager = StorageManager.emulate({ as: signer }); runtime = new Runtime({ apiUrl: new URL(import.meta.url), storageManager, cfcFlowLabels: "observe", }); const compiled = await runtime.patternManager.compilePattern( program(declaration, out), { space }, ); const tx = runtime.edit(); const result = runtime.getCell>( space, "narrowed capture floor", compiled.resultSchema, tx, ); runtime.run(tx, compiled, { secret: { a: "x", b: "y" } }, result); runtime.prepareTxForCommit(tx); expect((await tx.commit().settled).ok).toBeDefined(); await result.pull(); await runtime.settled(); await storageManager.synced(); const read = runtime.edit(); const outCell = result.key("out").withTx(read).resolveAsCell(); const id = outCell.getAsNormalizedFullLink().id; expect(outCell.get()).toBe("x"); read.commit(); const replica = storageManager.open(space).replica as unknown as { getDocument(id: string): { cfc?: { labelMap?: { entries: StoredEntry[] } }; } | undefined; }; return (replica.getDocument(id)?.cfc?.labelMap?.entries ?? []) .filter((entry) => entry.origin === "declared") .map((entry) => entry.label); }; it("labels the result of a lift reading a labeled value by a property chain", async () => { expect( await declaredLabelsOfOut( 'secret: Confidential', "secret.a", ), ).toEqual([{ confidentiality: ["topsecret"] }]); }); it("labels the result of a lift reading a labeled value by an optional chain", async () => { expect( await declaredLabelsOfOut( 'secret: Confidential | undefined', 'secret?.a ?? ""', ), ).toEqual([{ confidentiality: ["topsecret"] }]); }); it("labels the result of a lift reading a labeled union with every member's confidentiality", async () => { const [label] = await declaredLabelsOfOut( 'secret: Confidential', "secret.a", ); expect(new Set(label?.confidentiality as unknown[])).toEqual( new Set(["outer", "x", "y"]), ); }); it("labels the result of a lift reading a union under an empty label with each member's confidentiality", async () => { const [label] = await declaredLabelsOfOut( "secret: Confidential", "secret.a", ); expect(new Set(label?.confidentiality as unknown[])).toEqual( new Set(["x", "y"]), ); }); it("labels the result of a lift reading a value by an optional chain with its declared policy", async () => { expect( await declaredLabelsOfOut( "secret: Confidential]>", 'secret?.a ?? ""', ), ).toMatchObject([{ confidentiality: [{ policyRefKind: "module", symbol: "rules" }], }]); }); it("labels the result of a lift reading an optional property with its declared policy", async () => { expect( await declaredLabelsOfOut( "secret?: Confidential]>", 'secret?.a ?? ""', ), ).toMatchObject([{ confidentiality: [{ policyRefKind: "module", symbol: "rules" }], }]); }); it("labels the result of a lift reading a value whole with its declared policy", async () => { expect( await declaredLabelsOfOut( "secret: Confidential]>", 'JSON.stringify(secret) ? secret.a : ""', ), ).toMatchObject([{ confidentiality: [{ policyRefKind: "module", symbol: "rules" }], }]); }); it("labels the result of a lift reading a value a CFC alias over a union labels beside `null` with its declared policy", async () => { expect( await declaredLabelsOfOut( "secret: Confidential]> | null", 'secret?.a ?? ""', ), ).toMatchObject([{ confidentiality: [{ policyRefKind: "module", symbol: "rules" }], }]); }); describe("a lift reading a value two CFC aliases over the same union label", () => { // `readers` and `writers` have one type, so the checker folds both labeled // unions into the same members, and only their nodes tell the policies // apart. /** The policies the result of a lift reading `first | second` declares. */ const declaredPolicies = async (first: string, second: string) => { const labeled = (binding: string) => `Confidential]>`; const [label] = await declaredLabelsOfOut( `secret: ${labeled(first)} | ${labeled(second)} | null`, 'secret?.a ?? ""', ); return new Set( (label?.confidentiality as { symbol?: string }[]).map((atom) => atom.symbol ), ); }; it("labels the result with both policies, `readers` written first", async () => { expect(await declaredPolicies("readers", "writers")).toEqual( new Set(["readers", "writers"]), ); }); it("labels the result with both policies, `writers` written first", async () => { expect(await declaredPolicies("writers", "readers")).toEqual( new Set(["readers", "writers"]), ); }); }); describe("a lift reading a union whose policy alternatives share a type", () => { for (const payload of ["Secret", "Secret | Other"]) { for (const nullable of [false, true]) { for (const whole of [false, true]) { it(`keeps both policies of ${payload}${nullable ? " beside null" : " without null"} read ${whole ? "whole" : "by a property"}`, async () => { const labeled = (binding: string) => `Confidential<${payload}, [PolicyOf]>`; for ( const [first, second] of [["readers", "writers"], [ "writers", "readers", ]] ) { const [label] = await declaredLabelsOfOut( `secret: ${labeled(first!)} | ${labeled(second!)}${ nullable ? " | null" : "" }`, whole ? 'JSON.stringify(secret) ? secret?.a ?? "" : ""' : 'secret?.a ?? ""', ); expect(label?.confidentiality).toEqual(expect.arrayContaining([ expect.objectContaining({ policyRefKind: "module", symbol: "readers", }), expect.objectContaining({ policyRefKind: "module", symbol: "writers", }), ])); expect(label?.confidentiality).toHaveLength(2); } }); } } } }); describe("a lift reading whole an optional value whose annotation writes a union", () => { const WHOLE = 'JSON.stringify(secret) ? secret?.a ?? "" : ""'; const POLICY = [{ confidentiality: [{ policyRefKind: "module", symbol: "rules" }], }]; it("labels the result with a nullable value's declared policy", async () => { expect( await declaredLabelsOfOut( "secret?: Confidential]> | null", WHOLE, ), ).toMatchObject(POLICY); }); it("labels the result with the declared policy of each value the union holds", async () => { expect( await declaredLabelsOfOut( "secret?: Confidential]> | Confidential]>", WHOLE, ), ).toMatchObject(POLICY); }); it("labels the result with the declared policy of a value whose annotation writes `undefined`", async () => { expect( await declaredLabelsOfOut( "secret?: Confidential]> | undefined", WHOLE, ), ).toMatchObject(POLICY); }); }); it("labels nothing for a lift reading an unlabeled value", async () => { expect(await declaredLabelsOfOut("secret: Secret", "secret.a")).toEqual( [], ); }); });