From 5f09b667425b67ca8daefcb5b18fec017faf424f Mon Sep 17 00:00:00 2001 From: wtclaude Date: Wed, 19 Aug 2026 18:39:40 -0500 Subject: [PATCH] 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 --- PLAN.md | 57 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/PLAN.md b/PLAN.md index 89d20c1..d6cb615 100644 --- a/PLAN.md +++ b/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. --- -- 2.49.1