Public: anyone can read this; the crew can change it.
Decision written: how a person with no account gets in to contribute to a public app #9600
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/9573-decision-written-how-a-person-with-no-ac → main 1 commit fork 1 thread · 1 unresolved
1 file
changed +97
−0
docs/features/guests.md added +97
| @@ -0,0 +1,97 @@ | ||
| 1 | # How a person with no account gets in to contribute | |
| 2 | ||
| 3 | **Status: recommended, not yet chosen.** The owner said on #9428 (2026-11-05) | |
| 4 | that both a forge of one's own and a guest account here should work. This page | |
| 5 | lays out the options and their costs so a person can pick the order. The choice | |
| 6 | is recorded at the bottom once the owner or a writer comments it on #9573. | |
| 7 | ||
| 8 | Signup on the root forge is invite-only (the `signup` setting is `invite`, and | |
| 9 | the static gate `forge-signup-gate` in front of `/signup` serves the | |
| 10 | invite-only page). A stranger who finds a public app and wants to change it has | |
| 11 | no way in. Three ways could give them one. | |
| 12 | ||
| 13 | ## What exists today | |
| 14 | ||
| 15 | - `src/core/roles.ts`: a guest can read, comment and **contribute** (fork a | |
| 16 | public repository and send a pull for review). A guest cannot make | |
| 17 | repositories, run a crew or administer. See `docs/ROLES.md`. | |
| 18 | - `docs/features/guest-pulls.md`: a pull from another forge is a guest pull. Its | |
| 19 | preview gets no variables or forge token and the crew does not review it | |
| 20 | until a writer approves it once. Checks never carry secrets. | |
| 21 | - The `signup` setting (`open`, `invite`, `closed`) and invite links | |
| 22 | (`docs/OPERATING.md`). | |
| 23 | - `/forges/new` and the MCP tool `spawn` give a person a forge of their own. | |
| 24 | ||
| 25 | ## Option A: their own forge, and a guest pull from it | |
| 26 | ||
| 27 | The person runs or is given their own forge, forks the public app there, and | |
| 28 | sends a pull across. It arrives as a guest pull. | |
| 29 | ||
| 30 | - **For:** no account on the root forge at all, so nothing new to abuse here; | |
| 31 | the pull path and its guards already exist; the person owns their work. | |
| 32 | - **Risks:** the highest bar for a newcomer ("run a forge" is not a grandma | |
| 33 | step); a forge needs a machine or hosting, and hosting is not shipped; the | |
| 34 | forge is unknown to us, so every pull is from an unvetted origin, which | |
| 35 | writers must approve one by one. | |
| 36 | - **Cost to build:** low. A clear page that says how, plus the one-command | |
| 37 | deploy (#9571). | |
| 38 | ||
| 39 | ## Option B: an invite request | |
| 40 | ||
| 41 | A stranger asks for an invite on `/signup`: a name and a reason. A person (or | |
| 42 | the crew on automode, as a filter only) approves, and an invite link is sent. | |
| 43 | ||
| 44 | - **For:** keeps signup closed to bots; every account was looked at once; fits | |
| 45 | the invite model already in place. | |
| 46 | - **Risks:** a person must answer every request, so it scales with attention | |
| 47 | and goes stale when nobody is looking; the form is a spam target (needs rate | |
| 48 | limit and validation at the boundary); waiting kills a gamer's momentum; the | |
| 49 | request text is untrusted input a reviewing agent must not follow. | |
| 50 | - **Cost to build:** medium. A request table, an admin list, a limit, and | |
| 51 | notice to the owner. | |
| 52 | ||
| 53 | ## Option C: a guest account limited to forks and pulls | |
| 54 | ||
| 55 | Signup opens for guests only. A guest gets the `contribute` ability already in | |
| 56 | the roles table: fork a public repository, send a pull. Nothing else. | |
| 57 | ||
| 58 | - **For:** the shortest path for a stranger and the one that matches "get users | |
| 59 | using it"; the role already exists, so a guest is already refused crew runs, | |
| 60 | apps and administration. | |
| 61 | - **Risks:** open signup invites bots and storage abuse. Needed first, in this | |
| 62 | order: a storage quota per guest, a low rate limit on signup and on pulls, no | |
| 63 | crew runs and no apps for a guest, guest pulls reviewed by the crew on | |
| 64 | automode and by a person otherwise, and a stranger's pull barred from | |
| 65 | secrets, credentials, permissions and release machinery (#9575). Only then | |
| 66 | may the static `forge-signup-gate` be removed, which is an owner-visible | |
| 67 | switch. Opening `signup` to everyone also lets a guest see what members see | |
| 68 | of public pages, so the limits above must hold before the switch. | |
| 69 | - **Cost to build:** the highest: quota, limits, a guest-only signup path (the | |
| 70 | `signup` setting has no "guests only" value today), and removing the gate. | |
| 71 | ||
| 72 | ## What the crew recommends | |
| 73 | ||
| 74 | **C, with A as the standing alternative on the same page, and B not built.** | |
| 75 | ||
| 76 | 1. Say both ways plainly on every public app and repo: "make an account to send | |
| 77 | a change" and "or use a forge of your own". No one is taught anything; | |
| 78 | the page says what happens to their pull. | |
| 79 | 2. Build C in this order: quotas and rate limits, the guard on a stranger's pull | |
| 80 | (#9575), the guest-only signup value, then the owner removes the gate. | |
| 81 | Until the limits exist, signup stays invite-only and A is the only way in. | |
| 82 | 3. Do not build B. It adds a queue a person must tend and is slower than C for | |
| 83 | the same protection, which C gets from limits and review. | |
| 84 | ||
| 85 | If the owner would rather not open signup yet, A alone is safe today; it costs | |
| 86 | only the clear page and #9571. | |
| 87 | ||
| 88 | ## What this decides for the work that follows | |
| 89 | ||
| 90 | - #9574 (a stranger's path to a first pull) builds the page for A and C. | |
| 91 | - #9575 (a stranger's pull is filtered and guarded) is needed before C opens. | |
| 92 | - No code changes with this page. | |
| 93 | ||
| 94 | ## Decision | |
| 95 | ||
| 96 | Not yet recorded. When the owner or a writer comments the choice on #9573, add | |
| 97 | it here: the option, the date, who chose it. The issue is closed only then. |
Decision is intentionally unrecorded; the issue must stay open until it is filled in.