@bongos/core 1.19.430 → 1.19.432

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.bongos-core.json +64 -44
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +2 -0
  4. package/clients/bongos-client/index.cjs +2 -0
  5. package/clients/bongos-client/index.d.ts +3 -0
  6. package/clients/bongos-client/index.mjs +2 -0
  7. package/docs/adr/0215-the-recruiter-sliver-is-a-ceiling-not-a-step.md +116 -0
  8. package/docs/adr/0216-a-fake-pool-interpreter-must-fail-loudly-not-silently-ignore.md +102 -0
  9. package/docs/adr/README.md +2 -0
  10. package/docs/api/openapi.json +64 -3
  11. package/docs/api-reference.md +3 -2
  12. package/docs/copy-inventory.md +48 -48
  13. package/docs/copy-registry.json +57 -57
  14. package/docs/file-map.md +1 -0
  15. package/docs/module-api-changelog.md +4 -0
  16. package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
  17. package/modules/hall-ui/public/settings.html +1 -1
  18. package/modules/hall-ui/public/settings.js +17 -8
  19. package/modules/platform-identity/account-visibility.js +47 -0
  20. package/modules/platform-identity/platform-identity.js +4 -4
  21. package/modules/platform-identity/recruiter-sliver.js +197 -0
  22. package/modules/platform-identity/routes/scouting.js +58 -0
  23. package/package-lock.json +2 -2
  24. package/package.json +1 -1
  25. package/src/module-api.js +1 -1
  26. package/tests/account_privacy_flags.mjs +115 -9
  27. package/tests/application_echo.mjs +43 -9
  28. package/tests/application_lifecycle.mjs +18 -7
  29. package/tests/connections_ownership.mjs +44 -4
  30. package/tests/effective_visibility_predicate.mjs +137 -50
  31. package/tests/government_require_permission.mjs +22 -0
  32. package/tests/handle_machinery.mjs +15 -1
  33. package/tests/hub_profile_leak.mjs +18 -4
  34. package/tests/own_session_revoke.mjs +77 -9
  35. package/tests/profile_connections_ui.mjs +49 -10
  36. package/tests/profile_privacy_owner_view.mjs +68 -37
  37. package/tests/profile_rollup_consent.mjs +46 -14
  38. package/tests/profile_route.mjs +6 -0
  39. package/tests/recruiter_sliver_boundary.mjs +841 -0
  40. package/tests/scouting_owner_access_and_reach.mjs +175 -39
  41. package/tests/scouting_rollup_fanout.mjs +15 -4
