clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

fix/175-template-quality-pass
lofi / package / schema / shared_encrypted_test.ts
shared_encrypted_test.ts 5.2K
1// Shared-column contract: state-valued reads over the keyring (pending →2// ready without redefinition), the unscoped-write guard, and keyring3// bookkeeping.4import {5 clearSharedFieldKeys,6 getSharedFieldKey,7 installSharedFieldKey,8 latestSharedFieldGeneration,9 sharedKeyScope,10 subscribeSharedKeyring,11} from "./shared-keyring.ts";12import { generateFieldKey, sealSharedValue, SharedFieldError } from "./shared-crypto.ts";13import {14 sharedEncryptedText,15 sharedFieldReady,16 type SharedFieldValue,17 unwrapSharedField,18} from "./shared-encrypted.ts";19import { clearSharedColumnRegistry, sharedColumnConfigs } from "./shared-registry.ts";20import { assert } from "../runtime/test-assert.ts";2122const OPTIONS = {23 group: "workspaces",24 groupIdColumn: "workspaceId",25 keys: "workspaceFieldKeys",26 directory: "keyDirectory",27} as const;2829function transformOf(column: unknown): {30 to: (value: unknown) => string;31 from: (value: string) => unknown;32} {33 const transform = (column as { _transform?: unknown })._transform;34 assert(typeof transform === "object" && transform !== null, "column carries no transform");35 return transform as { to: (value: unknown) => string; from: (value: string) => unknown };36}3738Deno.test("the keyring installs, reports generations, and notifies", () => {39 clearSharedFieldKeys();40 const scope = sharedKeyScope("workspaces", "ws-1");41 try {42 assert(getSharedFieldKey(scope, 1) === null, "no key before install");43 assert(latestSharedFieldGeneration(scope) === null, "no generation before install");44 let notified = 0;45 const stop = subscribeSharedKeyring(() => notified += 1);46 const key = generateFieldKey();47 installSharedFieldKey(scope, 1, key);48 installSharedFieldKey(scope, 3, generateFieldKey());49 assert(notified === 2, `install must notify (saw ${notified})`);50 installSharedFieldKey(scope, 1, key);51 assert(notified === 2, "an identical re-install must not re-notify");52 assert(latestSharedFieldGeneration(scope) === 3, "latest generation must win");53 assert(getSharedFieldKey(scope, 1) !== null, "installed keys must resolve");54 stop();55 } finally {56 clearSharedFieldKeys();57 }58});5960Deno.test("reads surface pending, then ready once the key installs", () => {61 clearSharedFieldKeys();62 clearSharedColumnRegistry();63 try {64 const column = transformOf(sharedEncryptedText("docs.body", OPTIONS));65 const fieldKey = generateFieldKey();66 const stored = sealSharedValue({67 plaintext: "shared content",68 fieldKey,69 label: "docs.body",70 scope: { groupTable: "workspaces", groupId: "ws-1", generation: 2 },71 });7273 const pending = column.from(stored) as SharedFieldValue<string>;74 assert(75 pending.state === "pending-key" && pending.generation === 2,76 `a keyless read must surface pending (saw ${JSON.stringify(pending)})`,77 );78 let threw = false;79 try {80 unwrapSharedField(pending);81 } catch (error) {82 threw = error instanceof SharedFieldError && error.code === "key-pending";83 }84 assert(threw, "unwrapSharedField must throw key-pending while pending");8586 installSharedFieldKey(sharedKeyScope("workspaces", "ws-1"), 2, fieldKey);87 const ready = column.from(stored) as SharedFieldValue<string>;88 assert(89 sharedFieldReady(ready) && ready.value === "shared content",90 "the same stored value must decrypt after key install",91 );92 assert(unwrapSharedField(ready) === "shared content", "unwrap must return the value");9394 // The wrong key surfaces corrupt, never garbage.95 installSharedFieldKey(sharedKeyScope("workspaces", "ws-1"), 2, generateFieldKey());96 const corrupt = column.from(stored) as SharedFieldValue<string>;97 assert(corrupt.state === "corrupt", "a wrong key must surface corrupt");98 const unprefixed = column.from("plaintext leftovers") as SharedFieldValue<string>;99 assert(unprefixed.state === "corrupt", "a non-sealed stored value must surface corrupt");100 } finally {101 clearSharedFieldKeys();102 clearSharedColumnRegistry();103 }104});105106Deno.test("writes pass sealed values and refuse everything else", () => {107 clearSharedColumnRegistry();108 try {109 const column = transformOf(sharedEncryptedText("docs.note", OPTIONS));110 const fieldKey = generateFieldKey();111 const sealed = sealSharedValue({112 plaintext: "x",113 fieldKey,114 label: "docs.note",115 scope: { groupTable: "workspaces", groupId: "ws-1", generation: 1 },116 });117 assert(column.to(sealed) === sealed, "sealed values must pass through");118 let refused = false;119 try {120 column.to("raw plaintext");121 } catch (error) {122 refused = error instanceof SharedFieldError && error.code === "unscoped-write";123 }124 assert(refused, "an unsealed write must refuse with unscoped-write");125 } finally {126 clearSharedColumnRegistry();127 }128});129130Deno.test("constructors register their wiring for the runtime", () => {131 clearSharedColumnRegistry();132 try {133 sharedEncryptedText("docs.registered", OPTIONS);134 const configs = sharedColumnConfigs();135 assert(136 configs.length === 1 && configs[0].label === "docs.registered" &&137 configs[0].keys === "workspaceFieldKeys" && configs[0].directory === "keyDirectory",138 "the constructor must record its configuration",139 );140 } finally {141 clearSharedColumnRegistry();142 }143});