Contextfulv0.23.0

Docs / Guides

contract disclosure · 60-visibility.md · 61-disclosure.md · 62-accountability.md · guide · card

Visibility, disclosure and accountability

The problems this contract solves

A Contextful workspace indexes an organization’s wiki, drive and chat. Three problems follow. A reader sees only what the source lets that reader see (visibility). A figure computed from other people’s rows reaches one asker without exposing any contributor (disclosure). Every read leaves a verifiable trace, and a person or a tenant is removable on demand (accountability).

Visibility: mirroring source permissions

The example is a wiki page shared with the group planning, which contains eng-leads, which contains one reader.

A pack is the reviewed unit that loads one source with its access mapping; a table with no mapping fails at diagnosis (mapping-absent). A sweep reads the source’s permission state and commits it as one run (sweep-verb). Grants arrive as ordinary rows of reserved _visibility tables (grants-table).

For the wiki, the sweep writes one resource row, one grant to planning and two membership rows. A grant naming no resource fails at commit (orphan-grant). A Drive sweep follows every permission page of each file before its grants replace earlier ones (permission-pages).

Flowchart diagram Flowchart, top to bottom. 9 nodes, 8 edges. connector pack → ACL sweep job [access mapping] visibility: ACL sweep job → access tables [copied grants] visibility: access tables → reader [reachable rows, within budget] reader → audit chain [recorded read] disclosure: release job → published aggregate [suppressed, noised figures] disclosure: published aggregate → reader [cohort answer] accountability: audit chain accountability: erasure cascade → purge receipt [signed]; → audit chain [erasure entry] accountability: purge receipt visibility copied grants ACL sweep job access tables disclosure suppressed, noised figures release job published aggregate accountability signed erasure entry audit chain erasure cascade purge receipt access mapping reachable rows, within budget recorded read cohort answer connector pack reader

At read time, a bounded group closure walks planning, then eng-leads, then the reader (closure-walk). The registered view admits a row only when its resource holds a grant in that reachable set (semi-join). The reachable set holds every principal the subject reaches through identity links and groups (subject-principals).

Fidelity states how closely a table follows its source, and the source family caps the claim (family-bound).

When permission state goes stale

An editor removes planning from the page. The table’s staleness budget, a declared duration (budget-grammar), bounds how long the old grant keeps answering. If the sweep stalls past the budget, the reader’s next read fails instead of serving a revoked grant (access-stale).

A table declared public_only instead narrows to public rows past its budget (public-only). The engine retains no reachable set computed in either state (degraded-uncached).

Explaining a decision

Asked why a colleague lacks access to the page, audit explain decides from current grants (decision). The explanation names groups on the path and omits their members (groups-not-members).

Disclosure: releasing a figure

A release computes statistics over contributors’ rows. It first reserves each contributor’s spend against a lifetime budget, and a failed reservation publishes nothing (budget-reservation). A group key outside the permitted columns fails (group-key). A model declaring a disclosure policy publishes only through a release: a plain build of it, or a build job naming it, fails before staging any row (governed-build).

The release suppresses a group whose distinct contributors fall under the declared minimum (min-group-size). Every suppressed group together leaves one sentinel row with no key or figure (sentinel-row).

A model declares whether its figures describe one person or a cohort, and a model declaring neither is per-person (governance-declaration). A cohort key resolving to one person fails at declaration (singleton-cohort).

The tables a cohort model’s statement reads hold one row per contributor, so a read of one fails unless the credential grants read-individual over it (per-individual-row). A statement grouping the published cohort table by fewer than all its group-key columns fails: the coarser groups sum figures no release noised (cohort-widening).

A derive or synthesis pass over such a table needs read-individual too; its output inherits the rule (derive-individual, synthesize-individual). A scheduled synthesis holds it only when its job declares read_individual = true (fire-individual).

A named query template holds one statement (single-statement). The offline diagnostic checks every published model’s policy from local files (check-verb).

Accountability: the audit chain

Each read appends one audit entry, and rows leave only after that entry syncs (read-entry). Entries hash-link into segments, each closed by a signed root (segment).

A proof for one entry verifies offline under the signer’s public key alone (inclusion-proof). Verification of a damaged chain fails at the earliest broken index (broken-chain).

Erasure

When the reader leaves, an operator erases their rows under the forget grant (privilege). The cascade invalidates every fact derived from the erased rows in the same operation (cascade), and the files holding them are rewritten or collected (physical-removal).

A dead letter repeats the content of the rows its failed batch carried, so each letter citing an erased row leaves with it (dead-letters). A letter without evidence cites no row, so no subject reaches it; context erase --dead-letters-without-evidence clears those letters through the same signed publication (dead-letters-without-evidence).

A tenant purge returns a signed receipt naming a salted pseudonym, not the tenant identifier (pseudonym).