Default-deny. An untagged fact is visible to no one. Every context should carry a blanket
default class so the common case isn't hand-tagged. (SIFT tags per-node instead, for now.)
Classes & grants are themselves facts (no parallel ACL system):
Multi-label: a node may carry several cls facts (e.g. d_brd = eng + internal + external).
Visibility predicate: viewer sees a fact iff closure(can_see(viewer)) ∩ cls(fact) ≠ ∅.
closure = transitive over can_see edges (role hierarchy falls out for free).
Mask is applied FIRST — filter the fact-set to the viewer's visible subset before any
fold/follow/incoming/diff. Filtering last leaks: traversal already crossed the boundary.
Masking first makes invisible facts non-existent for the query → traversal cannot leak.
Vyasa KG — ACL (viewer-mask) Engine + UI Handoff Prompt