docs(plan): D13 settles the contact address, and Phase 0 is done
The domain still has no mailbox. Rather than delay the beta on Cloudflare Email Routing, the org lead elected to publish the existing address. - D13 recorded: whitlocktech@gmail.com is the published contact, held only in brand.json so a later privacy@/security@ is a file copy, not a rebuild. - Phase 0 PR 0.10 withdrawn -- SECURITY.md already carries that address. - checkFacts.mjs gains the rule that keeps the promise true: no email address in the source outside brand-default/brand.json. - Phase 0 marked complete (docs#172, docs#173, .profile#4, Module-uo#19). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
57
PLAN.md
57
PLAN.md
@@ -1,7 +1,8 @@
|
||||
# runicgateway.com — design of record
|
||||
|
||||
**Status:** decisions taken by the org lead on 2026-08-19 and recorded in §5. Nothing is built yet.
|
||||
**Date:** 2026-08-19 (revision 2)
|
||||
**Status:** decisions taken by the org lead on 2026-08-19 and recorded in §5. **Phase 0 is
|
||||
complete**; Phase 1 is the next build step.
|
||||
**Date:** 2026-08-19 (revision 3)
|
||||
**Repo:** `RunicGateway/runicgateway.com`
|
||||
**AI-assisted:** yes — drafted by Claude, per the org's AI-usage disclosure policy.
|
||||
|
||||
@@ -11,7 +12,9 @@ build modules and integrations for it. A third arrives with the Android closed b
|
||||
who want the app.
|
||||
|
||||
Revision 1 asked five open questions. Revision 2 records the answers as decisions and designs
|
||||
against them. §14 lists the three facts still outstanding — none of them block starting.
|
||||
against them. Revision 3 marks Phase 0 shipped and adds **D13**, which settles the contact address
|
||||
§14 N2 had left open — the domain still has no mailbox, and the org lead chose to publish the
|
||||
existing one rather than delay the beta.
|
||||
|
||||
---
|
||||
|
||||
@@ -197,7 +200,7 @@ verified values from §2.
|
||||
| 0.7 | `docs` | `README.md` — index entries for `TEAMS.md`, `ARCHITECTURE.md`, `TRUSTED_DEVICES_MFA.md`, `MODERATION_APPEALS.md`. |
|
||||
| 0.8 | `docs` | `website/BACKEND_DESIGN.md` — retitle for the game-agnostic core. |
|
||||
| 0.9 | `Module-uo` | `README.md` — Phase 4 marked complete. |
|
||||
| 0.10 | `docs` | `SECURITY.md` — the public vulnerability contact moves from a personal Gmail to `security@runicgateway.com` (§14, N2). Conditional on that address existing. |
|
||||
| ~~0.10~~ | ~~`docs`~~ | ~~`SECURITY.md` — the public vulnerability contact moves from a personal Gmail to `security@runicgateway.com`.~~ **Withdrawn 2026-08-19 by D13.** The domain has no mailbox and the org lead elected to publish the existing address rather than wait; `SECURITY.md` already carries it and needs no change. |
|
||||
|
||||
0.5–0.9 are grouped where they touch one repo, so the real PR count is smaller than the row count;
|
||||
`docs` PRs 0.5–0.8 land as one hygiene PR.
|
||||
@@ -205,6 +208,10 @@ verified values from §2.
|
||||
**Nothing in Phase 0 changes code or a contract.** Each PR corrects documentation to match what the
|
||||
code already does, and each cites the source of truth in its description.
|
||||
|
||||
**Phase 0 is complete.** It shipped on 2026-08-19 as four merged PRs — `docs`#172 (0.1–0.3),
|
||||
`docs`#173 (0.5–0.8), `.profile`#4 (0.4), `Module-uo`#19 (0.9) — plus 0.10 withdrawn as above.
|
||||
Every fact the site is about to quote now agrees across the repositories.
|
||||
|
||||
---
|
||||
|
||||
## 5. Decisions of record
|
||||
@@ -219,12 +226,13 @@ Taken by the org lead (Colby Whitlock) on 2026-08-19. Recorded so they are not r
|
||||
| **D4** | **Real web screenshots**, captured from the local review stack, not placeholders. | §13 phase 6. Needs seeded, presentable demo content. |
|
||||
| **D5** | **Claude drafts `/privacy` and `/terms`** from what the code actually collects; the org lead reviews before ship. | §9. |
|
||||
| **D6** | **Ship the image and compose file; the org lead deploys.** DNS and TLS terminate at their existing reverse proxy. | §13 phase 9. This repo never touches the production host. |
|
||||
| **D7** | **The site sends no email at all.** No SMTP, no notifications, no mailbox behind the domain yet. | §8 designs the signup so it works anyway — see "The opt-in link removes the need for email". A contact address is still required (§14, N2). |
|
||||
| **D7** | **The site sends no email at all.** No SMTP, no notifications, no mailbox behind the domain yet. | §8 designs the signup so it works anyway — see "The opt-in link removes the need for email". A contact address is still required; D13 supplies it. |
|
||||
| **D8** | **Understated honesty.** The site reads as finished; factual badges appear only where they save a reader wasted effort. **The Integration Kit stays marked draft until a second module is successfully built against it.** | §11, §10. A status with an exit criterion, not a mood. |
|
||||
| **D9** | **No analytics.** No tracking scripts, no third-party requests, no cookie banner. | Reverse-proxy access logs are the only traffic data. |
|
||||
| **D10** | **Support routes to Discord and Gitea issues.** Invite: `https://discord.gg/t2Jav8yT4g`. | §10. Discord is the front door; Gitea takes issues from anyone with an account, which today is nobody outside the org — §14, N3. |
|
||||
| **D11** | **Keep the existing emblem.** `runic-emblem.png` is the mark on both the website and the Android launcher icon; the site adopts it rather than drawing a new one. | §11. Revision 1's "draw a new geometric mark" recommendation is withdrawn. |
|
||||
| **D12** | **A public demo instance is planned but out of scope today** — a Proxmox VM running the full stack including ServUO, with restricted settings and an hourly automatic reset. | §15. The IA reserves the slot so it lands later without a restructure. |
|
||||
| **D13** | **Publish the existing address.** No mailbox has been created at the domain and the org lead elected not to wait for one: `whitlocktech@gmail.com` is the published contact wherever the site needs one — `/privacy`, `/terms`, `/community`, the Play listing — and `docs/SECURITY.md` keeps the address it already carries. | Taken 2026-08-19, superseding §14 N2 as a blocker. The address lives **only** in `brand.json` (§7), never in prose, so moving to `privacy@`/`security@` later is a file edit and a restart. Phase 0's PR 0.10 is withdrawn, not deferred. |
|
||||
|
||||
---
|
||||
|
||||
@@ -466,7 +474,7 @@ Organised by what a reader is trying to do. A reader should never need to know t
|
||||
| `/integrations/` | Discord, mobile + ntfy push, SSO — with an explicit "not built" list |
|
||||
| `/app/` | The Android app: what it does, the 14 existing screenshots, and the beta CTA |
|
||||
| `/beta/` | The closed-beta signup (§8) |
|
||||
| `/community/` | Discord (`discord.gg/t2Jav8yT4g`) as the front door, the Gitea org for code and contributions, `security@` for vulnerabilities — the split in §14 N3 |
|
||||
| `/community/` | Discord (`discord.gg/t2Jav8yT4g`) as the front door, the Gitea org for code and contributions, the `brand.json` contact address for vulnerabilities (D13) — the split in §14 N3 |
|
||||
| `/privacy/`, `/terms/` | §9 |
|
||||
|
||||
**Feature grouping**, using project terminology:
|
||||
@@ -594,6 +602,12 @@ a mechanism rather than diligence:
|
||||
|
||||
Same mechanism and the same intent as the Integration Kit's `checkCoreApi.js`: when the platform
|
||||
moves, this repo goes red so someone updates the site. That failure is the feature.
|
||||
|
||||
It carries one rule that is not a version: **no email address may appear anywhere in the source
|
||||
except `brand-default/brand.json`.** D13 publishes a personal address that is meant to be
|
||||
replaceable by a file copy, and that promise survives exactly as long as nobody types the address
|
||||
into a paragraph. Same argument as `checkTokens.mjs` and colour literals — the check is the
|
||||
mechanism, diligence is not.
|
||||
- **`scripts/checkLinks.mjs`** — every internal link resolves; every outbound link into a
|
||||
`RunicGateway` repo points at a branch path, not a commit permalink.
|
||||
- **`scripts/checkTokens.mjs`** — no colour literal outside the token file (§7).
|
||||
@@ -631,22 +645,33 @@ None of these block starting Phase 0 or Phase 1.
|
||||
**N1 — Resolved.** `runicgateway.com` is registered through **Cloudflare**, with DNS on Cloudflare.
|
||||
The domain does not resolve to anything yet; the record is pointed at the host in phase 12.
|
||||
|
||||
**N2 — A contact address at the domain. Recommendation: Cloudflare Email Routing**, now that N1
|
||||
confirms the domain is on Cloudflare. It is free, unlimited, receive-only, and adds its own MX and
|
||||
SPF records automatically. Three addresses, all forwarding to the existing inbox:
|
||||
**N2 — Settled by D13, and no longer blocking anything.** As of 2026-08-19 no mailbox exists at the
|
||||
domain and the org lead chose not to wait for one. **`whitlocktech@gmail.com` is the published
|
||||
contact**, and `docs/SECURITY.md` keeps the address it already carries.
|
||||
|
||||
| Address | Used by |
|
||||
The site is built so this is reversible for the cost of a file edit. The address is a `brand.json`
|
||||
field (§7), read by `/privacy`, `/terms`, `/community` and the OG/structured metadata; **it appears
|
||||
in no page's prose and in no committed markdown**, and `checkFacts.mjs` (§12) fails the build if a
|
||||
literal `@` address is found outside `brand-default/brand.json`. Changing the published contact is
|
||||
then the same operation as changing the logo — copy a file, restart the container.
|
||||
|
||||
The recommendation stands for whenever it is wanted: **Cloudflare Email Routing**, now that N1
|
||||
confirms the domain is on Cloudflare. Free, unlimited, receive-only, and it adds its own MX and SPF
|
||||
records automatically. Three addresses, all forwarding to the existing inbox:
|
||||
|
||||
| Address | Would replace the Gmail in |
|
||||
|---|---|
|
||||
| `hello@runicgateway.com` | The Play store listing's contact email; `/community` |
|
||||
| `privacy@runicgateway.com` | `/privacy` — deletion and data requests (§9) |
|
||||
| `security@runicgateway.com` | `docs/SECURITY.md`, which currently publishes a personal Gmail on a public repo |
|
||||
| `security@runicgateway.com` | `docs/SECURITY.md` (a one-line `docs` PR, whenever) |
|
||||
|
||||
Pair it with Gmail's "Send mail as" to reply from the addresses rather than the underlying inbox.
|
||||
Routing is receive-only, which is sufficient — the site sends nothing (D7). If double opt-in is ever
|
||||
wanted later, Resend or Brevo's free tier plus DKIM/DMARC would cover sending.
|
||||
|
||||
Retiring the personal address from `SECURITY.md` is a one-line `docs` PR and rides along with
|
||||
Phase 0.
|
||||
**One consequence to accept knowingly:** a Play store listing's contact email is public, and so is
|
||||
this site, so the address will be scraped. That is the trade the org lead took against delaying the
|
||||
beta; the mitigation is that switching later costs one file.
|
||||
|
||||
**N3 — Gitea registration.** Open registration previously drew a flood of spam accounts, so it is
|
||||
disabled, and "file an issue" is therefore a wall for anyone outside the org. Reopening it safely on
|
||||
@@ -683,9 +708,9 @@ MAX_CREATION_LIMIT = 0 ; -1 is unlimited; 0 means no user may
|
||||
**Consequently, `/community` should describe an honest split rather than one channel:** Discord
|
||||
(`discord.gg/t2Jav8yT4g`) is the front door for questions, bug reports and the beta announcements —
|
||||
instant and unauthenticated. Gitea is where the code lives, is publicly readable without an account,
|
||||
and takes issues and pull requests from contributors willing to request one. `security@` is the
|
||||
private channel for vulnerabilities. That page is written the same way whether or not N3 is
|
||||
actioned; only one sentence changes.
|
||||
and takes issues and pull requests from contributors willing to request one. The `brand.json`
|
||||
contact address (D13) is the private channel for vulnerabilities. That page is written the same way
|
||||
whether or not N3 is actioned; only one sentence changes.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user