---
title: People-owned and producer-owned data
description: Every document in the store has exactly one kind of writer. Which paths belong to people, which to producers, and why that rule replaces locking.
sidebar:
  order: 7
---

## What it is

Every path in the store is written either by producers (routine runs) or by people (through the Desk), never both. Views and agent columns are the one shared case: a producer may create them, and from then on only people change them.

## Why it exists

Page writes in the artifact database carry no version check; they are last-writer-wins. Only the run side uses `if_version`. If a person and a run could both write one document, a run could silently undo a person's decision, or a person's save could vanish under a run's write. Giving each document one kind of writer means they never race, with no locks.

It is also the main safety rule. Settings, decisions and merges are how people steer a routine. If a run could write them, text on a fetched page could steer the routine instead.

## How it works

- `desk_contract.py` holds `HUMAN_PREFIXES`: `settings/`, `userstate/`, `decisions/`, `merges/`, `data/users/`. `guard()` refuses any planned batch with a write under them.
- `CREATE_ONLY_PREFIXES`: `views/`, `columns/`. A producer may create a document there only if it is absent; any edit or delete is refused.
- `PRIVATE_PREFIXES`: `userstate/`, `data/users/`. The planner never reads them.
- On the page side, `actions.js` is the only file that writes, and only to `PEOPLE_COLLECTIONS` (`settings`, `userstate`, `decisions`, `merges`, `views`, `columns`) plus `data/users/<viewer>/`.

## Reference

| Path | Writer | Notes |
|---|---|---|
| `meta/workspace`, `meta/definition` | Seed step | Written once by `seed`, or `compile` for the definition |
| `entities/<id>` | Producers | Each producer replaces only its own `bySource` slice |
| `runs/<runId>` | Producers | |
| `inbox/<runId>--<n>` | Producers | |
| `pending/<id>` | Producers | Gates; create-only per run id |
| `state/learning` | Producers | Written by `learn` |
| `settings/<producerId>`, `settings/workspace` | People | Seed writes defaults once, only when absent |
| `decisions/<id>` | People | Keep, drop, accept, reject, approve |
| `merges/<entityId>` | People | Hand merges |
| `userstate/<entityId>` | People | Stars, tags, notes |
| `views/<id>`, `columns/<id>` | Agent creates as proposed; people own every later edit | |
| `data/users/<viewer>/state/...` | That viewer | Read, done, ack; private even from the owner |
| `settingsHistory/<id>` | People | Since 0.5.0; see below |

> Since 0.5.0: `settingsHistory/` is a new people collection (every Settings save writes `{producer, before, after, at, by}`), and per-viewer `snooze` and `pin` state under `data/users/<viewer>/state/`. New people collections are added to both `actions.js` and `HUMAN_PREFIXES`.

### Per-viewer state

`data/users/<id>/` is private to that viewer. The page gets `<id>` from `user.id()` after declaring the `user` capability. Documents sit at even segment counts, so per-viewer paths carry a `state` segment: `data/users/<viewer>/state/read/<inboxId>`. If `user.id()` returns null, per-viewer features are off for that view; nothing falls back to a shared path or to localStorage.

## Worked example

On Hiring Signals, a person opens the dropped "Graduate Data Analyst" role and chooses Keep. The Desk writes `decisions/role--https-jobs-example-au-1002` `{decision: "keep", at, by}`. On the next run the write contract reads that decision and writes the role as `status: "active"`, `dropReason: null`, with the sighting note `kept by person`. The run never writes the decision, and the person never writes the entity. The learning step counts the keep as evidence that `title_keywords` missed something.

## Common pitfalls

- **Storing a person's edit on the entity.** It will be overwritten by the next run. Store it as a decision or in `userstate/`.
- **A routine that "remembers" by writing settings.** Refused. Memory lives in `state/` or on records.
- **Reading per-viewer state in a run.** The planner never reads it, by design. A run cannot know who read what.

## Related

- [The store and the write contract](/concepts/store-and-write-contract)
- [Store collections](/reference/store-collections)
- [The Desk: capabilities and degradation](/desk/capabilities)
