oficina / sheets Public

Record oficina.works as the primary domain

Supersedes ruling 11 (passkey RP on a provisional oncarlos.com host).
The RP is id.oficina.works; a Sheets instance is
<team>.sheets.oficina.works, one team to one hostname. Hosting stays on
Carloku, with oficina.works as a custom domain in front of it.

The rename drill in S9.7 did not have to run: no app in the suite has a
passkey.Config yet, so no credential was ever scoped to an oncarlos.com
host. The window documented there is sized for the next move, not this
one.

The full-host RP ID constraint survives with a new reason -- on a zone we
own, a suffix RP ID would be valid at every host in it, so the home's
credential would be presentable straight to a Sheets instance, which is
the separation ruling 15 keeps.

Spec only. No code, no behaviour change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJ4p3qTNQqScxS6Z6wp8Pw
Paul Campbell pushed by paul@keymail.dev 8a27bfcc92dbb9883d85182d949e724ab40912b9 parent d7cea4f
1 file changed, +35 −20
  • docs/superpowers/specs/2026-08-30-sheets-design.md +35 −20

CI passed — run details

Intent

Attributed to this commit: 78.0 g CO₂e (8017787 tokens). This is an attribution, not a measurement — usage counted from this commit's own marker forward to the next one on domain/oficina-works, never backward from it. A turn that produced more than one commit books all of its tokens to the last one, and a concurrent session on this branch can add to the same figure. Some of it was priced using the shared default rate, because no model-specific factor row exists yet for at least one model involved. The Carbon view has the repo total, which is never derived from this attribution.

diff --git a/docs/superpowers/specs/2026-08-30-sheets-design.md b/docs/superpowers/specs/2026-08-30-sheets-design.md
index c0142e6..6602356 100644
--- a/docs/superpowers/specs/2026-08-30-sheets-design.md
+++ b/docs/superpowers/specs/2026-08-30-sheets-design.md
@@ -42,13 +42,14 @@ value reaching the replicated SQLite file or any object storage we write.
| 8 | **Cell fill stored as OKLCH intent; imported hex retained** | Intent only (lossy round-trip); absolute hex (breaks in dark mode) | Paul, 2026-08-30 |
| 9 | **Provisioning: the home queues, an operator drains** | A standing console token in a web-facing app | Paul, 2026-08-30 |
| 10 | **The home is its own repo and its own spec** | Keeping it here; Docs drafting it | Paul, 2026-08-30 |
-| 11 | **Passkey RP is an `oncarlos.com` host, provisionally** — §9.7 | A real suite domain now; no passkeys | Paul, 2026-08-30 |
+| 11 | ~~Passkey RP is an `oncarlos.com` host, provisionally~~ — superseded by 18 | A real suite domain now; no passkeys | Paul, 2026-08-30 |
| 12 | **Link sharing is viewer-or-commenter, never editor** | Anonymous link editing | Paul, 2026-08-30 |
| 13 | **Passkey 2FA optional per person, owner-enforceable per team** | Mandatory; none | Paul, 2026-08-30 |
| 14 | **Light/dark is a per-person preference, switchable in the editor** | Per-document; per-team; follow-OS-only | Paul, 2026-08-30 |
| 15 | **One RP: the home's credential origin. Instances never enroll passkeys** — §8.1 | Per-instance passkeys (three teams = three credentials) | Proposed by this session, **confirmed by Paul, 2026-08-30** |
| 16 | **Version history replays inputs and recomputes; derived values are never logged** — §4.3 | Logging derived values (instant restore, log grows with fan-out) | Paul, 2026-08-30 |
| 17 | **Slip order written down: charts first, conditional formatting second. Version history's baseline is restore-a-cell-or-range** — §13 | Holding all eleven at full scope; cutting charts outright today | Paul, 2026-08-30 |
+| 18 | **`oficina.works` is the primary domain; the RP is `id.oficina.works`, instances are `<team>.sheets.oficina.works`** — §9.7 | Waiting until passkeys shipped (the move only stays free until then) | Paul, 2026-09-03 |
---
@@ -664,25 +665,39 @@ requires a **re-announce sweep**, not merely outbox retry — retry
redelivers *failed* upserts and does not re-enumerate every existing grant.
That sweep is a named operator verb, not an emergent behaviour.
-### 9.7 The RP rename drill — smaller than the first draft thought
-
-Ruling 11 puts the RP on a platform-default host provisionally, which
-**schedules** the rename rather than avoiding it.
-
-**The concrete hosts, corrected 2026-08-30.** The account is `oficina`,
-sqid **`bds`** (`console.carloku.com/a/bds/`). Default addresses are
-`<app>.<sqid>.<apps-domain>` and the hosted apps-domain is **`oncarlos.com`**
-— *not* `carloku.com`, which is the console brand and appears nowhere in
-`platform.md`. So the credential origin is an `oncarlos.com` host under
-`bds`, and earlier drafts of this spec naming carloku.com were simply wrong.
-Worth catching here, because the RP hostname is the single most expensive
-string in the document to get wrong.
-
-**Never widen the RP ID to a registrable suffix on a shared platform
-domain.** WebAuthn permits an RP ID that is a suffix of the origin's
-hostname, so `oncarlos.com` would be *accepted* — and it is shared by every
-Carloku tenant, which would scope our credentials across other people's
-apps. The RP ID is the full host, always.
+### 9.7 The RP rename drill — scheduled, then made unnecessary
+
+Ruling 11 put the RP on a platform-default host provisionally, which
+**scheduled** this rename rather than avoiding it. Ruling 18 then ran it
+early, for free.
+
+**The hostnames, settled 2026-09-03.** The suite's primary domain is
+**`oficina.works`**, registered and ours. The credential origin is
+**`id.oficina.works`** — that is the RP — and a Sheets instance is
+**`<team>.sheets.oficina.works`**, one team to one hostname. Hosting stays
+on Carloku, with `oficina.works` as a custom domain in front of it.
+
+This replaces the provisional `<app>.<sqid>.<apps-domain>` on the hosted
+apps-domain `oncarlos.com` under account sqid **`bds`**
+(`console.carloku.com/a/bds/`). `bds` was a hosting artifact and does not
+survive the move. Earlier drafts naming `carloku.com` — the console brand —
+were wrong about the old domain too; none of it matters now except as the
+`LegacyRPID` value, if it is ever needed.
+
+**The drill did not have to run.** At the time of the move no `passkey.Config`
+existed in any app in the suite — sign-in was magic-link throughout — so no
+credential had ever been scoped to an `oncarlos.com` host. The window below
+is sized for the *next* move, not this one, and its cost is the argument for
+having moved before passkeys shipped rather than after.
+
+**Never widen the RP ID to a registrable suffix.** WebAuthn permits an RP ID
+that is a suffix of the origin's hostname, so `oficina.works` would be
+*accepted* for `id.oficina.works`. The objection used to be other Carloku
+tenants on a shared platform domain; on a zone we own it is that such an RP
+ID is valid at every host in the zone — this instance included — so the
+credential the home holds would be presentable straight to a Sheets
+instance, which is the separation ruling 15 exists to keep. The RP ID is the
+full host, always.
**But the mechanism already exists.** `passkey.Config.LegacyRPID` —
verified at source — is *"a relying party this instance used to be, accepted