@@ -0,0 +1,102 @@
1
+ # ADR 0216 — A fake-pool interpreter must FAIL LOUDLY on what it cannot model; the refusal is uniform, the interpreters stay separate
2
+
3
+ - **Status:** accepted
4
+ - **Date:** 2026-08-29
5
+ - **Task:** [task 1003354](https://cloudbongos.com/builders#/task/1003354) (folding in idea 1000877, raised by the adversarial review of [task 1002968](https://cloudbongos.com/builders#/task/1002968))
6
+ - **Relates to:** [ADR 0202](<redacted>.md) D4 and [ADR 0213](<redacted>.md) (the predicates these interpreters stand in for), [ADR 0215](<redacted>.md) D7 (where the structure guard was first written), [ADR 0091](<redacted>.md) §2 (deliberate duplication across a boundary)
7
+
8
+ ## Context
9
+
10
+ Nine test files in this repo carry a **fake pool** — an in-memory Postgres substitute whose row filter is derived from *each statement's own `WHERE` text* rather than hand-written. That design is deliberate and good: it is what makes a proof like `tests/connections_ownership.mjs` say something about the real query instead of about a canned response. Delete `addressee_github_id = $2::bigint` from the real SQL and the fake genuinely stops applying it, so a stranger's row genuinely moves and the test genuinely reds.
11
+
12
+ The design has one failure mode, and it is silent: **a term the interpreter does not recognise is simply not applied.** A predicate the fake cannot read degrades to *no* predicate, the boundary becomes vacuous, and every assertion above it keeps passing. Each file already understood a piece of this and guarded it:
13
+
14
+ - an unread `$N` placeholder throws (all nine);
15
+ - a literal comparison on an unknown column throws (four);
16
+ - an unmodelled `IS [NOT] NULL` throws (two, added by [ADR 0213](<redacted>.md)).
17
+
18
+ Every one of those guards is a **term** guard, and three separate reviews found the same thing: the term list is not the predicate.
19
+
20
+ **The missing term.** ADR 0213 made consent two columns — `profile_state = 'active' AND terms_accepted_at IS NOT NULL`. `tests/scouting_owner_access_and_reach.mjs` modelled the first and not the second. A `NULL` test is a *third syntax*: the placeholder sweep scans `$N`, the literal sweep matches `col = '…'`, and neither can see `IS NOT NULL` at all. So the term was dropped in silence and the suite reported **17 passed, 0 failed** while modelling a predicate the database no longer had — inside a file whose own header states that exact failure is impossible.
21
+
22
+ **The rewritten joiner.** The adversarial review of task 1002968 found the deeper one. An interpreter that COLLECTS the terms it recognises and `AND`s them **re-imposes an `AND` the SQL may no longer contain.** Rewrite a predicate's `AND` to `OR` and Postgres serves every *active* account on the platform — private ones included — or lets any builder revoke any session by id; the term-collecting fake answers exactly as it did before, and every isolation and 404 assertion in the file stays green. Task 1002968 fixed the three copies it owned and filed the rest as idea 1000877.
23
+
24
+ **Recognition is not application.** ADR 0213's own first draft checked only that the column *name* was recognised, and a mutation deleting the filter still passed. It needed a second set to prove the term had been turned into a filter — which is bookkeeping that can itself go stale.
25
+
26
+ The common shape of all three is one sentence: **the interpreter silently answered a question it was not asked.**
27
+
28
+ ## Decision
29
+
30
+ ### D1 — The governing rule: an interpreter that cannot model a term must REFUSE the statement, never ignore the term
31
+
32
+ This is the rule the fake-pool pattern always implied and never stated. It is not "model every term" — a test fake is allowed to be incomplete. It is that **incompleteness must be loud.** A statement carrying anything this interpreter cannot faithfully reproduce is an error thrown at the test, not a filter quietly dropped from the answer.
33
+
34
+ Refusing is safe in a way ignoring is not, and the asymmetry is the whole argument: a refusal fails the build *today*, in the session that changed the SQL, with the unreadable text in the message. A silent drop fails nothing, ever, and the proof above it becomes decorative without anyone learning that it did.
35
+
36
+ ### D2 — The mechanism is a CONSUMING parse with a pure-conjunction residue check
37
+
38
+ Term guards cannot express D1, because a guard has to know a term exists before it can complain about it — and the whole problem is the terms nobody thought of. So the interpreter is inverted: instead of listing what it recognises, it accounts for **everything the clause contains**.
39
+
40
+ Each recognised term is matched, modelled, and **spliced out of the text**. Whatever survives is exactly the part the interpreter did not understand, and it must be nothing but whitespace, parentheses and `AND`:
41
+
42
+ ```js
43
+ if (!/^[\s()]*(?:AND[\s()]*)*$/.test(residue)) throw new Error(`fake pool: unmodelled boolean structure …`);
44
+ ```
45
+
46
+ That single check subsumes every term guard that came before it and closes all three defects at once. An unmodelled `IS NOT NULL` survives in the residue. An `OR`, a `NOT`, a `CASE` survives in the residue. And **recognition can no longer come apart from application** — a term the interpreter recognised but did not apply is, by construction, still there — which retires ADR 0213's `modelled`-set bookkeeping rather than maintaining it.
47
+
48
+ A legitimate `OR` — the handle rename window, connections' either-side clause, the session-expiry disjunction, the rescind transition guard — is consumed as a **whole unit**, which is both how it survives the check and how it stays honest: a matcher that tore one in half would leave a dangling `OR` and be refused.
49
+
50
+ Two term guards are kept in front of the structure guard, not because they add coverage but because they add a **better error**: an unreadable `$N` or an unknown column is reported as the thing it is, rather than as leftover text.
51
+
52
+ ### D3 — The interpreters stay SEPARATE; only the refusal is uniform
53
+
54
+ Nine copies of nearly-identical machinery is the shape that normally demands extraction, and it was considered and rejected. Task 1002968 concluded these are independent by construction; this ADR agrees, with the reason written down:
55
+
56
+ **What differs is the term vocabulary, and it differs completely.** These interpreters stand in for different tables — `platform_identity_accounts`, `platform_identity_connections`, `builder_sessions`, `access_requests`, `platform_identity_application_echoes`, `<redacted>` — and share almost no term. A shared registry would have to accept every table's vocabulary, which makes it a small SQL engine: more code than the copies it replaces, harder to reason about, and a new place for a bug to hide *behind* the guard rather than in front of it. It would also couple unrelated proofs — a session-revoke test would fail to a change in a connections matcher.
57
+
58
+ **What must never differ is the refusal**, and that is three lines and one regex. So the discipline is: identical guard, identical error message, in every copy — and each copy carries its **own calibration test** pinning the four refusals (unknown literal, unread placeholder, unmodelled `NULL` test, `OR`) plus a `doesNotThrow` over the real composed predicate, so the guard is a filter on the unreadable and not a blanket refusal.
59
+
60
+ That per-file calibration is the anti-drift mechanism a shared helper would otherwise have provided, and it is strictly better at the job: a shared helper proves the guard exists *somewhere*; a calibration test in each file proves the guard is *reached* by that file's own statements.
61
+
62
+ ### D4 — A modelled term proves nothing until a fixture makes it observable
63
+
64
+ The corollary, learned twice in one session. Modelling `terms_accepted_at IS NOT NULL` while every fixture carries an acceptance is a filter that filters nothing: delete the term from the real predicate and the answer does not change, so the mutation does not bite and the proof is cosmetic.
65
+
66
+ Every axis a predicate carries therefore needs **one fixture that differs on that axis alone**. Three were added here — a pre-terms account in the scouting directory and in the real-DB rollup proof, and a pending membership in the application echo — each differing from the control in exactly one column, so the mutation that deletes the term has somewhere to land.
67
+
68
+ Where a file deliberately does *not* carry such a fixture because another file owns that matrix, the comment says so. An absence that is a decision reads differently from an absence that is an oversight, and only the first survives the next reader.
69
+
70
+ ### D5 — Every copy is verified BY MUTATION, against the real source
71
+
72
+ No copy was accepted on green. For each, a term was deleted or an `AND` rewritten to `OR` **in the real module**, the file was required to go red, and the source was reverted. Ten mutations, ten reds, every one of them a 0-failure pass before this work:
73
+
74
+ | mutation (in real source, reverted) | file | before → after |
75
+ |---|---|---|
76
+ | `accountActiveSql`: delete the acceptance term | `scouting_owner_access_and_reach` | 0 → 2 failed |
77
+ | `accountVisibleSql`: `AND` → `OR` | `scouting_owner_access_and_reach` | 0 → 10 failed |
78
+ | `accountActiveSql`: delete the acceptance term | `effective_visibility_predicate` | 0 → 2 failed |
79
+ | `accountVisibleSql`: `AND` → `OR` | `effective_visibility_predicate` | 0 → 8 failed |
80
+ | `accountVisibleSql`: `AND` → `OR` | `profile_privacy_owner_view` | 0 → 3 failed |
81
+ | `listRecentApplications`: `AND` → `OR` | `application_echo` | 0 → 1 failed |
82
+ | `listMembershipsForAccount`: `AND` → `OR` | `application_echo` | 0 → 6 failed |
83
+ | `listMembershipsForAccount`: delete the pending term | `application_echo` | 0 → 3 failed |
84
+ | `acceptConnection`: `AND` → `OR` | `connections_ownership` · `profile_connections_ui` | 0 → 4 · 0 → 1 failed |
85
+ | `revokeSessionForBuilder`: `AND` → `OR` | `own_session_revoke` | 0 → 4 failed |
86
+ | `listActiveSessionsForBuilder`: delete `revoked_at IS NULL` | `own_session_revoke` | 0 → 2 failed |
87
+
88
+ ## Consequences
89
+
90
+ - **Nine fake pools now refuse what they cannot read.** `tests/recruiter_sliver_boundary.mjs` (where the pattern originated), `effective_visibility_predicate`, `profile_privacy_owner_view`, `scouting_owner_access_and_reach` (both of its filters), `connections_ownership`, `profile_connections_ui`, `own_session_revoke`, `application_echo`, `application_lifecycle`. `canonical_profile_url` is deliberately untouched: its residue must be **empty**, which is strictly stronger, so it already refuses an `OR`.
91
+ - **Adding a term to a shared predicate now BREAKS the tests that model it**, loudly, in the session that adds it — instead of being silently absorbed. That is the intended cost and the entire point: ADR 0213 tightened `accountActiveSql` and five proofs absorbed the change without noticing.
92
+ - **`own_session_revoke.mjs` had no calibration test at all** and three silently-permissive paths, including a clause with no readable term yielding an empty filter that matched every row. On a table where the predicate *is* the own-scope boundary.
93
+ - **`application_echo.mjs` was deleting a term before interpreting it** — `membership_kind <> 'pending'` was `.replace`d out of the clause, so dropping it from the real query would have been invisible (the replace would simply no-op). Stripping a term you do not want to model is the same defect as ignoring one; the term is modelled now.
94
+ - **A residue check must strip the statement's tail** (`ORDER BY`, `RETURNING`, `LIMIT`) and consume table aliases, or it refuses correct statements. Both were found by the guard failing honestly on real SQL, which is the guard working.
95
+
96
+ ## Alternatives rejected
97
+
98
+ - **One shared interpreter module.** D3. The vocabulary is per-table and shares almost nothing; the shared thing would be a small SQL engine, and it would couple unrelated proofs.
99
+ - **A fitness check asserting every fake pool carries the guard.** Tempting, and it would catch a *new* copy written without one. Rejected for now: it would have to identify "a fake pool" by heuristic, and a heuristic gate over test internals is a maintenance surface with a false-positive cost. The per-file calibration tests hold the copies that exist; a tenth copy written without one is a review question. Recorded here as the known gap rather than papered over.
100
+ - **Keeping the `KNOWN_NULL_TESTS` + `modelled` pair alongside the structure guard.** Strictly weaker and now redundant: an unapplied term is still in the residue. Two sets to keep in sync, for nothing.
101
+ - **Parsing the boolean tree properly.** A real parser would let the fake *model* an `OR` rather than refuse it. That is a worse trade for a test double: refusing is a one-line invariant, and no statement in this repo needs a disjunction the unit-consumption approach cannot handle.
102
+ - **Accepting green as verification.** The failure this ADR exists for is invisible to a passing suite, by definition. D5.
@@ -300,6 +300,8 @@ This keeps the decision history honest and traceable.
300
300
  | 0212 | [**The connections section is built on the profile page that exists, and it addresses a builder by asking the API to name them** ([task 1002296](https://cloudbongos.com/builders#/task/1002296), R20 · goal 1000045 criterion C6 — the UI half of the connections wave). The profile-page spec puts section 6 on the canonical `cloudbongos.com/u/<handle>`, which [task 1002806](https://cloudbongos.com/builders#/task/1002806) proved does not exist (no route, no page, no search entry, no sitemap row) and which belongs to goal 1000048 R14. Decisions: (1) **section 6 lands in the reserved slot R04 left on the hall profile page** (`modules/hall-ui/public/profile.{html,js}`), as a separate `profile-connections.js` so neither the page script nor `platform-identity.js` grows against its line ratchet, and it follows the CROSS-PROJECT section’s contract exactly — the markup ships `hidden` and reveals only where the hub answered, so an instance without `platform-identity` never renders it. It does not pre-empt the canonical page, which inherits the same three own-scope calls. (2) **Addressing: the page hands the API the `github_login` it holds and uses the `handle` the response echoes back for every write** — core `GET /builders/:id/profile` whitelists nine columns and `handle` is not one of them, and widening that whitelist is task 1002804’s canonical-URL work. `findAccountByHandle` already resolves current-or-previous handle and the route answers with the canonical one, which is the same move the API built for a stale Connect link. It fails closed into the deliberately indistinguishable 404 (unknown / provisional / private stranger), so the ONE honest gap is stated rather than discovered: **a twice-renamed handle has no connect button on this surface**, and it disappears when `/u/<handle>` lands. (3) Three rendering rules, enforced by `tests/profile_connections_ui.mjs` (real router over a WHERE-derived fake pool on a real socket, real client above it): `degree: null` renders "Out of network" and never "not connected", with copy that is BYTE-IDENTICAL whether `truncated` was set — varying it would rebuild the ADR 0207 L2 side channel in words; a sent request claims exactly `201 { status: 'pending' }`, so a re-ask swallowed by the 90-day cooldown simply shows "Connect" again next load with no explanation anywhere; and every count is the length of the list beside it, with `seen_at` and `truncated` never reaching the screen. Rejected: waiting for the hub page (it would block C6’s proof on another goal); building `/u/<handle>` here (the spec says only one such page gets built); adding `handle` to the core profile whitelist or to `cross_project` (the latter is `null` under `hide_stats`, which is exactly where the edge must still show — ADR 0202 D4 §3); resolving through public `GET /profiles/:handle` (it 404s for a private account the viewer IS connected to). Deferred and named: a public per-builder connections list (there is deliberately no such route), removal from the other person’s profile, and sections 7–8.](<redacted>.md) | platform identity / social graph / hall UI |
301
301
  | 0214 | [**The canonical profile URL gets one resolver, and it stays dark until the page it names actually resolves** ([task 1002804](https://cloudbongos.com/builders#/task/1002804), P08 · goal 1000045 criterion C1 — the canonical/redirect wiring). Profile-page spec Decision 1 wants `rel=canonical` on the instance, a link-out to the hub, and a numeric-id redirect; `/u/<handle>` does not exist (goal 1000048 R14 is `backlog`, and R01 — the ADR that fixes its PATH — is unwritten, while R03 proposes moving platform pages under `/bongos/…`). Decisions: (1) **one resolver** (`modules/platform-identity/canonical-profile.js`) answers where a profile lives, and it answers `null` while the page 404s — a canonical naming a non-indexable URL consolidates nothing and risks the one page that works, and the address is not even settled yet; one boolean flips all three surfaces together, and a test reds if a `/u/` route lands while it is still false. (2) **`{{hubOrigin}}`** joins `applyBrandTokens` (own `publicOrigin` on the hub, `loadIdpConfig().origin` when federated, `''` otherwise) — the server-side stamp ADR 0171 D1 asked for — delivered as a `<meta>`, never inside an `href`, because an empty value in an href degrades to a same-host URL claiming to be the hub. (3) **`handle` joins `GET /builders/:id/profile`** under the EXISTENCE predicate (`isAccountVisible`), not the rollup one: `hide_stats` suppresses numbers and never addressability, and the `handle`+`cross_project: null` pair is already published unauthenticated by `GET /profiles/:handle`. This closes ADR 0212’s stated gap — a twice-renamed builder now has a connect button. (4) **The hub redirects and a federated instance canonicalizes**, which is how Decision 1’s two apparently contradictory clauses reconcile: the hub serves the same person at both URLs, a federated instance serves genuinely different content. (5) **The redirect is not an existence oracle** — its non-redirect branch is the ordinary working page, absent/provisional/private are byte-identical, and the one bit it exposes is what `/profiles/:handle` already answers with 200-vs-404.](<redacted>.md) | platform identity / SEO / hall UI |
302
302
  | 0210 | [**The recruiting directory graduates on an instance-asserted ownership claim, and the recruiting opt-out gates the directory and nothing else** ([task 1002290](https://cloudbongos.com/builders#/task/1002290), R14, goal 1000045 criterion C5 — "project owners, not only Archons, browse builder profiles to recruit"). Two independent problems wore one task id. The reach flag `recruiter_discoverable` protected nobody — task 1002967 said so, and the Settings row stayed in the future tense because of it. And "widen the Archon-only /scouting" was already stale (ADR 0157 lowered `project.curate` to metic) while hiding the real question: **a project owner is not a rank**, and someone who registers a project is an Archon on their OWN instance and usually a bare `xenos` on the hub where the directory lives, so no floor reaches them without reaching every stranger. **D1** "project owner" on the hub is `<redacted>.membership_kind = 'owner'` — written by the PROJECT itself at `POST /sso/membership/check-in` from its own first-admin config, and refused unless the hub's own `signin_verified_at` witness stands (ADR 0205) — and never `platform_identity_projects.owner_github_id`, the hub-curated column ADR 0201 D3 names and forbids; the prohibition is about a hub-held list consulted before an ADMISSION on someone else's box, and this is the hub reading the instance's own mirrored claim before a read of the hub's OWN directory. **D2** the two doors are an OR in `modules/platform-identity/scouting-authz.js` (the `goal-authz.js` owner-or-rank shape, kept out of `platform-identity.js` at its size ratchet): ownership is asked first and a "no" falls through to the UNMODIFIED `requirePermission`, so a refusal keeps its exact code, `required`/`held` and floors map — the widening can only admit; the atom is spelled in the ROUTE's middleware list, because a gate hidden in the helper would make `route-rank-check.js` and `gen-api-docs.js` record this privileged route as `any-builder`; and a broken ownership read falls closed onto the rank door rather than admitting or 500ing. No atom is minted — `project.recruit` belongs to the console wave (spike 1002786 R3). **D3** `PAGE_GATES` gains an optional `alsoAdmits` naming a function on the `platform-identity.hub` port, declared on `requireProjectCuratePage` alone and consulted only after the permission check refused, so the `/people` shell admits exactly the two audiences its data route does; absent port, absent function or a throw all deny. **D4** the reach COALESCE gets its SQL twin in `account-visibility.js` (its sole owner) and composes into `scoutingListableSql` = rollup AND reach, which `listScoutingRollup` joins — but reach is deliberately NOT folded into `rollupVisibleSql`, because the community spec D3 says the opt-out governs the recruiting surface only and folding it down would silently empty a future public leaderboard. **D5** no migration: both columns exist and migration 003's `(github_id)` index already serves the probe. **D6** the ownership query JOINs `platform_identity_sso_clients` on `status='active'` — a membership row never expires and nothing ages it out, so suspending the client (the lever that already stops a project signing anyone in) had to revoke the read it derives, or suspending a rogue project would leave its owner reading every builder on the platform forever. The task's own adversarial review also found the sole-owner drift guard was matching only the UNALIASED spelling of the reach COALESCE — i.e. not the one that ships — and two fail-open defaults (a prototype-reachable `alsoAdmits`, and an alias guard resting on template evaluation order); all three fixed and mutation-checked. ⚠ Honest limits recorded, not fixed: the hall NAV still hides People from a project owner (task 1003349, sequenced with R15 which owns that surface), the `touchMembership` write path stays as ADR 0205 left it, and `openapi.json` cannot express "or owner". ⚠ And DELEGATES do not reach the directory yet (blocker 1000122 + task 1003350, linked) — an instance reports `owner` for its first admin only, so the registrant half works and the delegate half needs the instance to report `owner` for any archon, which changes a cross-version wire contract and a shipped bucketing; filed as blocker 1000122, and nothing here changes when it is answered. Rejected: lowering the floor further (a floor low enough to admit a registrant excludes nobody); a `project.owner` atom (ADR 0201 D3 rejected it); minting `project.recruit` here; gating on `owner_github_id`; folding reach into the rollup predicate; widening `membershipKind()` on our own judgement; shipping the route without the page.](<redacted>.md) | platform identity / authz + privacy |
303
+ | 0215 | [**The pre-accept recruiter sliver is a CEILING, not a step: a whitelist keyed by consent-and-reach, on the recruiting surface’s own door** ([task 1002968](https://cloudbongos.com/builders#/task/1002968), PV3 · goal 1000045 criteria C2/C5; privacy spec D3, owner-signed 2026-08-16). Privacy spec D2 has a row nothing could serve — **private · discoverable** — and ADR 0210 D4 named the reason: *“the full rollup is never its disclosure — the D3 sliver is”*. Decisions: **D1** the audience predicate is `recruiterSliverVisibleSql` = `accountActiveSql AND recruiterReachSql`, composed in `account-visibility.js` (its sole owner) and the ONE composed answer that deliberately **omits the existence axis** — ANDing `accountVisibleSql` would empty the sliver of exactly the account it serves; dropping it is safe only because reach is `COALESCE(recruiter_discoverable, visibility=’public’)`, so a private account reaches this surface only by its owner’s explicit opt-IN — and, after adversarial review, that opt-IN must be the one they MEANT: `setAccountPrivacy` now resets `recruiter_discoverable` to NULL when a PATCH turns an account private without naming reach, because a `true` set while PUBLIC meant “recruiters may see my public profile” and this predicate would have activated that stale consent silently. `profile_state=’active’` still floors it (a provisional account is never recruiter-visible) and `hide_stats` is absent, because hide changes the sliver’s SHAPE, never who appears in it; the guard PINS that existence-less predicate to its one reader, since a future public read joining it would look adopted while serving private accounts. **D2** the projection is a literal whitelist — `handle`, `display_name`, `avatar_url`, `disciplines`, `active_recently`, and under `hide_stats` the last two are **absent, not null**, with the activity query never issued at all (the cheapest way for a later edit to leak a number is for it to already be in hand). `last_active` is compared to the 30-day window IN SQL and only the boolean returns, so the date never enters the process; `github_id`/`github_login` are never KEYS, every count and any profile URL stay out — with one limit stated rather than glossed: the avatar D3 grants is GitHub’s own URL and embeds the account id, so the proof pins WHERE the id may appear instead of claiming an absence the code does not deliver. **D3** the handle is an ADDRESS, not a door — `GET /profiles/:handle` joins `accountVisibleSql` and 404s for the very account whose sliver was just read (asserted, with a 200 control), and a PREVIOUS handle resolves to nothing here unlike the public page’s 301, because a recruiting read has no shared links to preserve and a redirect would confirm a rename. **D4** one route, `GET /scouting/:handle`, beside the directory in `routes/scouting.js` but deliberately NOT sharing its gate: **no `project.recruit` atom is minted** (ADR 0201 D3 and ADR 0210 both reserve it for the console wave that defines it), and until it exists the sliver holds spec D1’s declared floor for that atom — `api.requireRank('archon')`. The first draft reused the directory’s door and that was WIDER than the owner-signed floor on both halves (`project.curate` at metic, OR any project owner — typically a bare xenos), on the first surface that discloses a PRIVATE account; narrowing after people are disclosed is not recoverable, widening later is. The audience question is the owner’s and is FILED, not taken — blocker 1000126, with the C5 tension it carries and a one-line swap either way. 404 never 403 (a 403 confirms the handle), `no-store` (ADR 0171 D5). **D5** it grants nothing (ADR 0016): the module is required by exactly ONE first-party server file — the route that serializes it — enumerated from source, and no rank/role/permission/membership travels with it. **D6** the Settings copy widens back from “the People directory” (narrowed by task 1002290 while this was unbuilt) to name **both** recruiting surfaces — “both” and not “every”, because a guard asserts `routes/scouting.js` mounts exactly two routes and that both readers compose `recruiterReachSql`. The half that was actually WRONG was the grant itself: the copy promised a hidden account “your name and nothing else” while the sliver also ships the AVATAR, never named the picture in the shown branch, and never told a private account this is the one thing a recruiter sees while their page answers “not found”. The guard now iterates SLIVER_KEYS from the module instead of checking transcribed phrases, so a sixth granted field cannot ship undescribed. **D7** no migration; the port lives beside `getPublicProfileExtras` in the MODULE, not the file, which is on the 1500-line ratchet. The proof is a whitelist over the module’s own exported key list, planted improbable sentinels asserted absent from the whole body with controls against vacuity, and a fake pool that reads boolean STRUCTURE — the house interpreter collects terms and ANDs them, so rewriting this predicate’s `AND` to `OR` (which in Postgres serves EVERY active account) passed all three test files green until each term was made to be CONSUMED and the residue required to be pure conjunction. That hole is still open in five sibling proofs (idea 1000877). Four further defects came out of the same review: the credits/karma sentinels sat on rows the sliver never reads, a “control” compared a fixture to itself, and the one-reader pin missed the predicate’s JS twin. ⚠ Honest limits: **no UI consumes it yet** (the recruiting view is the console wave’s and task 1002972’s); **the audience is UNRESOLVED** (blocker 1000126) and the archon floor is narrower than goal C5 describes, so project owners cannot use the sliver today; the two-route guard counts only `routes/scouting.js`, so a recruiting read added elsewhere would not trip it; the route is unmetered (idea 1000876); and `active_recently` understates for a builder whose only project never reports a rollup. Rejected: flooring on `accountVisibleSql`; folding reach into `rollupVisibleSql`; minting `project.recruit`; **reusing the directory’s door**; leaving a stale `recruiter_discoverable = true` to read as consent after an account goes private; a second route file; null-instead-of-absent rollup keys; a profile URL / `github_login` / a project count / a raw `last_active`; 301-ing a previous handle; 403 for a non-discoverable builder.](<redacted>.md) | platform identity / privacy |
303
304
  | 0213 | [**The platform T&C acceptance is the hub's own witness, written once, and consent becomes two columns** ([task 1002913](https://cloudbongos.com/builders#/task/1002913), goal 1000045). ADR 0141 §4 deferred consent for cross-project aggregation to "the platform T&C" and ADR 0171 D3 wrote its own definition around the moment that acceptance "can later be captured" - but no acceptance record existed, and while `/terms` DOES exist (task 1003251) it says nothing about work crossing between projects, so the public-profile premise ("already carries platform T&C consent") was untrue for every account. The scouting.js:6 pointer the task named had also been overwritten by ADR 0210, so the debt was going invisible rather than getting paid. Decision: `terms_accepted_at` + `terms_version` on `platform_identity_accounts` (migration 019), written ONLY by `upsertAccount`'s `activate` branch - one caller, /sso/authorize, where `activate: true` is a source literal and every field comes from the hub's resolved session (the ADR 0205 D3 property; a record a caller could assert is evidence of nothing). COALESCE makes it write-once, so the column keeps meaning WHEN consent was given. The consent axis in `account-visibility.js` becomes `profile_state = 'active' AND terms_accepted_at IS NOT NULL`, composed into every other predicate, which is what makes the tie structural rather than a promise. NO backfill (D4): existing active accounts re-accept on their next hub sign-in - ADR 0171 D3's own rule and P03's ratified rationale - and that visible consequence, plus the wording itself, went to the owner on blocker 1000123. Rejected: an acceptances TABLE (no event stream yet), a click-through gate (an interstitial in a redirect built to be invisible; additive later), backfilling (records a consent that never happened), deriving profile_state from the timestamp, and putting the predicate in `terms-acceptance.js` (a second owner of an effective-visibility answer, which ADR 0202 D4 forbids).](<redacted>.md) | platform identity / consent / privacy |
305
+ | 0216 | [**A fake-pool interpreter must FAIL LOUDLY on what it cannot model; the refusal is uniform, the interpreters stay separate** ([task 1003354](https://cloudbongos.com/builders#/task/1003354), folding in idea 1000877 from the adversarial review of [task 1002968](https://cloudbongos.com/builders#/task/1002968)). Nine test files carry a **fake pool** whose row filter is derived from each statement’s own WHERE text — the design that makes an isolation proof say something about the real query rather than about a canned response. It has one silent failure mode: a term the interpreter does not recognise is simply not applied, so the boundary goes vacuous and every assertion above it keeps passing. Each file guarded a piece of that (unread `$N`, unknown literal, unmodelled `IS NULL`) and every one of those is a **term** guard — and the term list is not the predicate. Three reviews found the same shape. **The missing term:** ADR 0213 made consent two columns and `scouting_owner_access_and_reach.mjs` modelled only the first; a NULL test is a third syntax neither sweep can see, so the suite reported 17 passed while modelling a predicate the database no longer had, inside a file whose own header calls that impossible. **The rewritten joiner:** an interpreter that COLLECTS recognised terms and ANDs them re-imposes an `AND` the SQL may no longer contain — rewrite a predicate’s `AND` to `OR` and Postgres serves every active account on the platform, or lets any builder revoke any session by id, while the fake answers exactly as before. **Recognition is not application:** ADR 0213’s own first draft checked only that a column name was recognised, and a mutation deleting the filter still passed. Decisions: **D1** the governing rule — an interpreter that cannot model a term must REFUSE the statement, never ignore the term; incompleteness is allowed, silence is not, because a refusal fails the build in the session that changed the SQL while a silent drop fails nothing ever. **D2** the mechanism is a CONSUMING parse: each recognised term is spliced out of the text and the residue must be a pure conjunction (`/^[\s()]*(?:AND[\s()]*)*$/`), which subsumes every term guard, catches `OR`/`NOT`/`CASE`, and retires ADR 0213’s `modelled`-set bookkeeping because an unapplied term is by construction still there; a legitimate `OR` (the rename window, the either-side clause, the expiry disjunction, the rescind guard) is consumed as a whole unit. **D3** the interpreters stay SEPARATE and only the refusal is uniform — the term vocabulary differs completely across six tables, so a shared registry would be a small SQL engine and would couple unrelated proofs; instead every copy carries the identical guard and its OWN calibration test, which is strictly better anti-drift than extraction (a helper proves the guard exists somewhere; a calibration test proves it is reached by that file’s own statements). **D4** a modelled term proves nothing until a fixture makes it observable — three fixtures added, each differing from its control in exactly one column, so the mutation that deletes the term has somewhere to land; where a file deliberately lacks one because another owns that matrix, the comment says so. **D5** every copy verified BY MUTATION against the real source — ten mutations, ten reds, each a 0-failure pass beforehand. ⚠ Honest limits: no fitness check asserts a NEW fake pool carries the guard (identifying “a fake pool” needs a heuristic, and a heuristic gate over test internals has a false-positive cost) — the per-file calibration tests hold the nine that exist and a tenth is a review question; `canonical_profile_url.mjs` is untouched because its residue must be EMPTY, strictly stronger already. Rejected: one shared interpreter module; a fitness heuristic; keeping `KNOWN_NULL_TESTS` + `modelled` beside the structure guard; parsing the boolean tree properly; accepting green as verification.](<redacted>.md) | testing / proof integrity |
304
306
 
305
307
  > ⚠️ **Numbering collisions are now machine-enforced, not narrated.** Twenty numbers are shared by two ADRs each — assigned in parallel sessions before anything checked. The files keep their filenames (renumbering would break every existing citation, and a number once assigned is never reused), and this table disambiguates each pair as `NNNN-a` / `NNNN-b`. The authoritative list is `LEGACY_DUPLICATE_ADRS` in [`scripts/gds/adr-namespace.js`](../../scripts/gds/adr-namespace.js), frozen by exact filename: a **new** collision — or a third file joining a legacy number, or a rename of either half — hard-fails the `unit` CI gate, as does an index row that points at no file or an ADR with no row. The list may only shrink. This paragraph used to narrate the collisions one by one and had fallen eight behind reality; see [ADR 0195](<redacted>.md) for why the check exists and why the pairs are grandfathered rather than renumbered.
@@ -12089,6 +12089,58 @@
12089
12089
  ]
12090
12090
  }
12091
12091
  },
12092
+ "/scouting/{handle}": {
12093
+ "get": {
12094
+ "operationId": "get_scouting_handle",
12095
+ "tags": [
12096
+ "scouting"
12097
+ ],
12098
+ "summary": "GET /scouting/:handle",
12099
+ "description": "the PRE-ACCEPT SLIVER for ONE builder (privacy spec D3, ADR 0215 D4, task 1002968). This is the FIRST surface on the platform that discloses a PRIVATE account, and its audience is deliberately NOT the directory's. WHY A RANK GATE AND NOT THE RECRUITING DOOR ABOVE. Spec D3 gates this read on `project.recruit`, an atom whose declared shape is FLOOR ARCHON, widenable per instance (spec D1). That atom does not exist — ADR 0201 D3 and ADR 0210 both refuse to mint it outside the project-admin-console wave that defines it (spike 1002786 R3), and this task does not either. The directory's door (`project.curate` at metic, OR any project owner — ADR 0210 D2) is WIDER than the signed floor on both halves, so adopting it here would widen an owner-signed privacy decision by implementation convenience. Until the atom lands, the honest reading of D3 is its floor, held by rank. Whether the wider recruiting audience is authorized for this surface is the owner's call and is filed as a blocker, NOT resolved here; when it is answered, this one line moves and nothing else does. 404, never 403, for a builder who is not recruiter-reachable: a 403 would confirm the handle exists, which is the disclosure the opt-out removes. The sliver's own predicate does the deciding, inside the module.\n\n**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).",
12100
+ "x-rank": "archon",
12101
+ "x-source": "modules/platform-identity/routes/scouting.js",
12102
+ "parameters": [
12103
+ {
12104
+ "name": "handle",
12105
+ "in": "path",
12106
+ "required": true,
12107
+ "schema": {
12108
+ "type": "string"
12109
+ },
12110
+ "description": "Path parameter `handle`."
12111
+ }
12112
+ ],
12113
+ "responses": {
12114
+ "200": {
12115
+ "description": "Success.",
12116
+ "content": {
12117
+ "application/json": {
12118
+ "schema": {
12119
+ "$ref": "#/components/schemas/GetScoutingHandleResponse"
12120
+ }
12121
+ }
12122
+ }
12123
+ },
12124
+ "400": {
12125
+ "$ref": "#/components/responses/BadRequest"
12126
+ },
12127
+ "401": {
12128
+ "$ref": "#/components/responses/Unauthorized"
12129
+ },
12130
+ "403": {
12131
+ "$ref": "#/components/responses/Forbidden"
12132
+ },
12133
+ "404": {
12134
+ "$ref": "#/components/responses/NotFound"
12135
+ }
12136
+ },
12137
+ "security": [
12138
+ {
12139
+ "builderSession": []
12140
+ }
12141
+ ]
12142
+ }
12143
+ },
12092
12144
  "/search": {
12093
12145
  "post": {
12094
12146
  "operationId": "post_search",
@@ -16804,6 +16856,15 @@
16804
16856
  "page"
16805
16857
  ]
16806
16858
  },
16859
+ "GetScoutingHandleResponse": {
16860
+ "type": "object",
16861
+ "properties": {
16862
+ "sliver": {}
16863
+ },
16864
+ "required": [
16865
+ "sliver"
16866
+ ]
16867
+ },
16807
16868
  "GetScoutingResponse": {
16808
16869
  "type": "object",
16809
16870
  "properties": {
@@ -21376,9 +21437,9 @@
21376
21437
  "description": "A required dependency/feature is not configured or is temporarily down."
21377
21438
  }
21378
21439
  },
21379
- "x-endpoint-count": 338,
21380
- "x-schema-count": 374,
21440
+ "x-endpoint-count": 339,
21441
+ "x-schema-count": 375,
21381
21442
  "x-undocumented-bodies": 9,
21382
- "x-response-schemas": 254,
21443
+ "x-response-schemas": 255,
21383
21444
  "x-generated-by": "scripts/gds/gen-api-docs.js"
21384
21445
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Bongos API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 338 endpoints across 54 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 339 endpoints across 54 route files.
6
6
  > Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
7
7
 
8
8
  Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -484,11 +484,12 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
484
484
  | GET | `/api/bongos/public/uptime` | `public` | — | Uptime: current status + 90-day history bucketed by hour. |
485
485
  | GET | `/api/bongos/public/versions` | `public` | — | read-only surface for the status dashboard (status.<apex>). |
486
486
 
487
- ## `scouting` (1)
487
+ ## `scouting` (2)
488
488
 
489
489
  | Method | Path | Rank | Body | Description |
490
490
  |---|---|---|---|---|
491
491
  | GET | `/api/bongos/scouting` | `metic+archon` | — | the internal talent directory across every project. |
492
+ | GET | `/api/bongos/scouting/:handle` | `archon` | — | the PRE-ACCEPT SLIVER for ONE builder (privacy spec D3, ADR 0215 D4, task 1002968). |
492
493
 
493
494
  ## `search` (2)
494
495
 
@@ -206,7 +206,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
206
206
  | `e6982a9ff948` | certain | Charter library | `modules/hall-ui/public/government.js:657` |
207
207
  | `f8725cf3ba62` | certain | Checking dependency order… | `modules/hall-ui/public/work.js:800` |
208
208
  | `7a41b18c0de8` | certain | Checking for conflicts… | `modules/hall-ui/public/work.js:779` |
209
- | `aa3ba7d28a76` | certain | Checking your key… | `modules/hall-ui/public/settings.js:1099` |
209
+ | `aa3ba7d28a76` | certain | Checking your key… | `modules/hall-ui/public/settings.js:1108` |
210
210
  | `1c6b0e3ffc0e` | certain | Choose a setup | `modules/hall-ui/public/hall-render.js:650` |
211
211
  | `6c88cdf417f1` | certain | Choose which sound plays for each build event — one when Claude waits for your input, another when a task ship | `modules/hall-ui/public/settings.html:321` |
212
212
  | `ab326d863a38` | certain | Claim next | `modules/hall-ui/public/goals-render.js:146` |
@@ -243,7 +243,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
243
243
  | `cfc287c42263` | certain | Complete your profile | `modules/hall-ui/public/profile-nudge.js:62` |
244
244
  | `2867c85d196d` | certain | Confirm that verification for #{…} actually passed? | `modules/hall-ui/public/task.js:327` |
245
245
  | `9b16a22bf24c` | certain | Connect Discord &amp; join the server | `modules/hall-ui/public/hall-render.js:855` |
246
- | `9b16a22bf24c` | certain | Connect Discord &amp; join the server | `modules/hall-ui/public/settings.js:912` |
246
+ | `9b16a22bf24c` | certain | Connect Discord &amp; join the server | `modules/hall-ui/public/settings.js:921` |
247
247
  | `9f8d8e07224f` | certain | Connect your Claude Desktop to your dev box with a one-time pairing code — the guided flow lives on its own pa | `modules/hall-ui/public/settings.html:234` |
248
248
  | `c07898571b24` | certain | Connects to | `modules/hall-ui/public/atlas.js:275` |
249
249
  | `3983ee271e7a` | certain | Container cost is tracked for oversight — not charged in the early stage. | `modules/hall-ui/public/watch.js:642` |
@@ -273,7 +273,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
273
273
  | `b9e53fbd90e6` | certain | Could not change standing: {…} | `modules/hall-ui/public/watch.js:603` |
274
274
  | `1ef1efc15b6c` | certain | Could not change that just now. | `modules/hall-ui/public/goals-render.js:993` |
275
275
  | `78e18ea59b9f` | certain | Could not close: {…} | `modules/hall-ui/public/harbor.js:134` |
276
- | `c3f99e7c6e6b` | certain | Could not copy automatically — select and copy manually. ({…}) | `modules/hall-ui/public/settings.js:979` |
276
+ | `c3f99e7c6e6b` | certain | Could not copy automatically — select and copy manually. ({…}) | `modules/hall-ui/public/settings.js:988` |
277
277
  | `e3fd1febf63d` | certain | Could not copy to the clipboard. Try again. | `modules/hall-ui/public/goals-page.js:374` |
278
278
  | `e3fd1febf63d` | certain | Could not copy to the clipboard. Try again. | `modules/hall-ui/public/work.js:561` |
279
279
  | `487e0b39ac8f` | certain | Could not copy — select and copy by hand. | `modules/hall-ui/public/box-panel.js:413` |
@@ -302,15 +302,15 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
302
302
  | `edd5bafbe075` | certain | Could not load the queue just now. | `modules/hall-ui/public/ideas.js:387` |
303
303
  | `02bb0570996a` | certain | Could not load the ranks. | `modules/hall-ui/public/ranks.js:197` |
304
304
  | `2878778cf9f3` | certain | Could not load this page. | `modules/hall-ui/public/watch.js:946` |
305
- | `4b0c8d94541c` | certain | Could not load your account. Reload the page to try again. | `modules/hall-ui/public/settings.js:1357` |
305
+ | `4b0c8d94541c` | certain | Could not load your account. Reload the page to try again. | `modules/hall-ui/public/settings.js:1366` |
306
306
  | `2a9fb4046bc4` | certain | Could not load your rank. Return to the hall and try again. | `modules/hall-ui/public/ranks.js:196` |
307
307
  | `9d533e811dec` | certain | Could not load your sessions: {…} | `modules/hall-ui/public/settings-sessions.js:114` |
308
- | `64f9d51f0fa2` | certain | Could not load your settings. | `modules/hall-ui/public/settings.js:1360` |
308
+ | `64f9d51f0fa2` | certain | Could not load your settings. | `modules/hall-ui/public/settings.js:1369` |
309
309
  | `2366356926b4` | certain | Could not mark the primer just now. Try again. | `modules/hall-ui/public/primer.js:497` |
310
310
  | `753987b5da13` | certain | Could not reach the submit endpoint. | `modules/hall-ui/public/modules.js:204` |
311
311
  | `6f500726f0ac` | certain | Could not read the report: {…} | `modules/hall-ui/public/watch.js:405` |
312
- | `8b470cebf53d` | certain | Could not remove your key. Try again. | `modules/hall-ui/public/settings.js:1179` |
313
- | `4cf6bc8b377b` | certain | Could not remove. Try again. | `modules/hall-ui/public/settings.js:1178` |
312
+ | `8b470cebf53d` | certain | Could not remove your key. Try again. | `modules/hall-ui/public/settings.js:1188` |
313
+ | `4cf6bc8b377b` | certain | Could not remove. Try again. | `modules/hall-ui/public/settings.js:1187` |
314
314
  | `7a778d188e87` | certain | Could not remove: {…} | `modules/hall-ui/public/government.js:336` |
315
315
  | `ebeda72a6c15` | certain | Could not request access right now. | `modules/hall-ui/public/my-projects.js:146` |
316
316
  | `ebeda72a6c15` | certain | Could not request access right now. | `modules/hall-ui/public/my-projects.js:148` |
@@ -318,11 +318,11 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
318
318
  | `b526ee0b8c48` | certain | Could not save just now. Try again. | `modules/hall-ui/public/builders.js:459` |
319
319
  | `41a351aea8d4` | certain | Could not save the volume. Try again. | `modules/hall-ui/public/settings.js:214` |
320
320
  | `5305186a4154` | certain | Could not save your choice. Try again. | `modules/hall-ui/public/settings.js:104` |
321
- | `ea4fb30debd0` | certain | Could not save your key. Try again. | `modules/hall-ui/public/settings.js:1123` |
322
- | `ef609f2c0cb3` | certain | Could not save your name. Try again. | `modules/hall-ui/public/settings.js:848` |
321
+ | `ea4fb30debd0` | certain | Could not save your key. Try again. | `modules/hall-ui/public/settings.js:1132` |
322
+ | `ef609f2c0cb3` | certain | Could not save your name. Try again. | `modules/hall-ui/public/settings.js:857` |
323
323
  | `59ecd5c52f59` | certain | Could not save your preference. Try again. | `modules/hall-ui/public/builders.js:356` |
324
- | `59ecd5c52f59` | certain | Could not save your preference. Try again. | `modules/hall-ui/public/settings.js:768` |
325
- | `6e196f9d9175` | certain | Could not save your privacy preference. Try again. | `modules/hall-ui/public/settings.js:670` |
324
+ | `59ecd5c52f59` | certain | Could not save your preference. Try again. | `modules/hall-ui/public/settings.js:777` |
325
+ | `6e196f9d9175` | certain | Could not save your privacy preference. Try again. | `modules/hall-ui/public/settings.js:679` |
326
326
  | `bd197a4373c8` | certain | Could not save your rendering preference. Try again. | `modules/hall-ui/public/settings.js:525` |
327
327
  | `f81ab95f1d88` | certain | Could not save your sound preference. Try again. | `modules/hall-ui/public/settings.js:234` |
328
328
  | `f81ab95f1d88` | certain | Could not save your sound preference. Try again. | `modules/hall-ui/public/settings.js:324` |
@@ -330,13 +330,13 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
330
330
  | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:103` |
331
331
  | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:455` |
332
332
  | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:524` |
333
- | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:669` |
334
- | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:767` |
335
- | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:847` |
336
- | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:1122` |
333
+ | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:678` |
334
+ | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:776` |
335
+ | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:856` |
336
+ | `8c234d5c8bd4` | certain | Could not save. Try again. | `modules/hall-ui/public/settings.js:1131` |
337
337
  | `31c6e3fd754b` | certain | Could not send the request just now. | `modules/hall-ui/public/goals-render.js:1008` |
338
- | `1f4d9a989606` | certain | Could not set up key storage. Try again. | `modules/hall-ui/public/settings.js:1159` |
339
- | `e65b392144ac` | certain | Could not set up storage. Try again. | `modules/hall-ui/public/settings.js:1158` |
338
+ | `1f4d9a989606` | certain | Could not set up key storage. Try again. | `modules/hall-ui/public/settings.js:1168` |
339
+ | `e65b392144ac` | certain | Could not set up storage. Try again. | `modules/hall-ui/public/settings.js:1167` |
340
340
  | `d4601887a058` | certain | Could not sign out everywhere: {…} | `modules/hall-ui/public/settings-sessions.js:102` |
341
341
  | `b1602d01f4bb` | certain | Could not unblock: {…} | `modules/hall-ui/public/harbor.js:187` |
342
342
  | `3db890b074a7` | certain | Could not update visibility just now. | `modules/hall-ui/public/goals-render.js:977` |
@@ -367,8 +367,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
367
367
  | `457f4967541b` | certain | Device pairing | `modules/hall-ui/public/pair.html:15` |
368
368
  | `433beff4d202` | certain | Device · dev box · memory · server (authority + prod) · GitHub — and the full box→production ship flow. | `modules/hall-ui/public/diagrams.html:86` |
369
369
  | `65322ac89221` | certain | Discard draft | `modules/hall-ui/public/ideas.html:82` |
370
- | `0f685daf1bd5` | certain | Discord connected ✓ | `modules/hall-ui/public/settings.js:905` |
371
- | `d8017b5ca98f` | certain | Discord unlinked. | `modules/hall-ui/public/settings.js:924` |
370
+ | `0f685daf1bd5` | certain | Discord connected ✓ | `modules/hall-ui/public/settings.js:914` |
371
+ | `d8017b5ca98f` | certain | Discord unlinked. | `modules/hall-ui/public/settings.js:933` |
372
372
  | `f3e09453374f` | certain | Dismissed — looked at, leaving it as it is | `modules/hall-ui/public/copy-desk.html:118` |
373
373
  | `3e561393f4e9` | certain | Display name | `modules/hall-ui/public/settings.html:66` |
374
374
  | `3e561393f4e9` | certain | Display name | `modules/hall-ui/public/settings.html:75` |
@@ -406,7 +406,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
406
406
  | `ddebbccd4b37` | certain | Everyone building across hosted projects, ranked by track record. Descriptive only — cross-project numbers nev | `modules/hall-ui/public/people.html:23` |
407
407
  | `4750e12477e7` | certain | Everyone is already a member | `modules/hall-ui/public/goals-render.js:910` |
408
408
  | `04bbccfe7465` | certain | Everything a new builder needs before claiming their first task. About a ten-minute read. | `modules/hall-ui/public/primer.html:31` |
409
- | `d629e152f074` | certain | Expires {…} · refreshes on use. | `modules/hall-ui/public/settings.js:974` |
409
+ | `d629e152f074` | certain | Expires {…} · refreshes on use. | `modules/hall-ui/public/settings.js:983` |
410
410
  | `536a7e99640a` | certain | File the flag | `modules/hall-ui/public/copy-desk.html:105` |
411
411
  | `077cf99f49f6` | certain | File this idea | `modules/hall-ui/public/ideas.html:81` |
412
412
  | `1def0e7c716e` | certain | Find something to flag | `modules/hall-ui/public/copy-desk.html:65` |
@@ -422,14 +422,14 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
422
422
  | `448d00771dc8` | certain | Flagged. It is in the queue. | `modules/hall-ui/public/copy-desk.js:281` |
423
423
  | `617f13fa3fdb` | certain | Flip the switch. | `modules/hall-ui/public/hall-render.js:650` |
424
424
  | `42cee5cb3584` | certain | Fold this idea into # | `modules/hall-ui/public/task-detail.js:457` |
425
- | `647bcfcfdb03` | certain | Fresh CLI token issued. Paste it in your terminal: | `modules/hall-ui/public/settings.js:971` |
425
+ | `647bcfcfdb03` | certain | Fresh CLI token issued. Paste it in your terminal: | `modules/hall-ui/public/settings.js:980` |
426
426
  | `55c71d76a94c` | certain | From creation to production — and the exact step where {{currency}} are awarded (at | `modules/hall-ui/public/diagrams.html:61` |
427
427
  | `a025080147a1` | certain | Full Idea | `modules/hall-ui/public/government.js:716` |
428
428
  | `ecae3916bf01` | certain | Gate — {{worldName}} | `modules/hall-ui/public/gate.html:6` |
429
429
  | `ecae3916bf01` | certain | Gate — {{worldName}} | `modules/hall-ui/public/gate.html:6` |
430
430
  | `4638e024f0af` | certain | Generated from the code on the last deploy · | `modules/hall-ui/public/atlas.js:333` |
431
431
  | `3c1a5d27ef0b` | certain | Generated from the code on the last deploy. | `modules/hall-ui/public/atlas.js:333` |
432
- | `2ae2114b61db` | certain | Get a free key ↗ | `modules/hall-ui/public/settings.js:1003` |
432
+ | `2ae2114b61db` | certain | Get a free key ↗ | `modules/hall-ui/public/settings.js:1012` |
433
433
  | `4794a991de3d` | certain | Getting started | `modules/hall-ui/public/hall-widgets.js:59` |
434
434
  | `a28b1a567f1a` | certain | GitHub username | `modules/hall-ui/public/hall-render.js:275` |
435
435
  | `79934b879a12` | certain | Give the nod | `modules/hall-ui/public/goal-inbox.js:231` |
@@ -480,7 +480,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
480
480
  | `ef224c9de7c8` | certain | Ideas — {{worldName}} | `modules/hall-ui/public/ideas.html:6` |
481
481
  | `ef224c9de7c8` | certain | Ideas — {{worldName}} | `modules/hall-ui/public/ideas.html:6` |
482
482
  | `7d6a7de7a69e` | certain | If the {…} has invited you, sign in with GitHub and you're in. If not, ask them for an invite — this project d | `modules/hall-ui/public/hall-render.js:267` |
483
- | `b6c47d4ee42c` | certain | Image key removed. | `modules/hall-ui/public/settings.js:1175` |
483
+ | `b6c47d4ee42c` | certain | Image key removed. | `modules/hall-ui/public/settings.js:1184` |
484
484
  | `783853467d52` | certain | Image-generation key | `modules/hall-ui/public/settings.html:175` |
485
485
  | `5c2e2bcbd5fb` | certain | In Progress | `modules/hall-ui/public/work.html:72` |
486
486
  | `810e47b6a209` | certain | In this guide | `modules/hall-ui/public/drachmae.html:41` |
@@ -504,9 +504,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
504
504
  | `eba610d25523` | certain | Jump to… | `modules/hall-ui/public/shell.js:318` |
505
505
  | `bc779353aa0c` | certain | Karma — peer recognition and approvals, a separate counter from {…}. | `modules/hall-ui/public/profile.js:58` |
506
506
  | `32d25ef2182d` | certain | Keep box | `modules/hall-ui/public/box-panel.js:164` |
507
- | `fbe40b5818a3` | certain | Key removed. | `modules/hall-ui/public/settings.js:1174` |
508
- | `93c17262bacf` | certain | Key storage is being set up by an Archon — check back shortly. {…} | `modules/hall-ui/public/settings.js:1053` |
509
- | `2a3c9e501f8e` | certain | Key storage isn't set up yet. As an Archon you can turn it on now — the server generates and safely stores the | `modules/hall-ui/public/settings.js:1049` |
507
+ | `fbe40b5818a3` | certain | Key removed. | `modules/hall-ui/public/settings.js:1183` |
508
+ | `93c17262bacf` | certain | Key storage is being set up by an Archon — check back shortly. {…} | `modules/hall-ui/public/settings.js:1062` |
509
+ | `2a3c9e501f8e` | certain | Key storage isn't set up yet. As an Archon you can turn it on now — the server generates and safely stores the | `modules/hall-ui/public/settings.js:1058` |
510
510
  | `7d6eaa8d4514` | certain | Kinds of work shipped | `modules/hall-ui/public/hall-render.js:1089` |
511
511
  | `d7b4392e0ea6` | certain | Largest files | `modules/hall-ui/public/watch.js:857` |
512
512
  | `81f62e066dbf` | certain | Last 14 days: {…} / 10 average across {…} graded work{…} ({…} passed). | `modules/hall-ui/public/builders.js:586` |
@@ -514,12 +514,12 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
514
514
  | `9be8b839eff8` | certain | Last 7 days | `modules/hall-ui/public/hall-widgets.js:129` |
515
515
  | `59f0bc78a28f` | certain | Last 90 days | `modules/hall-ui/public/hall-widgets.js:130` |
516
516
  | `13bae4dfb28e` | certain | Last claimed by | `modules/hall-ui/public/task.js:243` |
517
- | `1526a7ae8c85` | certain | Latest version: v{…}. | `modules/hall-ui/public/settings.js:1443` |
517
+ | `1526a7ae8c85` | certain | Latest version: v{…}. | `modules/hall-ui/public/settings.js:1452` |
518
518
  | `7c9b7a89353b` | certain | Leave goal | `modules/hall-ui/public/goals-render.js:785` |
519
519
  | `f192ff6563f9` | certain | Leave your GitHub username and an Archon will let you in. No coding needed to start — once you're approved, si | `modules/hall-ui/public/hall-render.js:275` |
520
520
  | `64f37809350f` | certain | Lifecycle: {…} | `modules/hall-ui/public/watch.js:336` |
521
521
  | `913b848753ea` | certain | Lines by directory | `modules/hall-ui/public/watch.js:832` |
522
- | `a53e0cde7ff7` | certain | Link first — your rank role is set the moment you join. | `modules/hall-ui/public/settings.js:913` |
522
+ | `a53e0cde7ff7` | certain | Link first — your rank role is set the moment you join. | `modules/hall-ui/public/settings.js:922` |
523
523
  | `64e85f1691f9` | certain | Link your Discord account and you're added to the {{worldName}} server with your rank role already set — no in | `modules/hall-ui/public/settings.html:53` |
524
524
  | `9a31cf5fe05b` | certain | Linking opens Discord's consent screen; unlinking applies at once. | `modules/hall-ui/public/settings.html:58` |
525
525
  | `a8a55023bef2` | certain | Loading dev boxes… | `modules/hall-ui/public/harbor.html:23` |
@@ -569,8 +569,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
569
569
  | `33c6325af200` | certain | My Projects | `modules/hall-ui/public/my-projects.html:15` |
570
570
  | `670aa6cee309` | certain | My Projects — {{worldName}} | `modules/hall-ui/public/my-projects.html:6` |
571
571
  | `670aa6cee309` | certain | My Projects — {{worldName}} | `modules/hall-ui/public/my-projects.html:6` |
572
- | `ae84ebe1d735` | certain | Name cannot be blank. | `modules/hall-ui/public/settings.js:816` |
573
- | `31e91ee6ce03` | certain | Name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:821` |
572
+ | `ae84ebe1d735` | certain | Name cannot be blank. | `modules/hall-ui/public/settings.js:825` |
573
+ | `31e91ee6ce03` | certain | Name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:830` |
574
574
  | `7def635421ea` | certain | Needs your attention | `modules/hall-ui/public/goal-inbox.js:274` |
575
575
  | `7fcc2583c372` | certain | New custom rank | `modules/hall-ui/public/government.html:65` |
576
576
  | `9e06c14d155a` | certain | New here — request access | `modules/hall-ui/public/hall-render.js:275` |
@@ -582,7 +582,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
582
582
  | `41ec1cf65d6f` | certain | No GitHub account yet? Make a free one at | `modules/hall-ui/public/hall-render.js:275` |
583
583
  | `c255749ec989` | certain | No achievements earned yet. | `modules/hall-ui/public/builders.js:475` |
584
584
  | `c255749ec989` | certain | No achievements earned yet. | `modules/hall-ui/public/profile.js:108` |
585
- | `83f62fc94271` | certain | No builder account found for this sign-in. | `modules/hall-ui/public/settings.js:1365` |
585
+ | `83f62fc94271` | certain | No builder account found for this sign-in. | `modules/hall-ui/public/settings.js:1374` |
586
586
  | `6d6fd2314248` | certain | No cross-project activity reported yet. | `modules/hall-ui/public/profile.js:239` |
587
587
  | `6d6fd2314248` | certain | No cross-project activity reported yet. | `modules/hall-ui/public/scouting.js:29` |
588
588
  | `b1ada579483c` | certain | No custom ranks yet | `modules/hall-ui/public/government.js:325` |
@@ -664,8 +664,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
664
664
  | `15a49bf15007` | certain | Page {…} of {…} | `modules/hall-ui/public/hall-kit.js:109` |
665
665
  | `d1cd74b39c2e` | certain | Page {…} of {…} · {…}–{…} of {…} | `modules/hall-ui/public/sessions.js:124` |
666
666
  | `8595b0aa76a0` | certain | Pair Claude Desktop | `modules/hall-ui/public/settings.html:233` |
667
- | `cf68a394cfa5` | certain | Paste command copied. | `modules/hall-ui/public/settings.js:978` |
668
- | `a495649d1f82` | certain | Paste your key first. | `modules/hall-ui/public/settings.js:1098` |
667
+ | `cf68a394cfa5` | certain | Paste command copied. | `modules/hall-ui/public/settings.js:987` |
668
+ | `a495649d1f82` | certain | Paste your key first. | `modules/hall-ui/public/settings.js:1107` |
669
669
  | `542f801cc77f` | certain | Path-based estimate from declared files. Glob-aware detection with claim collisions — and lead resolution acti | `modules/hall-ui/public/goals-render.js:518` |
670
670
  | `54fa47e421a5` | certain | Peer recognition | `modules/hall-ui/public/hall-widgets.js:168` |
671
671
  | `47d609ece51c` | certain | Pending invitations | `modules/hall-ui/public/goals-render.js:1048` |
@@ -701,7 +701,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
701
701
  | `6824ec470f99` | certain | Ranks — {{worldName}} | `modules/hall-ui/public/ranks.html:6` |
702
702
  | `6824ec470f99` | certain | Ranks — {{worldName}} | `modules/hall-ui/public/ranks.html:6` |
703
703
  | `e60039795803` | certain | Re-issue CLI token | `modules/hall-ui/public/settings.html:142` |
704
- | `101a51902f53` | certain | Re-issue failed: {…} | `modules/hall-ui/public/settings.js:983` |
704
+ | `101a51902f53` | certain | Re-issue failed: {…} | `modules/hall-ui/public/settings.js:992` |
705
705
  | `fae2f90927bd` | certain | Read an idea, then decide. An objection needs a reason and the section it faults. | `modules/hall-ui/public/government.html:54` |
706
706
  | `b6fcfdd652a7` | certain | Read it here | `modules/hall-ui/public/work.html:40` |
707
707
  | `26e6c9879035` | certain | Reading the diagrams | `modules/hall-ui/public/diagrams.html:48` |
@@ -726,7 +726,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
726
726
  | `aa4db91b5732` | certain | Released #{…}. It returns to the queue. | `modules/hall-ui/public/work.js:945` |
727
727
  | `9c74a2572f4d` | certain | Remote control (recommended) | `modules/hall-ui/public/hall-render.js:650` |
728
728
  | `65e3399a8fbf` | certain | Remove filter | `modules/hall-ui/public/hall-kit.js:308` |
729
- | `dacd113fb3b2` | certain | Remove your image-generation key? Art generation will stop until you add one again. | `modules/hall-ui/public/settings.js:1166` |
729
+ | `dacd113fb3b2` | certain | Remove your image-generation key? Art generation will stop until you add one again. | `modules/hall-ui/public/settings.js:1175` |
730
730
  | `20882d6ffdd0` | certain | Removed {…} from builder {…}. | `modules/hall-ui/public/government.js:332` |
731
731
  | `b06589044b0b` | certain | Render session cards as widgets (prettier, costs tokens) instead of plain text (cheaper, identical info). | `modules/hall-ui/public/settings.js:502` |
732
732
  | `9f4e519ea3e2` | certain | Repo Atlas | `modules/hall-ui/public/atlas.html:15` |
@@ -758,7 +758,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
758
758
  | `f7ed4ba07178` | certain | Roadmap — {{worldName}} | `modules/hall-ui/public/roadmap.html:6` |
759
759
  | `b6596905f845` | certain | Said more than once | `modules/hall-ui/public/copy-desk.html:57` |
760
760
  | `8bf1bf56b670` | certain | Same text, different place — it moved file or line since the flag was filed. | `modules/hall-ui/public/copy-desk.js:66` |
761
- | `0c79b504aebe` | certain | Save key | `modules/hall-ui/public/settings.js:1034` |
761
+ | `0c79b504aebe` | certain | Save key | `modules/hall-ui/public/settings.js:1043` |
762
762
  | `11486793742e` | certain | Saves the moment you toggle; applies from your next session. | `modules/hall-ui/public/settings.html:275` |
763
763
  | `e8e4e49fe8f4` | certain | Saves when you press Save; shows everywhere at once. | `modules/hall-ui/public/settings.html:79` |
764
764
  | `42cbc20a6ec8` | certain | Saves when you press Save; your next | `modules/hall-ui/public/settings.html:127` |
@@ -789,9 +789,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
789
789
  | `3f8f6c62adb8` | certain | Session pages | `modules/hall-ui/public/sessions.html:55` |
790
790
  | `cccb362bd6da` | certain | Sessions — {{worldName}} | `modules/hall-ui/public/sessions.html:6` |
791
791
  | `cccb362bd6da` | certain | Sessions — {{worldName}} | `modules/hall-ui/public/sessions.html:6` |
792
- | `b823d9a37a35` | certain | Set up key storage | `modules/hall-ui/public/settings.js:1050` |
792
+ | `b823d9a37a35` | certain | Set up key storage | `modules/hall-ui/public/settings.js:1059` |
793
793
  | `84f31c3c3797` | certain | Set up your machine / get the code | `modules/hall-ui/public/hall-render.js:717` |
794
- | `f639250de42f` | certain | Setting up key storage… | `modules/hall-ui/public/settings.js:1134` |
794
+ | `f639250de42f` | certain | Setting up key storage… | `modules/hall-ui/public/settings.js:1143` |
795
795
  | `44bd6c3a2471` | certain | Setting up your box… (about a minute) | `modules/hall-ui/public/box-panel.js:298` |
796
796
  | `65509721fe12` | certain | Setting up… | `modules/hall-ui/public/box-panel.js:352` |
797
797
  | `62c3ea026095` | certain | Settings sections | `modules/hall-ui/public/settings.html:43` |
@@ -924,7 +924,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
924
924
  | `b6e04e9bc86f` | certain | Try reloading in a moment. | `modules/hall-ui/public/task.js:346` |
925
925
  | `1a64679fbb42` | certain | Typo or grammar | `modules/hall-ui/public/copy-desk.html:96` |
926
926
  | `2c1c20785a6e` | certain | Unclear — a person would not know what to do | `modules/hall-ui/public/copy-desk.html:93` |
927
- | `aa445f06cc5e` | certain | Unlink failed: {…} | `modules/hall-ui/public/settings.js:929` |
927
+ | `aa445f06cc5e` | certain | Unlink failed: {…} | `modules/hall-ui/public/settings.js:938` |
928
928
  | `67fbc770b3b3` | certain | Upvote (+1) | `modules/hall-ui/public/builders.js:730` |
929
929
  | `e8d747720e47` | certain | View all sessions → | `modules/hall-ui/public/watch.html:96` |
930
930
  | `9b92aa01516d` | certain | View all {…} {…} → | `modules/hall-ui/public/goals-render.js:530` |
@@ -984,7 +984,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
984
984
  | `6b759151f722` | certain | You have reached the end. The button below is now active. | `modules/hall-ui/public/primer.js:529` |
985
985
  | `6d5a4ca58dd6` | certain | You haven’t joined any goals yet. | `modules/hall-ui/public/goals.js:83` |
986
986
  | `8e527ab12334` | certain | You {…}. One vote per member. | `modules/hall-ui/public/government.js:954` |
987
- | `8e1915b19274` | certain | You're in the {…} server with your rank role. | `modules/hall-ui/public/settings.js:906` |
987
+ | `8e1915b19274` | certain | You're in the {…} server with your rank role. | `modules/hall-ui/public/settings.js:915` |
988
988
  | `6a4ca8ccf466` | certain | You're not signed in yet. Sign in to manage your preferences. | `modules/hall-ui/public/settings.html:34` |
989
989
  | `7d26333b5fb0` | certain | Your asks | `modules/hall-ui/public/collab.html:45` |
990
990
  | `59a66b5ac5dd` | certain | Your box is up — waiting for the terminal to come online (a few seconds after boot)… | `modules/hall-ui/public/box-panel.js:282` |
@@ -996,15 +996,15 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
996
996
  | `4ca77de13df4` | certain | Your dev box is stopped — turn it back on below. | `modules/hall-ui/public/box-panel.js:332` |
997
997
  | `909b0b7c6ffa` | certain | Your display name | `modules/hall-ui/public/settings.html:75` |
998
998
  | `51cae49539b5` | certain | Your files are kept | `modules/hall-ui/public/box-panel.js:323` |
999
- | `a47f15b6a33c` | certain | Your image-generation key settings could not be loaded. Reload the page to try again. | `modules/hall-ui/public/settings.js:1201` |
999
+ | `a47f15b6a33c` | certain | Your image-generation key settings could not be loaded. Reload the page to try again. | `modules/hall-ui/public/settings.js:1210` |
1000
1000
  | `20d453b11ae5` | certain | Your name | `modules/hall-ui/public/hall-render.js:275` |
1001
- | `6dadadffa36e` | certain | Your name cannot be blank. | `modules/hall-ui/public/settings.js:817` |
1002
- | `bd77210a8c90` | certain | Your name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:822` |
1001
+ | `6dadadffa36e` | certain | Your name cannot be blank. | `modules/hall-ui/public/settings.js:826` |
1002
+ | `bd77210a8c90` | certain | Your name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:831` |
1003
1003
  | `7d0452671d54` | certain | Your own idea. You may vote, but it can\u2019t be decided by your vote alone, and a vote on your own idea earn | `modules/hall-ui/public/government.js:883` |
1004
1004
  | `8fc605026acf` | certain | Your pending join {…}: {…} — awaiting approval. | `modules/hall-ui/public/goal-inbox.js:88` |
1005
- | `e91418db3962` | certain | Your preferences, {…}. | `modules/hall-ui/public/settings.js:841` |
1006
- | `e91418db3962` | certain | Your preferences, {…}. | `modules/hall-ui/public/settings.js:1374` |
1007
- | `73ee3dc369a5` | certain | Your profile page setting applies now — private already answers "not found" everywhere your profile is read. R | `modules/hall-ui/public/settings.html:110` |
1005
+ | `e91418db3962` | certain | Your preferences, {…}. | `modules/hall-ui/public/settings.js:850` |
1006
+ | `e91418db3962` | certain | Your preferences, {…}. | `modules/hall-ui/public/settings.js:1383` |
1007
+ | `b6dceaace783` | certain | Your profile page setting applies now — private already answers "not found" everywhere your profile is read. R | `modules/hall-ui/public/settings.html:110` |
1008
1008
  | `f39746e3d66b` | certain | Your rendering preference could not be loaded. Reload the page to try again. | `modules/hall-ui/public/settings.js:549` |
1009
1009
  | `b2dfd7120052` | certain | Your request is sent ✓ | `modules/hall-ui/public/hall-render.js:372` |
1010
1010
  | `c16addf957d0` | certain | Your track record across every project you build on, shown on your public profile. Hiding it takes effect imme | `modules/hall-ui/public/settings.html:87` |
@@ -1197,7 +1197,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1197
1197
  | `3ad8f32dd43b` | certain | {…} you have sent | `modules/hall-ui/public/profile-connections.js:137` |
1198
1198
  | `8186b562553a` | certain | {…} {…} waiting | `modules/hall-ui/public/work.js:356` |
1199
1199
  | `0d4016a5531c` | certain | {…} {…}{…} | `modules/hall-ui/public/work.js:220` |
1200
- | `b3757ba3bb46` | certain | {…} · Stored encrypted; never shown again after saving. | `modules/hall-ui/public/settings.js:1036` |
1200
+ | `b3757ba3bb46` | certain | {…} · Stored encrypted; never shown again after saving. | `modules/hall-ui/public/settings.js:1045` |
1201
1201
  | `94445e6ed5e8` | certain | {…} · code | `modules/hall-ui/public/pair.js:53` |
1202
1202
  | `5a71c11cdd91` | certain | {…} · via rank | `modules/hall-ui/public/government.js:309` |
1203
1203
  | `085f93f3f775` | certain | {…} — see all standings | `modules/hall-ui/public/hall-render.js:80` |
@@ -1208,7 +1208,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1208
1208
  | `99d107c17070` | certain | · by {…} · | `modules/hall-ui/public/gate.js:138` |
1209
1209
  | `4188b6f8997e` | certain | · default (on) | `modules/hall-ui/public/settings.js:500` |
1210
1210
  | `f8c4498ef0f2` | certain | · default for your rank | `modules/hall-ui/public/settings.js:410` |
1211
- | `9588652a7aff` | certain | · follows your profile setting | `modules/hall-ui/public/settings.js:622` |
1211
+ | `9588652a7aff` | certain | · follows your profile setting | `modules/hall-ui/public/settings.js:631` |
1212
1212
  | `893901f11e81` | certain | · {…} permission{…} | `modules/hall-ui/public/government.js:147` |
1213
1213
  | `4a5ff4f662df` | certain | — ${…} of ${…} this month ({…}%). {…} | `modules/hall-ui/public/hall-render.js:452` |
1214
1214
  | `cbd220dd9184` | certain | — a later push must be re-approved. | `modules/hall-ui/public/gate.js:87` |