oficina / docs Public

samples-for-new-people: seed a person's space, not the instance closed

The app shipped, Paul signed in, and the document list was empty.

Six sample documents existed. They were correct, reviewed, and read well. They were also unreachable on any deployed instance, for two structural reasons:

  1. docs.Seed was reachable only through the -seed flag, gated on -env development, which is settable only by a literal flag the platform never passes. That gate is correct and stays exactly as it is — it is what keeps seeding away from a real database.
  2. Documents are owner-scoped. A boot-time seed has no person to own anything.

So the fix could not be "run the seeder on the server". Ownership is per person, which means seeding has to be too.

What changed

A person's space is seeded when their row is first created (Store.EnsurePerson), opted into per instance by $DOCS_SAMPLE_DOCUMENTS, default off.

Tied to person creation rather than to "the list is empty" so that deleting every document cannot resurrect them. Default off so a real team spinning up an instance is never handed six invented documents about an allotment committee.

Seeding runs strictly after the person INSERT commits, outside any transaction, and every failure is logged and swallowed. A person who cannot sign in because sample content failed to generate is a far worse outcome than a person with an empty list.

$DOCS_SAMPLE_DOCUMENTS is deliberately not fail-closed, unlike Origin, InstanceKey and the sign-in allowlist, which all refuse at startup. Those are security controls; this is cosmetic content. A typo parses to off. The asymmetry is written down in Config.SampleDocuments because a reader who has seen the rest of that file will expect a refusal and should learn why this one differs.

How it was verified

Against the real binary, with no -seed flag and only the environment variable set — the exact shape the platform runs:

Packing List — Thursday Site Visit
Proposal: Refitting the Elm Street Reading Room
Notes — Tuesday Planning Sync
Quick Reference: Resetting the Site Printer
Letter to the Harbourview Allotment Committee
A History of the Millbrook Waterworks

Six documents, four recency groups. Testing the wiring was not enough — testing the wiring is exactly what produced an empty instance in the first place.

The defect this branch is remediation for, stated plainly

Everything about the sample documents was verified except whether the code path could run where it was deployed. The unit tests passed, the task review passed, the whole-branch review passed, the prose was read by two of us. Every check measured something true and adjacent to the question a user would ask, which is: do I see documents.

That is the third instance of this shape on this codebase, after a gate test that re-implemented the gate and compared it to itself, and a test named for a write refusal that asserted only a timestamp. A fourth was found and fixed here: TestEnsurePersonSurvivesSeedingFailure asserted that EnsurePerson succeeded and List did not error — both of which hold just as well if seeding silently succeeded or was skipped. It now asserts fewer than len(seedDocs) documents survived, verified by swapping the deliberately-closed core for a working one and watching it fail.

Known, accepted

Accounts created before the setting is enabled never get samples, including the one whose empty list motivated this. The found-branch of EnsurePerson skips seeding by design. An existing account gets samples by signing in under a new address, not by any retroactive fill.

Reviewed as a single diff by the highest-capability model per AGENTS.md. Full CI gate green, exit 0.