"The master file is always accurate for exactly one day: the day you wrote it."
The God-File Temptation
The obvious way to build a family hub is one big list. A FAMILY dictionary: every member, its title, its host, its ports, its capabilities, its health. It feels great for an afternoon. Then Ember moves to a new port and the list is wrong. Then a repo is renamed and the list is wrong in a different place. Then someone adds a service and forgets the list entirely. The master file doesn't fail loudly — it drifts, quietly, into confident lies.
The problem isn't laziness; it's that the master file duplicates facts other places already own. The roster already knows the title. The network ledger already knows the port. The repo on disk already knows its Git state. Copying those into one file means every future change has two homes, and the second one always lags.
One Owner, Then Compose
Firelink's answer is to name a single canonical owner for each kind of fact and never copy it:
- Title, one-liner, lifecycle → the roster document.
- Hosts, ports, URLs, 'no network' declarations → the network ledger.
- Bundle IDs, service labels, adapter IDs, peer allowlists → Firelink's own operation-policy file.
- Disk, Git, installed app, process, endpoint state → live discovery, measured fresh.
- GitHub presence → a GitHub query.
- Human-facing product release → each repo's
cwk-product.json.
Then Firelink composes these owners into one typed model at read time. There is deliberately no static FAMILY list, no separate frontend operation list, no second service allowlist, no duplicate native-app allowlist. Every consumer — census, APIs, WebUI, the launcher's catalog, operation policy — reads the one composed registry.
Why Composition Beats a Copy
When each fact has exactly one home, a change has exactly one place to make it, and the composed view is correct the next time it's read. There's no reconciliation between the master file and reality because there's no master file to reconcile. The operation-policy file that Firelink does own is carefully scoped to hold only things no other ledger owns — adapter IDs, bundle IDs, peer allowlists — and it explicitly must not duplicate a title or a URL that a shared ledger already carries.