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 / runtime / shared_field_write_test.ts
shared_field_write_test.ts 4.4K
1// The write-side sealer: shared columns seal with the newest held2// generation, resolve their scope from the sibling group column (or a3// fetched row for updates), refuse without a key, and pass pre-sealed and4// non-shared values through untouched.5import { sealSharedColumnValues, sealSharedColumnValuesSync } from "./shared-field-write.ts";6import { clearEncryptedColumnRegistry, registerEncryptedColumns } from "../schema/encrypted.ts";7import { clearSharedColumnRegistry, registerSharedColumn } from "../schema/shared-registry.ts";8import {9 clearSharedFieldKeys,10 installSharedFieldKey,11 sharedKeyScope,12} from "../schema/shared-keyring.ts";13import { generateFieldKey, openSharedValue, SharedFieldError } from "../schema/shared-crypto.ts";14import { assert } from "./test-assert.ts";1516const LABEL = "writer.docs.body";1718function arrange(): Uint8Array {19 clearEncryptedColumnRegistry();20 clearSharedColumnRegistry();21 clearSharedFieldKeys();22 registerEncryptedColumns({23 docs: { body: { __marker: true } },24 });25 // The harvest walks builder tags; register directly for the unit scope.26 registerSharedColumn({27 label: LABEL,28 kind: "text",29 group: "workspaces",30 groupIdColumn: "workspaceId",31 keys: "workspaceFieldKeys",32 directory: "keyDirectory",33 });34 const fieldKey = generateFieldKey();35 installSharedFieldKey(sharedKeyScope("workspaces", "ws-1"), 1, fieldKey);36 installSharedFieldKey(sharedKeyScope("workspaces", "ws-1"), 3, fieldKey);37 return fieldKey;38}3940function cleanup(): void {41 clearEncryptedColumnRegistry();42 clearSharedColumnRegistry();43 clearSharedFieldKeys();44}4546// registerEncryptedColumns tags via builder symbols; the unit registry needs47// the (table, column, label) mapping directly, so stub the tag lookup by48// registering through the real harvest with a tagged builder object.49import { encryptedText } from "../schema/encrypted.ts";50function registerDocsBody(): void {51 clearEncryptedColumnRegistry();52 const tagged = encryptedText(LABEL);53 registerEncryptedColumns({ docs: { body: tagged } });54}5556Deno.test("inserts seal with the newest held generation", () => {57 const fieldKey = arrange();58 registerDocsBody();59 try {60 const sealed = sealSharedColumnValuesSync("docs", {61 workspaceId: "ws-1",62 title: "plain",63 body: "shared words",64 });65 const stored = sealed.body as string;66 assert(stored.startsWith("encs1.workspaces.ws-1.3."), "the newest generation must seal");67 assert(sealed.title === "plain", "plaintext columns pass through");68 assert(69 openSharedValue({ stored, fieldKey, label: LABEL }) === "shared words",70 "the sealed value must open under the field key",71 );72 // Idempotence: an already-sealed value passes through.73 const again = sealSharedColumnValuesSync("docs", { workspaceId: "ws-1", body: stored });74 assert(again.body === stored, "a pre-sealed value must pass through");75 } finally {76 cleanup();77 }78});7980Deno.test("writes without a key or scope refuse loudly", () => {81 arrange();82 registerDocsBody();83 try {84 let pending = false;85 try {86 sealSharedColumnValuesSync("docs", { workspaceId: "ws-other", body: "x" });87 } catch (error) {88 pending = error instanceof SharedFieldError && error.code === "key-pending";89 }90 assert(pending, "a scope without a held key must refuse with key-pending");9192 let unscoped = false;93 try {94 sealSharedColumnValuesSync("docs", { body: "x" });95 } catch (error) {96 unscoped = error instanceof SharedFieldError && error.code === "unscoped-write";97 }98 assert(unscoped, "a patch without the group column must refuse in the sync path");99 } finally {100 cleanup();101 }102});103104Deno.test("the async path resolves the scope from the fetched row", async () => {105 const fieldKey = arrange();106 registerDocsBody();107 try {108 const sealed = await sealSharedColumnValues(109 "docs",110 { body: "patched words" },111 () => Promise.resolve({ id: "row-1", workspaceId: "ws-1" }),112 );113 const stored = sealed.body as string;114 assert(stored.startsWith("encs1.workspaces.ws-1.3."), "the fetched scope must seal");115 assert(116 openSharedValue({ stored, fieldKey, label: LABEL }) === "patched words",117 "the update seal must open",118 );119120 // Tables without shared columns pass through untouched.121 const untouched = await sealSharedColumnValues("elsewhere", { body: "x" });122 assert(untouched.body === "x", "non-shared tables must pass through");123 } finally {124 cleanup();125 }126});