/// // FIXTURE (multi-runtime integration, CFC Phase 3.b): cross-reader isolation // of read-time-clearance query results. // // Each notes row names its intended reader (a full did:key string) in its own // `reader` column, and the row rule mints exactly that principal as the row's // confidentiality. A `readClearance: true` query therefore returns each acting // reader ONLY the rows naming them — and because the cleared result is // reader-specific, each reader must get an ISOLATED result cell (per-`user` // scope) keyed by a reader-aware request hash. Regression fixture for the // #4478 review P0 (52e3e7e7): a space-scoped result cell plus a reader-blind // request hash let one reader observe another reader's filtered rows. import { cfSqlite, handler, NAME, pattern, sqliteDatabase, type SqliteDb, } from "commonfabric"; interface NoteRow { id: number; reader: string; body: string; } /** Seed rows addressed to specific readers (full did:key strings). */ const seed = handler< { rows: { reader: string; body: string }[] }, { db: SqliteDb } >(({ rows }, { db }) => { for (const row of rows) { db.exec("INSERT INTO notes (reader, body) VALUES (?, ?)", [ row.reader, row.body, ]); } }); export default pattern(() => { // In-body destructuring: top-level destructuring is rejected by the SES // verifier, and the rule callback is the recognized `table(columns, rule)` // boundary (evaluated eagerly into a serialized AST). const { table, principal, match } = cfSqlite; // The base58btc multikey suffix of a did:key (z6Mk…). principal("key", …) // re-mints `did:key:`, so each row's confidentiality is exactly the // did:key stored in its own reader column — one conjunctive clause naming // one principal. const KEY = /z[1-9A-HJ-NP-Za-km-z]+/g; const notes = table( { id: "integer primary key", reader: "text", body: "text", }, // A bare term (no all() wrapper) — the simplest form for a single // alternative. (Term LISTS used to split into per-element linked docs on // the stored handle and destabilize the request hash across runtimes; // fixed in #4509 — the handle is stored self-contained — and guarded by // packages/runner/test/sqlite-handle-multi-runtime.test.ts.) (f) => ({ confidentiality: principal("key", match(f.reader, KEY, { min: 1 })), }), // Phase 3.b: opt the table into read-time clearance. { allowReadClearance: true }, ); const db = sqliteDatabase({ tables: { notes } }); // Baseline (no clearance): a shared, reader-blind result — every reader // sees every row, so any isolation observed on qClear is clearance-made. const qAll = db.query( "SELECT id, reader, body FROM notes ORDER BY id", { reactOn: db }, ); // Read-time clearance: rows filtered to the ACTING reader per runtime. const qClear = db.query( "SELECT id, reader, body FROM notes ORDER BY id", { reactOn: db, readClearance: true }, ); return { [NAME]: "SQLite read-time clearance (multi-runtime fixture)", db, qAll, qClear, seed: seed({ db }), }; });