Play, Reveals & Campaigns
The table side - how player-facing data is kept separate by construction, and how a campaign can diverge from canon without a second data model.
Worldbuilding has two audiences with opposite needs. The author wants to see everything. The player at the table should see only what the game master has shown them. Getting that wrong is not a cosmetic bug; it spoils the game. So Chronicler treats the split as a structural decision, not a runtime filter that a tired developer might forget to apply.
Two surfaces, and the player one cannot leak
The API is built around two first-class surfaces. The build surface is for authoring. The play surface is for the table, and it has its own DTOs. That is the important part: the player-facing shapes physically cannot contain game-master-only fields, because those fields are not in the type. Leaking secret data is not prevented by remembering to strip it. It is prevented by there being nothing to strip.
A campaign can diverge from canon
A campaign often needs its own version of the world. The city fell in this game, but not in canon. Rather than build a second modelling axis for that, Chronicler puts a first-class campaign scope on resources. A campaign can diverge in three ways: a shadowing variant that overrides a canon resource for that campaign, a brand-new resource that exists only in the campaign, and a campaign-scoped evolution. One scope covers all three, so the divergence lives in the same model as everything else.
Reveals, in two layers
A reveal is how a game master shows a resource to players, and it is deliberately two decisions, not one. The first layer is an access grant that makes the resource visible at all, hung off a campaign-scoped role. The second is a content filter that chooses which parts of it show.
The filter works because every revealable part of a resource is a row: the header, each attribute, each relationship, each lore segment, a stat block, a tag. Showing part of a resource is selecting rows, never parsing content. "Header", "partial", and "full" are just descriptions of how many rows were granted, not a stored setting that could disagree with reality. And because the access grant is anchored to the campaign, a reveal answers only play questions in its own campaign, so it cannot bleed into canon or a sibling table.
Where this connects
Reveals lean on the row model from Lore and authoring, and the campaign anchor is enforced in Authorization.
Read the record for the detail
This page is the guide. The full records under docs/adrs carry the reveal data model, the campaign scoping rules, and the alternatives that were weighed and rejected.