docs(plan): D13 settles the contact address, and Phase 0 is done #3

Merged
whitlocktech merged 1 commits from docs/contact-address-decision into main 2026-08-20 01:36:16 +00:00

57
PLAN.md
View File

@@ -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.50.9 are grouped where they touch one repo, so the real PR count is smaller than the row count;
`docs` PRs 0.50.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.10.3),
`docs`#173 (0.50.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.
---