| index 5f6d9b7..709e42c 100644 |
| --- a/docs/superpowers/specs/2026-08-30-sheets-design.md |
| +++ b/docs/superpowers/specs/2026-08-30-sheets-design.md |
| @@ -453,6 +453,14 @@ Team: owner, member, guest. Per sheet: owner, editor, commenter, viewer. A |
| guest holds no team-wide rights — they see exactly the sheets granted to |
| them and learn nothing about the team beyond §9.5's disclosure. |
| |
| +**Team standing comes from the roster the home holds** (suite §5) in suite |
| +shape, and from `$SHEETS_OWNERS` and the local member rows in lone shape. |
| +**Per-sheet roles stay here.** The doctrine deliberately does not unify |
| +them: a shared role vocabulary designed from three specs at once would fit |
| +none of them, and it may move to the contract module when two apps have |
| +shipped the same one (suite §5.6). Sheets has `commenter`; calendar has no |
| +such role and Docs has none yet, so that moment has not arrived. |
| + |
| This is Pegamento's *"sharing is membership"* taken literally: the sheet |
| never moves, and the outside person becomes a scoped member of the instance |
| that owns it. There is no federation story and there will not be one. |
| @@ -460,9 +468,21 @@ that owns it. There is no federation story and there will not be one. |
| ### 8.3 Link sharing |
| |
| **"Sharing is membership" does not forbid link sharing.** It forbids data |
| -crossing an instance boundary, and a link does not move data. This sentence |
| -exists because the rule reads like a prohibition and someone will later |
| -think it was one. (docs-e6, 2026-08-30.) |
| +crossing a *team* boundary (suite ruling 2), and a link does not move data — |
| +whoever holds it reads the sheet here. This sentence exists because the rule |
| +reads like a prohibition and someone will later think it was one. (docs-e6, |
| +2026-08-30.) |
| + |
| +**A link is not a rung on the sharing ladder** (suite ruling 15). A sheet is |
| +private, granted to named people, or shared with the team, and only the team |
| +rung is team-visible — so a sheet that is link-shared but not team-shared is |
| +one no sibling may hold a copy of. Making a link team-visible would turn |
| +"whoever I sent this URL to" into "everyone on the team, findable through |
| +memoria's search", which is a different grant than the one the sharer made. |
| + |
| +**Ruling 12 below is now the suite's rule**, adopted verbatim as suite |
| +ruling 15's read-only half. The doctrine cites it; it stays here as the |
| +original, and the reason it gives is the reason the suite took it. |
| |
| Off by default, high-entropy, revocable, **viewer-or-commenter only, never |
| editor** (ruling 12) — every version row carries an actor, and an anonymous |
| @@ -491,27 +511,30 @@ The home is a **separate repo and spec** (ruling 10), drafted by this |
| session with Docs as a declared consumer. This section records only what |
| Sheets depends on. |
| |
| -### 9.1 The five-call contract |
| +### 9.1 The contract, cited rather than restated |
| + |
| +**Sheets consumes the home contract as the home spec states it, and the |
| +suite contract as `oficina/suite` states it.** Neither is copied here. |
| |
| -1. **Sign-in and session minting** (§8.1 — the home is the identity |
| - authority, not merely a directory). |
| -2. **Directory upsert/revoke** — instance→home on grant change, sending the |
| - **address and the team's sealed display name**; **the home hashes** and |
| - **returns the person ref**, which we store against our member rows. |
| - Carries `kind` (member or guest) and a team-scoped revoke. |
| +This section used to enumerate five calls. It had already caught itself |
| +drifting once — *"the first draft called this the four-call contract and |
| +then admitted a fifth in a subsection; an implementer reading the heading |
| +builds four"* — and the same thing happened again from the other side: the |
| +home now has six calls, with a seventh and eighth designed, and nothing made |
| +this copy notice. The note was right about the mechanism and could not fix |
| +it, because the fix is not to count more carefully. It is to stop keeping a |
| +second copy (suite §10). |
| |
| - *Corrected 2026-08-30: this row previously read "carrying |
| - `HMAC(pepper, …)`", contradicting §9.6 of this same document. An |
| - implementer reading the contract table would have built instance-side |
| - hashing — which needs the pepper on every instance, the design §9.6 |
| - rejects.* |
| -3. **Directory list** for a signed-in person — every team across every |
| - suite app. |
| -4. **Provisioning enqueue** (§9.4 — and see the doctrine divergence there). |
| -5. **Rekey journal pull** (§9.6). |
| +What is Sheets' own, and stays: |
| |
| -*(The first draft called this "the four-call contract" and then admitted a |
| -fifth in a subsection. An implementer reading the heading builds four.)* |
| +- **The home hashes, and returns the person ref**, which we store against |
| + our member rows. An earlier revision of this section said the instance |
| + sends `HMAC(pepper, …)`, contradicting §9.6 of this same document; an |
| + implementer reading it would have built instance-side hashing, which needs |
| + the pepper on every instance. |
| +- **A directory row never grants team standing** (suite ruling 12), whatever |
| + its `kind` says. Membership is the home's own record, written only by an |
| + owner. |
| |
| Instance→home auth follows Pegamento's service contract: per-consumer |
| bearer token stored hashed, consumer identity is its origin, origins are an |
| @@ -722,6 +745,44 @@ window. |
| |
| --- |
| |
| +## 9a. Consumed suite rulings |
| + |
| +The suite sharing doctrine (`oficina/suite`) binds this spec. Read against |
| +**revision 4, commit `210312f`**. |
| + |
| +| # | What it settles for Sheets | |
| +|---|---| |
| +| 1 | The team is the boundary. A team's instances across every app are one trust domain, so a same-team memoria may hold team-visible sheets. | |
| +| 2 | Sharing is membership across teams. Nothing crosses a team label. | |
| +| 3 | Custody and authorization are two rules, and authorization is never cached at any scope. | |
| +| 5 | Two shapes, one switch. The sibling-token switch is independent of whether a home is present. | |
| +| 6 | The egress sentence, suite-wide. | |
| +| 7 | One contract, one module, fixtures as the interface. | |
| +| 8 | Two credentials. A consumer token proves a same-team sibling; an assertion proves a person. | |
| +| 9 | A write names its real actor — the rule §8.3's ruling 12 already served. | |
| +| 12 | Membership is the home's own record. A directory row never grants team standing. | |
| +| 14 | Custody is bounded at acquisition and retired by the feed. | |
| +| 15 | Three rungs and a read-only link. Sheets ruling 12 is the original this adopts. | |
| + |
| +Sheets serves **S1, S2, S3 and S6** wherever sibling consumer tokens are in |
| +its platform config. S6 is Sheets' alone: an enumerated aggregate over cell |
| +refs, capped, never expression text, so memoria can total a column without |
| +holding the sheet. |
| + |
| +**Not yet consumed:** S8 write-as-self (suite §7.2) needs a designated-area |
| +grant in the share UI, and the hand-off (suite §7.1) needs a receipt route |
| +with pending state. Neither is specified here. |
| + |
| +**One thing the doctrine took from Sheets rather than the other way round.** |
| +Ruling 12 — link sharing is viewer-or-commenter, never editor — is now suite |
| +ruling 15's read-only half, and the reason Sheets gave for it is the reason |
| +the suite took it: every version row carries an actor, and an anonymous |
| +editor writes unattributed rows into history. A draft of the doctrine |
| +proposed an anonymous link editor and had to be corrected against this |
| +spec. |
| + |
| +--- |
| + |
| ## 10. Design system |
| |
| `day` theme (ruling 7). rastrillo tokens. |