oficina / home Public

Record oficina.works as the primary domain

Supersedes the provisional platform-default hosts
(<app>.<sqid>.oncarlos.com under Carloku account sqid bds) with the
suite's own domain:

  id.oficina.works           credential origin / RP
  oficina.works              directory, at the apex
  <team>.<app>.oficina.works one team, one instance, one hostname

The team slot is new: the provisional shape had nowhere to put the
per-team hostname that home spec S7 reserves at enqueue.

The RP rename drill (LegacyRPID + a window sized by the guest tail) did
not have to run. No app in the suite has a passkey.Config yet -- sign-in
is magic-link throughout -- so no credential was ever scoped to an
oncarlos.com host. Moving now was free; moving after passkeys ship is
not.

The full-host RP ID constraint survives the move, with a new reason:
oficina.works as an RP ID would be valid at every host in the zone,
including the directory and each team instance, collapsing the split
origins that home ruling 2 exists to create.

Specs 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 462df846d9bddcc7678cdc2586f16169f7fb4a27 parent ad6dd30
1 file changed, +37 −13
  • docs/superpowers/specs/2026-08-30-home-design.md +37 −13

CI passed — run details

Intent

Attributed to this commit: 175 g CO₂e (15712881 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-home-design.md b/docs/superpowers/specs/2026-08-30-home-design.md
index aa0f313..444fbd9 100644
--- a/docs/superpowers/specs/2026-08-30-home-design.md
+++ b/docs/superpowers/specs/2026-08-30-home-design.md
@@ -52,9 +52,10 @@ blind, replaceable*.
| 10 | **Theme is per person, suite-level, resolved before first paint** | Per document; per team; follow-OS only | Paul, 2026-08-30 |
| 11 | **One shared instance — and this is not a divergence** — §2 | Instance-per-person; calling it a divergence | This session, 2026-08-30 |
| 12 | **Sealed at rest, DEK from platform secrets** | Plaintext (a plaintext column is a plaintext bucket leak) | This session, 2026-08-30 |
-| 13 | **Provisional origins are `oncarlos.com` hosts under account `bds`; the RP ID is always the full host** | `carloku.com` (console brand); a suffix RP ID | Corrected 2026-08-30 |
+| 13 | ~~Provisional origins are `oncarlos.com` hosts under account `bds`~~ — superseded by 16. The half that survives: **the RP ID is always the full host** | `carloku.com` (console brand); a suffix RP ID | Corrected 2026-08-30 |
| 14 | **Hand-roll sign-in: subject is an opaque person ref, link state is sealed** — §5.1 | `rastrillo/auth` as shipped (stores readable addresses); blocking on upstream | Paul, 2026-08-30 |
| 15 | **Passkey 2FA is optional per person. Owner-enforceable per-team is NOT in slice one** — §14 | Promising a per-team floor neither spec can build | Paul, 2026-08-30 |
+| 16 | **`oficina.works` is the primary domain — RP `id.oficina.works`, directory at the apex, instances at `<team>.<app>.oficina.works`** — §4 | Staying on `oncarlos.com` until passkeys forced the move; keeping the `bds` slot | Paul, 2026-09-03 |
---
@@ -231,16 +232,31 @@ The directory obtains its session by exchanging an assertion, the same
mechanism instances use (§5.3), so there is one assertion path rather than
two. An XSS on the directory cannot reach the RP.
-**Provisional hostnames (ruling 13).** Account `oficina`, sqid **`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`.
-
-**Never widen the RP ID to a registrable suffix.** 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**,
-asserted by a test.
+**The hostnames (ruling 16, 2026-09-03).** The suite's primary domain is
+**`oficina.works`**, registered and ours. It replaces the provisional
+platform-default addresses `<app>.<sqid>.oncarlos.com`, where `bds` was a
+Carloku *account* sqid — a hosting artifact that earns nothing on a domain
+we own.
+
+- **`id.oficina.works`** — the credential origin. This is the RP.
+- **`oficina.works`** — the directory, at the apex. A different hostname
+ from the RP, which is what this section requires.
+- **`<team>.<app>.oficina.works`** — one team, one instance, one hostname:
+ `acme.docs.oficina.works`, `acme.sheets.oficina.works`. This is the team
+ slot the provisional shape never had, and §7's "team name and hostname
+ reserved at enqueue" needs somewhere to reserve them.
+
+Hosting stays on Carloku; `oficina.works` is a custom domain in front of it,
+with a wildcard certificate per app zone (`*.docs.oficina.works`).
+
+**Never widen the RP ID to a registrable suffix** — and note that the reason
+changed with the domain rather than disappearing. WebAuthn permits an RP ID
+that is a suffix of the origin's hostname, so `oficina.works` would be
+*accepted* for `id.oficina.works`. On `oncarlos.com` the objection was other
+Carloku tenants. On a zone we own it is that `oficina.works` as an RP ID is
+valid at *every* host in the zone — the directory and each team instance
+included — which collapses the split this very section exists to make
+(ruling 2). **The RP ID is the full host**, asserted by a test.
---
@@ -410,9 +426,17 @@ Absent from the first draft, and the abuse suite did not test it.
works inside the attacker's account.
- Both are in gate 3.
-### 5.7 The RP rename drill
+### 5.7 The RP rename drill — not needed for the `oficina.works` move
+
+**Ruling 16 moved the domain before this service enrolled its first
+credential**, which is the whole reason the move cost nothing. At the time
+of the move `home` held no `passkey.Config` at all — sign-in across the
+suite was magic-link only — so no credential had ever been scoped to an
+`oncarlos.com` host and there was nothing to strand. The drill below is
+therefore documented rather than scheduled.
-Provisional hostnames schedule this rather than avoid it. **The mechanism
+Every *later* hostname move pays the full price described here, which is the
+argument for having taken this one early. **The mechanism
exists:** `passkey.Config.LegacyRPID` is *"a relying party this instance
used to be, accepted for assertions (never registration) so a hostname move
doesn't strand enrolled keys"* — verified at source. Set it, run the window,