oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1-- Sharing: a grant is one person's access to one document.
2--
3-- Spec §8.2 has described this since the design was written and nothing
4-- implemented it: until now `documents.owner_id` was the whole authorization
5-- model and every signed-in person saw only their own rows.
6--
7-- `subject` is a lowercased, trimmed address, NOT a `people.id`, and that is
8-- deliberate. A grant has to be makeable to somebody who has never signed in —
9-- that is most of what sharing is for — and `EnsurePerson`'s create branch is
10-- where a brand-new person gets seeded a sample library. Minting a Person row
11-- to hold a grant would hand an invitee six sample documents they never asked
12-- for, before they had even accepted. Keyed on the address, the grant simply
13-- waits, and `EnsurePerson` maps the address to an id whenever they arrive.
14--
15-- It is also the same subject the suite doctrine's §3 uses in lone shape: a
16-- lowercased address. Docs is lone-shaped today, and when a home arrives the
17-- subject gains a kind rather than a different meaning.
18--
19-- `role` is `reader` or `writer`. Not an integer, because a role read out of a
20-- database during an incident should say what it is. Document-scoped only:
21-- there is no team in this app yet, so there is nothing a NULL doc_id could
22-- mean, and a nullable column whose one legal value is "not that" is an
23-- invitation to guess. Spec §8.2's team-wide grant arrives with a team.
24--
25-- The UNIQUE index is the whole conflict story: granting twice to the same
26-- address on the same document updates the role rather than stacking two rows
27-- whose precedence nobody has decided.
28-- `created_by` is the person who made the grant, and it is in the spec's own
29-- data model (§4) — this table shipped without it, and the omission was never
30-- argued, only overlooked while the nullable `doc_id` above was argued at
31-- length. It is the one column that answers "who let this address in".
32--
33-- That question has teeth because admission is transitive in shape even where
34-- it is closed in policy: a guest is admitted by somebody's grant, and if a
35-- guest ever gains the power to grant, the chain of who admitted whom is only
36-- reconstructable if each link recorded its author. Adding it now, while the
37-- table is new, costs a line; adding it after a leak costs the history.
38CREATE TABLE IF NOT EXISTS grants (
39 id INTEGER PRIMARY KEY AUTOINCREMENT,
40 doc_id INTEGER NOT NULL,
41 subject TEXT NOT NULL,
42 role TEXT NOT NULL,
43 created_by INTEGER NOT NULL DEFAULT 0,
44 created_at DATETIME
45);
46
47CREATE UNIQUE INDEX IF NOT EXISTS idx_grants_doc_subject ON grants (doc_id, subject);
48
49-- The read path asks "which documents may this subject reach", so the index
50-- that matters leads on subject.
51CREATE INDEX IF NOT EXISTS idx_grants_subject ON grants (subject);
52