@bongos/core 1.19.578 → 1.19.580
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.
- package/.bongos-core.json +68 -38
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +4 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/adr/0255-a-public-lists-ordering-is-part-of-its-payload.md +4 -1
- package/docs/adr/0259-a-projects-departure-from-the-public-list-is-public.md +128 -0
- package/docs/adr/0260-the-application-is-the-consent-and-the-echo-is-the-gate.md +146 -0
- package/docs/adr/README.md +2 -0
- package/docs/api/openapi.json +73 -3
- package/docs/api-reference.md +3 -2
- package/docs/copy-inventory.md +23 -21
- package/docs/copy-registry.json +51 -33
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +4 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/hall-ui/public/oversight.css +7 -0
- package/modules/hall-ui/public/watch.js +75 -0
- package/modules/onboarding/routes/access-requests.js +56 -1
- package/modules/platform-identity/applicant-profile.js +158 -0
- package/modules/platform-identity/application-echo.js +50 -0
- package/modules/platform-identity/recruiter-sliver.js +19 -0
- package/modules/platform-identity/routes/sso.js +126 -0
- package/modules/public-landing/public/projects.html +2 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/bongos/auth-admission.js +61 -0
- package/src/bongos/auth.js +2 -1
- package/src/module-api.js +11 -1
- package/tests/adr_renumber_integrity.mjs +84 -0
- package/tests/applicant_profile_boundary.mjs +641 -0
- package/tests/applicant_profile_read_bounds.mjs +95 -0
- package/tests/module_api.mjs +1 -0
- package/tests/projects_hub.mjs +24 -0
- package/tests/recruiter_sliver_boundary.mjs +35 -2
- package/tests/watch_applications_queue.mjs +94 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# ADR 0260 — An application IS the consent, and the hub's own echo is the gate: the D7 applicant view
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-09-03
|
|
5
|
+
- **Task:** [task 1002972](https://cloudbongos.com/builders#/task/1002972) (PV7, goal 1000045 — criterion C4)
|
|
6
|
+
- **Relates to:** `docs/specs/<redacted>.md` **D7** (owner-signed 2026-08-16), [ADR 0215](<redacted>.md) (the D3 sliver this reuses), [ADR 0205](<redacted>.md) + security report 1000027 (client credentials name a project, never a person), [ADR 0201](<redacted>.md) D1.2/D1.3 (the vouch mark and the statusless echo), [ADR 0171](<redacted>.md) D4/D5 (indistinguishable nulls, no-store), [ADR 0016](<redacted>.md) (descriptive, never authority), [ADR 0083](<redacted>.md) (the doorway)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
Spec D7 asks for one thing in one sentence: a reviewer looking at an application
|
|
11
|
+
sees **what the applicant's own profile rules would already show them**, plus the
|
|
12
|
+
applicant's note, **evaluated live at review time**. Public account → the public
|
|
13
|
+
profile view. Private account → the D3 sliver. No new disclosure class.
|
|
14
|
+
|
|
15
|
+
Two halves of that already existed when this task opened. The applicant's note
|
|
16
|
+
reaches the project's queue through the join relay (task 1002330,
|
|
17
|
+
`relayApplicationNote`). The D3 projection exists and is proved
|
|
18
|
+
([ADR 0215](<redacted>.md)). What did not
|
|
19
|
+
exist was the **rule** — which of the two views an applicant gets — and the
|
|
20
|
+
**path** by which a project's reviewer queue could ask the hub for it.
|
|
21
|
+
|
|
22
|
+
Three things about that path are not obvious, and each could have been got wrong
|
|
23
|
+
in a way that looked like a simplification.
|
|
24
|
+
|
|
25
|
+
## Decision
|
|
26
|
+
|
|
27
|
+
### D1 — The rule is one port composing the two EXISTING views, never a third shape
|
|
28
|
+
|
|
29
|
+
`modules/platform-identity/applicant-profile.js` answers
|
|
30
|
+
`null | { view:'public', account, cross_project } | { view:'sliver', sliver }`.
|
|
31
|
+
|
|
32
|
+
The public branch's rollup half is `getPublicProfileExtras` — the very port the
|
|
33
|
+
canonical `/u/<handle>` page calls. The private branch's projection is
|
|
34
|
+
`sliverShapeFor`, exported from `recruiter-sliver.js` — the very function the
|
|
35
|
+
recruiting route serializes. **Neither branch builds its own object**, because a
|
|
36
|
+
third five-key lookalike *is* the new disclosure class D7 forbids: free to drift
|
|
37
|
+
from the original field by field, and uncovered by the whitelist proof over it.
|
|
38
|
+
|
|
39
|
+
`tests/applicant_profile_boundary.mjs` asserts both key sets against the
|
|
40
|
+
**modules' own exported lists**, never against copies kept in the test.
|
|
41
|
+
|
|
42
|
+
### D2 — The APPLICATION is the consent, not the recruiting opt-in
|
|
43
|
+
|
|
44
|
+
This is the one place the applicant view differs from the recruiter sliver, and
|
|
45
|
+
it is the decision most likely to be "tidied" away later.
|
|
46
|
+
|
|
47
|
+
`getRecruiterSliver` floors on `recruiterSliverVisibleSql` = consent **and
|
|
48
|
+
recruiting reach**, because a recruiter browsing a directory was invited by
|
|
49
|
+
nobody. An applicant has done something a browsing recruiter has not — spec D7
|
|
50
|
+
says it in those words: **"applying is an explicit act"**.
|
|
51
|
+
|
|
52
|
+
So routing this port through `getRecruiterSliver` would be wrong *in the
|
|
53
|
+
direction that looks safe*. `recruiter_discoverable` defaults to **false** for a
|
|
54
|
+
private account, so a private builder who deliberately applied would show their
|
|
55
|
+
reviewer **nothing at all**, and criterion C4 would be satisfied by an empty box.
|
|
56
|
+
The reach opt-out governs the *recruiting surface* — `account-visibility.js` says
|
|
57
|
+
exactly that of `scoutingListableSql` — and was never a gate on a door the
|
|
58
|
+
account itself knocked on.
|
|
59
|
+
|
|
60
|
+
**What the swap does NOT relax**, and this is what keeps it from meaning
|
|
61
|
+
"applying opts you into everything":
|
|
62
|
+
|
|
63
|
+
- `accountActiveSql` still floors it — `profile_state='active'` **and**
|
|
64
|
+
`terms_accepted_at IS NOT NULL`. A provisional account and one that never
|
|
65
|
+
accepted the platform terms disclose nothing, applying or not.
|
|
66
|
+
- `hide_stats` is untouched in both branches. Applying is consent to be **seen**,
|
|
67
|
+
never consent to be **counted**.
|
|
68
|
+
- The existence axis stays off, for ADR 0215 D1's reason: the private account is
|
|
69
|
+
precisely this rule's subject.
|
|
70
|
+
|
|
71
|
+
The proof asserts the swap **in both directions on the same account** — `PRIVOUT`
|
|
72
|
+
gets an applicant view and gets `null` from `getRecruiterSliver` — so the
|
|
73
|
+
tempting refactor cannot pass quietly.
|
|
74
|
+
|
|
75
|
+
### D3 — The gate is the hub's own echo, because client credentials name a project and not a person
|
|
76
|
+
|
|
77
|
+
`POST /sso/applicant-profile` is authenticated by `client_id` + `client_secret`,
|
|
78
|
+
like its two siblings. **That authentication is not sufficient on its own**, and
|
|
79
|
+
this is the whole security argument for the route.
|
|
80
|
+
|
|
81
|
+
[ADR 0205](<redacted>.md) / security
|
|
82
|
+
report 1000027 is the lesson `/sso/membership/check-in` and `/sso/activity/rollup`
|
|
83
|
+
both had to learn: credentials prove *which project* is calling and say **nothing
|
|
84
|
+
about who the `github_id` in the body is**. Without a per-subject witness, this
|
|
85
|
+
route is a **bulk disclosure oracle** over every account on the platform —
|
|
86
|
+
private ones included, since D7's private branch is exactly the disclosure the
|
|
87
|
+
existence axis normally withholds. That is strictly worse than the rollup hole it
|
|
88
|
+
would mirror.
|
|
89
|
+
|
|
90
|
+
The witness is `platform_identity_application_echoes` — the statusless
|
|
91
|
+
"you applied to this project on this date" row from
|
|
92
|
+
[ADR 0201](<redacted>.md) D1.3. It is
|
|
93
|
+
the right witness because **the hub writes it itself**, in its own join relay,
|
|
94
|
+
only after the project answered the relayed application with a success. A client
|
|
95
|
+
cannot assert itself into that table. `applicationBacksProfileRead` is the exact
|
|
96
|
+
analogue of `membershipBacksRollup`: a boolean, and the narrowest cross-account
|
|
97
|
+
read the table has — the caller must already name both the account and the
|
|
98
|
+
project, and there is no listing by `client_id`, so a project learns nothing
|
|
99
|
+
about who applied that it was not already told at its own door.
|
|
100
|
+
|
|
101
|
+
It reuses the **same 30-day window**, and that is load-bearing rather than tidy:
|
|
102
|
+
when the echo stops matching, the view stops rendering, because the platform has
|
|
103
|
+
stopped vouching for the link between that queue row and that account.
|
|
104
|
+
|
|
105
|
+
Refusal is **404, never 403** — a 403 would confirm the `github_id` names a real
|
|
106
|
+
account. And the gate runs **before any account is read**: the proof asserts that
|
|
107
|
+
on the statement log, not on the response, because a gate that refuses *after*
|
|
108
|
+
reading has already done the disclosure work.
|
|
109
|
+
|
|
110
|
+
### D4 — LIVE means nothing is stored, at either end
|
|
111
|
+
|
|
112
|
+
Nothing about the applicant is written to the `access_requests` row and nothing is
|
|
113
|
+
cached on the project. The profile is resolved on **every render**
|
|
114
|
+
(`attachApplicantProfiles`), so an applicant who hides their stats, goes private,
|
|
115
|
+
or loses their account between applying and being reviewed is answered by the next
|
|
116
|
+
read of the queue — criterion C2's "immediately". A snapshot taken at apply time
|
|
117
|
+
would keep publishing a consent that had since been withdrawn, for as long as the
|
|
118
|
+
request sat in the queue. The hub sends `Cache-Control: no-store`; the project
|
|
119
|
+
keeps nothing.
|
|
120
|
+
|
|
121
|
+
### D5 — The queue keys on the VOUCH, never on `github_login`
|
|
122
|
+
|
|
123
|
+
`attachApplicantProfiles` resolves only rows carrying `applicant_github_id` — the
|
|
124
|
+
hub's own assertion about who filed the request (`core_230`). `POST /access-requests`
|
|
125
|
+
is the one **public unauthenticated write** on the GDS, so `github_login` is a
|
|
126
|
+
string anybody may type. Resolving a cross-project record against an unvouched
|
|
127
|
+
login is precisely the impersonation surface the vouch exists to close: file a
|
|
128
|
+
request naming a well-known builder, let the owner read that builder's excellent
|
|
129
|
+
record, and walk in. An unvouched row gets `profile: null`, always.
|
|
130
|
+
|
|
131
|
+
### D6 — The credential stays in core; the module gets a narrow port
|
|
132
|
+
|
|
133
|
+
The hub call lives in `src/bongos/auth-admission.js` beside the two other calls
|
|
134
|
+
that hold the hub client secret, and `loadIdpConfig` stays **off** the doorway —
|
|
135
|
+
putting it there would hand every module the credential that speaks for the whole
|
|
136
|
+
project. `<redacted>(githubId)` is published instead: one
|
|
137
|
+
`github_id` in, one already-bounded view out. The module can neither widen the
|
|
138
|
+
request nor re-address it.
|
|
139
|
+
|
|
140
|
+
## Consequences
|
|
141
|
+
|
|
142
|
+
- **The path is complete but DORMANT until R09 ([task 1002285](https://cloudbongos.com/builders#/task/1002285)) ships the vouch writer.** Nothing in the tree writes `applicant_github_id` today, so every queue row currently resolves `profile: null` and renders exactly as it did before. This is stated rather than glossed: the feature is wired end to end and proved, and it lights up on the day R09 lands its writer — the sequencing R08's own migration comment predicted. 1002972's declared dependency was PV3 alone; **the real dependency on R09 was missing from the graph.**
|
|
143
|
+
- The reviewer queue degrades rather than breaks: a hub outage, a self-hosted instance with no hub, and an applicant with no echo all render a row with its login, note and vouch pill and no profile block.
|
|
144
|
+
- `MAX_LIVE_PROFILE_READS = 25` caps per-render hub round-trips against a 200-row queue. It bites on vouched rows in list order, so the rows a reviewer acts on carry the profile. Raising it buys detail and costs latency; it changes nothing about what may be disclosed.
|
|
145
|
+
- `recruiter-sliver.js` now has a second first-party reader. The sole-reader guard in `tests/recruiter_sliver_boundary.mjs` was widened with a stated reason **and strengthened**: every listed reader is now checked to not *branch* on a sliver field, so the property the guard protects — descriptive data is never consulted as authority — is enforced rather than trusted.
|
|
146
|
+
- **Still not built:** the apply UI's *"your application shares: …"* disclosure line D7 names. There is no apply UI anywhere — `POST /my-projects/join` has no browser caller — so the sentence has no page to live on. It belongs with whichever task builds that surface, and is filed rather than silently dropped.
|
package/docs/adr/README.md
CHANGED
|
@@ -350,3 +350,5 @@ This keeps the decision history honest and traceable.
|
|
|
350
350
|
> ⚠️ **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.
|
|
351
351
|
| 0257 | [**Auth resolves before the hall mounts anything, and a widget's boot read may never navigate** ([task 1003673](https://cloudbongos.com/builders#/task/1003673) · goal 1000063 — *The front door*). An invite-only instance could not admit its FIRST builder, and the symptom lied about where the fault was: an owner saw an empty Access-requests queue and no approve button, because **signing in does not file a request** — only the landing's *Request access* form does, and that form was unreachable. A signed-out visitor to `/builders` was bounced to GitHub, refused as a first-timer ("request access first"), and pointed back at `/builders` to be bounced again. Reproduced against `main`, not just an old pin. `builders.js` was already careful — `/me` is read `softAuth` and a 401 there renders the landing — but `DOMContentLoaded` called `mountHallWidgets()` FIRST, synchronously, and `goals.js`'s mount-time read of `/goals` goes through a `getJSON` with no `softAuth`, which answers 401 by NAVIGATING. The widget's read raced `renderLanding()` and won. **Decision: the front door settles which page this is before anything else runs** — `boot()` reads `/me` (soft), then either renders the landing and stops (nothing mounts, nothing else fetches) or mounts the hall, handing the resolved payload to `loadAll()` so the page still asks once. Widgets are member surfaces (`renderLanding` hid them all after the fact anyway), so not mounting them while signed out removes the CLASS rather than the one instance of it that was found; **a widget's own boot read may never navigate** is the belt beside it (`goals.js` reads soft and renders nothing without a session). A 401 during boot is not an instruction to go and sign in — only a user action is. `tests/hall_landing_boot.mjs` executes the real `builders.js` in a DOM stub and was confirmed to FAIL against the pre-fix file. Rejected: patching `goals.js` alone (it was merely first); making the 401 redirect soft everywhere (an expired session mid-visit SHOULD be sent to sign in — the line is boot vs user action); open enrollment as the cure (removes the gate [ADR 0050](<redacted>.md) chose deliberately instead of repairing the door).](<redacted>.md) | hall-ui / admission / front door |
|
|
352
352
|
| 0258 | [**The public CLI is a generated client-only package, and its file list is proven by running it** ([task 1003679](https://cloudbongos.com/builders#/task/1003679) · goal 1000054 — *A newcomer can build without the UI*). The core ships private as `@bongos/core` ([ADR 0108](<redacted>.md)), so a newcomer with no credential can install NOTHING and the web hall is the only way in — the owner's words: "how am I supposed to easily take on tasks as a new builder? I should be able to do everything without the UI." Open task 1002025 proposed publishing the core, which ships the SERVER and bypasses [ADR 0099](<redacted>.md)'s redaction pipeline (dormant until ~2026-11). **Decision: generate a separate public `@cloudbongos/cli` from the core and do not publish the core.** Four load-bearing parts. (1) SCOPED NAME, because npm shares one namespace between org names and unscoped packages — the bare `cloudbongos` is unpublishable *precisely because the owner owns that org*, which npm reports as "invalid" and reads like the name is taken; and a package name cannot be created on the npm website at all (it exists on first publish, which is why "Add Existing Package" answered `Forbidden`). (2) THE FILE LIST IS DECLARED AND PROVEN BY BEHAVIOUR, never computed — a static require-closure CANNOT answer this, because `src/module-api.js` is the doorway a module may only import ([ADR 0083](<redacted>.md)) and it *names* every kernel capability, so a static walk sees 33 `src/` files from `start.js` alone where runtime resolves **one** (`api-prefix.js`, which imports nothing) — the same trap as task 1003677's unsatisfiable done-when. So the test packs the tarball, installs it into an empty dir with NO repo, and runs every verb: it may fail for want of a session, never for a missing file. That caught two real holes on its first strengthened run — `clients/bongos-client/index.mjs`, reached by a dynamic `import()` no `require()` walk can see, and a hand-listed `files` array that dropped `clients/` and produced a tarball which installed cleanly then died on first use; both are now build-time refusals, and the `files` array is derived from the manifest. (3) `claim`/`ship`/`dev`/`serve`/`module`/`upgrade`/`onboard`/`doctor`/`exec`/`package-core` are ABSENT and the CLI says WHY plus the next step (`bongos shell` → a cloud box with the full CLI) — a bare `unknown command` teaches nothing, which is the exact failure being fixed. The supported journey is `login` → `start` → `shell`. (4) A REDACTION GATE fails the build closed on non-loopback IPv4 (RFC 5737 doc ranges exempt), token/key shapes, and every domain + owner login readable from the instance's own `config/branding.json` — needles come from host config so the core carries no instance identity ([ADR 0062 §7](<redacted>.md)); `cloudbongos.com` is allowlisted as public by design. No `repository` field while the core repo is private (it would 404 for every user and publish the owner's login for nothing). 31 files, one dependency (`undici`), version independent of the core's ([ADR 0161](<redacted>.md)). `@bongos/client` is VENDORED, not depended on — a public package depending on a private one is uninstallable. **The owner runs `npm publish`; a builder must not.** Task 1002025 is superseded. Rejected: publishing the core; deriving from a static closure (structurally impossible past the doorway); waiting for the mirror (dormant, and this is a build product not a source release); an unscoped name; depending on `@bongos/client`; a degraded `claim`; shipping all of `src/` to make lazy getters safe.](<redacted>.md) | cli / distribution / public surface |
|
|
353
|
+
| 0259 | [**A project’s departure from the public list is public, and the copy says so** ([task 1003672](https://cloudbongos.com/builders#/task/1003672) · goal 1000046 — *Project creation*). Decides the leak [ADR 0255](<redacted>.md) §6.2 deliberately filed rather than implied fixed. The public projects feed publishes a named list plus a count of anonymous rows, so when a project flips to stealth its named row LEAVES the identified block while the count RISES BY ONE — *“Mercury is gone, and there is one more black hole”* names it, and the moment, from a single diff of two snapshots. **Everything [ADR 0182](<redacted>.md) D2a does is defeated by it**, because the identity was never carried ON the anonymous row (`STEALTH_ANONYMOUS_KEEPS` is an allow-list precisely so a column added next year is anonymous by default) — it is carried by the ABSENCE of the named row that used to sit beside it. **Larger than the channel 0255 closed**, which needed repeated sampling and correlation; this one is exact and needs two reads. No `ORDER BY` change touches it: it is inherent in publishing a named list at all, so every fix is a product decision with a visible cost and the owner’s call, not a builder’s. **Decision: accept it, and make the copy say so.** Two reasons it is the right end of the trade and not merely the cheapest — (1) it is ALREADY the honest reading of the existing promise, since D2a made existence and count public *by design*, and a count that is public and truthful is a count whose CHANGES are public; (2) both alternatives damage the control they defend. A **delay window** means the owner clicks the privacy setting and is not private yet *without knowing it*, converting an information leak into a false belief — strictly worse, and the wrong direction for a privacy control. **Decoys** spend the count’s truthfulness (it is truthful today) on a guarantee that is still only probabilistic, and a decoy scheme needs some way to tell padding from real rows — the exact stable per-project key D2a forbids. The promise stealth actually keeps is about the project’s CONTENTS, not the TRANSITION: an anonymous row stays anonymous (no name, tagline, art, origin, or key surviving to the next snapshot); what is not private is stepping off a published list readers may keep copies of. So the copy — which read *“its name, and everything else about it, stay yours”*, every clause true and the paragraph as a whole overselling, because a reader takes it to cover the switch — now names the boundary in BOTH places an owner meets the setting (the choice’s blurb and the what-changes fold), in the plain register 0182’s interview fixed for this card. **A privacy control that oversells is worse than one that admits a limit**, the same standard 0255 §6 set for itself. **No behaviour changes** in `projects-feed.js` — the feed, the redaction allow-list and the keyed rotating permutation are decided FINISHED, not insufficient. `tests/projects_hub.mjs` pins the sentence in both surfaces (the copy IS the fix, so a future edit tightening the blurb must not quietly drop it) and re-applies the no-space-metaphor ban to it. Carries 0255 §6.3’s smaller residual so both live in one place: within one 24h epoch the permutation is stable, so same-day snapshots tell black holes apart (not name them) — accepted on the same reasoning, since the fix is a per-request permutation, which breaks pagination exactly as `ORDER BY random()` was rejected for. Guards recorded for any future attempt: no stable per-project key on an anonymous row, and no anonymous ordering an observer can predict or correlate. Rejected: the delay; decoys; dropping the named list (protects a privacy nobody asked for at the cost of the feature); and saying nothing, which is the failure mode this closes.](<redacted>.md) | platform-identity / privacy boundary / copy honesty |
|
|
354
|
+
| 0260 | [**An application IS the consent, and the hub’s own echo is the gate** ([task 1002972](https://cloudbongos.com/builders#/task/1002972) · goal 1000045, criterion C4). Privacy spec **D7** asks that a reviewer see what the applicant’s OWN profile rules would already show, evaluated LIVE at review time. The rule is ONE port composing the two EXISTING views — `getPublicProfileExtras` for a public account, `recruiter-sliver`’s own `sliverShapeFor` for a private one — because a third five-key lookalike **is** the new disclosure class D7 forbids. **The one deliberate difference from the D3 sliver:** `getRecruiterSliver` floors on recruiting REACH, and reusing it verbatim would be wrong in the direction that looks safe — `recruiter_discoverable` defaults to FALSE for a private account, so a private builder who deliberately applied would show their reviewer NOTHING and C4 would be satisfied by an empty box. D7 settles it: *“applying is an explicit act”*. The swap relaxes REACH only; `accountActiveSql` (active **and** terms accepted) and `hide_stats` still floor it, and the proof asserts both directions on the same account so the tempting refactor cannot pass quietly. **The federated route’s gate is the whole security story** ([ADR 0205](<redacted>.md) / security report 1000027): client credentials name a PROJECT and never a person, so `POST /sso/applicant-profile` authenticated alone is a bulk disclosure oracle over every account on the platform, private ones included. `applicationBacksProfileRead` demands a HUB-WRITTEN echo for exactly (this account, this client) inside the same 30-day window — a row only the hub’s own join relay creates — refusing **404, never 403**, and BEFORE any account is read (asserted on the statement log, because a gate that refuses after reading has already done the disclosure work). LIVE means nothing is stored at either end; the queue keys on the VOUCH and never on `github_login` (the one PUBLIC unauthenticated write makes an unvouched login an impersonation surface); and the hub client secret stays in core behind a narrow doorway port. **The path is complete but DORMANT until R09 ([task 1002285](https://cloudbongos.com/builders#/task/1002285)) ships the vouch writer** — nothing writes `applicant_github_id` today, and that dependency was missing from 1002972’s graph. Rejected: routing the port through `getRecruiterSliver`, a snapshot at apply time, resolving by `github_login`, and putting `loadIdpConfig` on the doorway.](<redacted>.md) | platform identity / privacy |
|
package/docs/api/openapi.json
CHANGED
|
@@ -13818,6 +13818,45 @@
|
|
|
13818
13818
|
"security": []
|
|
13819
13819
|
}
|
|
13820
13820
|
},
|
|
13821
|
+
"/sso/applicant-profile": {
|
|
13822
|
+
"post": {
|
|
13823
|
+
"operationId": "post_sso_applicant_profile",
|
|
13824
|
+
"tags": [
|
|
13825
|
+
"sso"
|
|
13826
|
+
],
|
|
13827
|
+
"summary": "POST /sso/applicant-profile",
|
|
13828
|
+
"description": "POST /sso/applicant-profile — a federated instance resolves ONE applicant's profile view for its own reviewer queue, LIVE at render (privacy spec D7, task 1002972). Server-to-server, client_id+client_secret auth, like the two routes above. Answers { profile: null | { view:'public', … } | { view: 'sliver', … } } — the D7 rule, decided entirely inside ../applicant-profile.js. WHY A POST FOR A READ. The same reason /sso/activity/rollup is one: the credentials are in the body, and a client_secret in a query string lands in access logs and proxy history. Nothing is written. THE ECHO IS THE GATE, AND IT IS THE WHOLE SECURITY ARGUMENT (ADR 0205, security report 1000027). Client credentials prove WHICH PROJECT is calling and nothing about WHO the github_id is, so authenticating the caller is not enough: without a per-subject witness this route is a bulk disclosure oracle over every account on the platform, private ones included, readable by any registered project holding only its own secret. applicationBacksProfileRead demands a HUB-WRITTEN echo for exactly (this account, this client) inside the 30-day window — a row only the hub's own join relay creates, and only after the project accepted the relayed application. A project may therefore read the profile of someone who applied TO IT, and of nobody else. 404, never 403, when the echo is absent — the /scouting/:handle posture. A 403 would confirm that the github_id names a real account, which is the disclosure the whole rule exists to withhold. An account that exists but discloses nothing (provisional, terms never accepted) answers the SAME { profile: null } as one that consented but is simply not readable, so the caller cannot tell those apart either (ADR 0171 D4). NOT AUTHORITY (ADR 0016). The answer is descriptive; the project's own admission gate reads status='invited' and never this. rank: public — authenticated by client_id + client_secret, not a builder rank. The limiter runs BEFORE the client lookup, so a refused probe costs no DB work — the accountExistenceReadRateLimit posture.\n\n**Rank:** `public` — No authentication — any caller.",
|
|
13829
|
+
"x-rank": "public",
|
|
13830
|
+
"x-source": "modules/platform-identity/routes/sso.js",
|
|
13831
|
+
"requestBody": {
|
|
13832
|
+
"required": true,
|
|
13833
|
+
"content": {
|
|
13834
|
+
"application/json": {
|
|
13835
|
+
"schema": {
|
|
13836
|
+
"$ref": "#/components/schemas/PostSsoApplicantProfileRequest"
|
|
13837
|
+
}
|
|
13838
|
+
}
|
|
13839
|
+
},
|
|
13840
|
+
"x-validated": true
|
|
13841
|
+
},
|
|
13842
|
+
"responses": {
|
|
13843
|
+
"200": {
|
|
13844
|
+
"description": "Success.",
|
|
13845
|
+
"content": {
|
|
13846
|
+
"application/json": {
|
|
13847
|
+
"schema": {
|
|
13848
|
+
"$ref": "#/components/schemas/PostSsoApplicantProfileResponse"
|
|
13849
|
+
}
|
|
13850
|
+
}
|
|
13851
|
+
}
|
|
13852
|
+
},
|
|
13853
|
+
"400": {
|
|
13854
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
13855
|
+
}
|
|
13856
|
+
},
|
|
13857
|
+
"security": []
|
|
13858
|
+
}
|
|
13859
|
+
},
|
|
13821
13860
|
"/sso/authorize": {
|
|
13822
13861
|
"get": {
|
|
13823
13862
|
"operationId": "get_sso_authorize",
|
|
@@ -21703,6 +21742,37 @@
|
|
|
21703
21742
|
"ok"
|
|
21704
21743
|
]
|
|
21705
21744
|
},
|
|
21745
|
+
"PostSsoApplicantProfileRequest": {
|
|
21746
|
+
"type": "object",
|
|
21747
|
+
"properties": {
|
|
21748
|
+
"client_id": {
|
|
21749
|
+
"type": "string",
|
|
21750
|
+
"maxLength": 200
|
|
21751
|
+
},
|
|
21752
|
+
"client_secret": {
|
|
21753
|
+
"type": "string",
|
|
21754
|
+
"maxLength": 512
|
|
21755
|
+
},
|
|
21756
|
+
"github_id": {
|
|
21757
|
+
"$ref": "#/components/schemas/StringifiableId"
|
|
21758
|
+
}
|
|
21759
|
+
},
|
|
21760
|
+
"required": [
|
|
21761
|
+
"client_id",
|
|
21762
|
+
"client_secret",
|
|
21763
|
+
"github_id"
|
|
21764
|
+
],
|
|
21765
|
+
"additionalProperties": false
|
|
21766
|
+
},
|
|
21767
|
+
"PostSsoApplicantProfileResponse": {
|
|
21768
|
+
"type": "object",
|
|
21769
|
+
"properties": {
|
|
21770
|
+
"profile": {}
|
|
21771
|
+
},
|
|
21772
|
+
"required": [
|
|
21773
|
+
"profile"
|
|
21774
|
+
]
|
|
21775
|
+
},
|
|
21706
21776
|
"PostSsoDevicePollRequest": {
|
|
21707
21777
|
"type": "object",
|
|
21708
21778
|
"properties": {
|
|
@@ -22605,9 +22675,9 @@
|
|
|
22605
22675
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
22606
22676
|
}
|
|
22607
22677
|
},
|
|
22608
|
-
"x-endpoint-count":
|
|
22609
|
-
"x-schema-count":
|
|
22678
|
+
"x-endpoint-count": 359,
|
|
22679
|
+
"x-schema-count": 395,
|
|
22610
22680
|
"x-undocumented-bodies": 9,
|
|
22611
|
-
"x-response-schemas":
|
|
22681
|
+
"x-response-schemas": 267,
|
|
22612
22682
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
22613
22683
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -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.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 359 endpoints across 58 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`.
|
|
@@ -556,11 +556,12 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
556
556
|
| GET | `/api/bongos/sessions/mine` | `any-builder` | — | your OWN sessions (self-serve; no audit needed). |
|
|
557
557
|
| GET | `/api/bongos/sessions/search` | `metic+archon` | — | cross-builder corpus search (BFG-principal posture until 6C.1). |
|
|
558
558
|
|
|
559
|
-
## `sso` (
|
|
559
|
+
## `sso` (8)
|
|
560
560
|
|
|
561
561
|
| Method | Path | Rank | Body | Description |
|
|
562
562
|
|---|---|---|---|---|
|
|
563
563
|
| POST | `/api/bongos/sso/activity/rollup` | `public` | `client_id`, `client_secret`, `github_id`, `credits`, `tasks_shipped`, `karma`, `rank`, `disciplines`, `recent_ships` | POST /sso/activity/rollup — a federated instance reports a builder's activity snapshot (ADR 0141 §4). |
|
|
564
|
+
| POST | `/api/bongos/sso/applicant-profile` | `public` | `client_id`, `client_secret`, `github_id` | POST /sso/applicant-profile — a federated instance resolves ONE applicant's profile view for its own reviewer queue, LIVE at render (priv… |
|
|
564
565
|
| GET | `/api/bongos/sso/authorize` | `public` | — | GET /sso/authorize?client_id=&redirect_uri=&state= — the browser authorize leg. |
|
|
565
566
|
| POST | `/api/bongos/sso/device/poll` | `public` | `device_code` | POST /sso/device/poll — poll the hub device flow. |
|
|
566
567
|
| POST | `/api/bongos/sso/device/start` | `public` | `origin` | POST /sso/device/start — begin CLI federation. |
|
package/docs/copy-inventory.md
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
> Deterministic on a given tree — regenerate and commit rather than hand-editing.
|
|
5
5
|
> Machine-readable twin: [`copy-registry.json`](copy-registry.json).
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**1709 strings** across 3 surfaces · 1478 distinct pieces of copy · 1709 certain, 0 heuristic · 162 shown in more than one place.
|
|
8
8
|
|
|
9
9
|
## Surfaces
|
|
10
10
|
|
|
11
11
|
| surface | lives at | files | strings |
|
|
12
12
|
|---|---|---|---|
|
|
13
|
-
| `builders-hall` | `modules/hall-ui/public` | 78 |
|
|
13
|
+
| `builders-hall` | `modules/hall-ui/public` | 78 | 1237 |
|
|
14
14
|
| `status-dashboard` | `modules/status-ui/public` | 4 | 100 |
|
|
15
|
-
| `landing` | `modules/public-landing/public` | 5 |
|
|
15
|
+
| `landing` | `modules/public-landing/public` | 5 | 372 |
|
|
16
16
|
|
|
17
17
|
## Confidence, and why it is on every row
|
|
18
18
|
|
|
@@ -75,10 +75,10 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
75
75
|
| `996edffc1966` | 2x | Access requests | modules/hall-ui/public/watch.html:46, modules/hall-ui/public/watch.html:61 |
|
|
76
76
|
| `a072071b893c` | 2x | All time | modules/status-ui/public/index.html:286, modules/status-ui/public/index.html:313 |
|
|
77
77
|
| `490b73a0c6e8` | 2x | Approve your Dev Box app — {{worldName}} | modules/hall-ui/public/pair.html:6, modules/hall-ui/public/pair.html:6 |
|
|
78
|
-
| `b2656d0b2402` | 2x | Asked {…} | modules/hall-ui/public/collab.js:41, modules/hall-ui/public/watch.js:
|
|
78
|
+
| `b2656d0b2402` | 2x | Asked {…} | modules/hall-ui/public/collab.js:41, modules/hall-ui/public/watch.js:464 |
|
|
79
79
|
| … | | _122 more in the JSON registry_ | |
|
|
80
80
|
|
|
81
|
-
## `builders-hall` —
|
|
81
|
+
## `builders-hall` — 1237 strings
|
|
82
82
|
|
|
83
83
|
| id | conf | text | where |
|
|
84
84
|
|---|---|---|---|
|
|
@@ -138,6 +138,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
138
138
|
| `303f8d90266f` | certain | Achievements could not be loaded. | `modules/hall-ui/public/builders.js:1158` |
|
|
139
139
|
| `6ca31dd5eb91` | certain | Acknowledge the primer | `modules/hall-ui/public/primer.html:99` |
|
|
140
140
|
| `4461b13f95c2` | certain | Actions apply at once. Closing stops and deletes the box; you can start a fresh one anytime. | `modules/hall-ui/public/settings.html:209` |
|
|
141
|
+
| `74cc57f76b42` | certain | Active recently | `modules/hall-ui/public/watch.js:411` |
|
|
141
142
|
| `524188fe0078` | certain | Active sessions | `modules/hall-ui/public/settings.html:162` |
|
|
142
143
|
| `f6036360c90c` | certain | Activity, by craft | `modules/hall-ui/public/profile.html:133` |
|
|
143
144
|
| `62eded408097` | certain | Add {…} | `modules/hall-ui/public/profile-nudge.js:68` |
|
|
@@ -162,7 +163,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
162
163
|
| `01a0f29ff406` | certain | As first filed | `modules/hall-ui/public/idea.js:252` |
|
|
163
164
|
| `688cc6dd38ee` | certain | Asked of you | `modules/hall-ui/public/collab.html:37` |
|
|
164
165
|
| `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/collab.js:41` |
|
|
165
|
-
| `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/watch.js:
|
|
166
|
+
| `b2656d0b2402` | certain | Asked {…} | `modules/hall-ui/public/watch.js:464` |
|
|
166
167
|
| `8c8ec2597036` | certain | Assigned {…} to builder {…}. | `modules/hall-ui/public/government.js:470` |
|
|
167
168
|
| `46714066f2da` | certain | Audit log | `modules/hall-ui/public/watch.html:148` |
|
|
168
169
|
| `1de02052abf2` | certain | Available from the {…} rank up. | `modules/hall-ui/public/gate.js:222` |
|
|
@@ -273,8 +274,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
273
274
|
| `7bcaeffb742f` | certain | Could not approve: {…} | `modules/hall-ui/public/gate.js:108` |
|
|
274
275
|
| `c922293e668c` | certain | Could not assign: {…} | `modules/hall-ui/public/government.js:475` |
|
|
275
276
|
| `94763c4d5a94` | certain | Could not block: {…} | `modules/hall-ui/public/harbor.js:167` |
|
|
276
|
-
| `e1fc7cedf4e7` | certain | Could not change rank: {…} | `modules/hall-ui/public/watch.js:
|
|
277
|
-
| `b9e53fbd90e6` | certain | Could not change standing: {…} | `modules/hall-ui/public/watch.js:
|
|
277
|
+
| `e1fc7cedf4e7` | certain | Could not change rank: {…} | `modules/hall-ui/public/watch.js:795` |
|
|
278
|
+
| `b9e53fbd90e6` | certain | Could not change standing: {…} | `modules/hall-ui/public/watch.js:821` |
|
|
278
279
|
| `1ef1efc15b6c` | certain | Could not change that just now. | `modules/hall-ui/public/goals-render.js:1059` |
|
|
279
280
|
| `78e18ea59b9f` | certain | Could not close: {…} | `modules/hall-ui/public/harbor.js:136` |
|
|
280
281
|
| `c3f99e7c6e6b` | certain | Could not copy automatically — select and copy manually. ({…}) | `modules/hall-ui/public/settings.js:997` |
|
|
@@ -298,7 +299,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
298
299
|
| `8b69e445592a` | certain | Could not load the question labels; showing the answers as stored. | `modules/hall-ui/public/idea.js:244` |
|
|
299
300
|
| `edd5bafbe075` | certain | Could not load the queue just now. | `modules/hall-ui/public/ideas.js:550` |
|
|
300
301
|
| `02bb0570996a` | certain | Could not load the ranks. | `modules/hall-ui/public/ranks.js:197` |
|
|
301
|
-
| `2878778cf9f3` | certain | Could not load this page. | `modules/hall-ui/public/watch.js:
|
|
302
|
+
| `2878778cf9f3` | certain | Could not load this page. | `modules/hall-ui/public/watch.js:1287` |
|
|
302
303
|
| `4b0c8d94541c` | certain | Could not load your account. Reload the page to try again. | `modules/hall-ui/public/settings.js:1376` |
|
|
303
304
|
| `2a9fb4046bc4` | certain | Could not load your rank. Return to the hall and try again. | `modules/hall-ui/public/ranks.js:196` |
|
|
304
305
|
| `9d533e811dec` | certain | Could not load your sessions: {…} | `modules/hall-ui/public/settings-sessions.js:114` |
|
|
@@ -306,7 +307,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
306
307
|
| `de244c45d916` | certain | Could not load {…} | `modules/hall-ui/public/task.js:703` |
|
|
307
308
|
| `2366356926b4` | certain | Could not mark the primer just now. Try again. | `modules/hall-ui/public/primer.js:260` |
|
|
308
309
|
| `753987b5da13` | certain | Could not reach the submit endpoint. | `modules/hall-ui/public/modules.js:297` |
|
|
309
|
-
| `6f500726f0ac` | certain | Could not read the report: {…} | `modules/hall-ui/public/watch.js:
|
|
310
|
+
| `6f500726f0ac` | certain | Could not read the report: {…} | `modules/hall-ui/public/watch.js:616` |
|
|
310
311
|
| `8b470cebf53d` | certain | Could not remove your key. Try again. | `modules/hall-ui/public/settings.js:1198` |
|
|
311
312
|
| `4cf6bc8b377b` | certain | Could not remove. Try again. | `modules/hall-ui/public/settings.js:1197` |
|
|
312
313
|
| `7a778d188e87` | certain | Could not remove: {…} | `modules/hall-ui/public/government.js:376` |
|
|
@@ -336,7 +337,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
336
337
|
| `d4601887a058` | certain | Could not sign out everywhere: {…} | `modules/hall-ui/public/settings-sessions.js:102` |
|
|
337
338
|
| `b1602d01f4bb` | certain | Could not unblock: {…} | `modules/hall-ui/public/harbor.js:187` |
|
|
338
339
|
| `3db890b074a7` | certain | Could not update visibility just now. | `modules/hall-ui/public/goals-render.js:1043` |
|
|
339
|
-
| `112d12b24879` | certain | Could not verify your access. Go back and try again. | `modules/hall-ui/public/watch.js:
|
|
340
|
+
| `112d12b24879` | certain | Could not verify your access. Go back and try again. | `modules/hall-ui/public/watch.js:1286` |
|
|
340
341
|
| `6bd74fd20311` | certain | Could not verify your access. Try again. | `modules/hall-ui/public/sessions.js:280` |
|
|
341
342
|
| `278e8281c82f` | certain | Could not vote: {…} | `modules/hall-ui/public/government.js:990` |
|
|
342
343
|
| `a48e9f098392` | certain | Could not {…} just now. | `modules/hall-ui/public/goals-render.js:1029` |
|
|
@@ -670,7 +671,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
670
671
|
| `d9c802f5d85e` | certain | Opening the studio… | `modules/hall-ui/public/studio.html:45` |
|
|
671
672
|
| `569980a263ae` | certain | Optional. This is the ledger link — a copy change ships as a task like every other change. | `modules/hall-ui/public/copy-desk.html:130` |
|
|
672
673
|
| `c78d7388ffd7` | certain | Or just stay in the online terminal | `modules/hall-ui/public/hall-render.js:750` |
|
|
673
|
-
| `d89d1923ecf9` | certain | Over the last {…} days | `modules/hall-ui/public/watch.js:
|
|
674
|
+
| `d89d1923ecf9` | certain | Over the last {…} days | `modules/hall-ui/public/watch.js:1129` |
|
|
674
675
|
| `695ffff13730` | certain | Over time | `modules/hall-ui/public/profile.html:72` |
|
|
675
676
|
| `5ded44da0cc5` | certain | Override requests | `modules/hall-ui/public/watch.html:143` |
|
|
676
677
|
| `15a49bf15007` | certain | Page {…} of {…} | `modules/hall-ui/public/hall-kit.js:112` |
|
|
@@ -696,6 +697,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
696
697
|
| `0ecbc4ee23f0` | certain | Primer required | `modules/hall-ui/public/work.html:42` |
|
|
697
698
|
| `04f8740a0cb4` | certain | Primer — {{worldName}} | `modules/hall-ui/public/primer.html:6` |
|
|
698
699
|
| `04f8740a0cb4` | certain | Primer — {{worldName}} | `modules/hall-ui/public/primer.html:6` |
|
|
700
|
+
| `92d8fad6dc91` | certain | Private account — this is all they share by applying. | `modules/hall-ui/public/watch.js:412` |
|
|
699
701
|
| `2b88c01d1697` | certain | Private — join is by invitation or an approved request | `modules/hall-ui/public/goals-render.js:797` |
|
|
700
702
|
| `230e7677aad4` | certain | Profile privacy | `modules/hall-ui/public/settings.html:110` |
|
|
701
703
|
| `f796836eac4e` | certain | Profile sections | `modules/hall-ui/public/profile.html:44` |
|
|
@@ -715,7 +717,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
715
717
|
| `3f85bdc47099` | certain | Protected module scope — join by request; an Archon admits members | `modules/hall-ui/public/goals-render.js:803` |
|
|
716
718
|
| `e5c292c8b361` | certain | Provides (seams) | `modules/hall-ui/public/atlas.js:288` |
|
|
717
719
|
| `4de232a05888` | certain | Raise after | `modules/hall-ui/public/project-settings.js:113` |
|
|
718
|
-
| `b9c6def6b120` | certain | Rank set to {…}. | `modules/hall-ui/public/watch.js:
|
|
720
|
+
| `b9c6def6b120` | certain | Rank set to {…}. | `modules/hall-ui/public/watch.js:789` |
|
|
719
721
|
| `ff50a1395cbc` | certain | Rank: {…} | `modules/hall-ui/public/profile.js:50` |
|
|
720
722
|
| `6824ec470f99` | certain | Ranks — {{worldName}} | `modules/hall-ui/public/ranks.html:6` |
|
|
721
723
|
| `6824ec470f99` | certain | Ranks — {{worldName}} | `modules/hall-ui/public/ranks.html:6` |
|
|
@@ -723,7 +725,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
723
725
|
| `101a51902f53` | certain | Re-issue failed: {…} | `modules/hall-ui/public/settings.js:1001` |
|
|
724
726
|
| `fae2f90927bd` | certain | Read an idea, then decide. An objection needs a reason and the section it faults. | `modules/hall-ui/public/government.html:66` |
|
|
725
727
|
| `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/drachmae.js:148` |
|
|
726
|
-
| `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/watch.js:
|
|
728
|
+
| `b03e17693dcd` | certain | Read it as a table | `modules/hall-ui/public/watch.js:1102` |
|
|
727
729
|
| `b6fcfdd652a7` | certain | Read it here | `modules/hall-ui/public/work.html:45` |
|
|
728
730
|
| `c5f19a888a15` | certain | Read the handoff notes | `modules/hall-ui/public/task.js:441` |
|
|
729
731
|
| `f9e998f4af3d` | certain | Read to the end and the button below unlocks. It is an honour system — nothing here checks your comprehension. | `modules/hall-ui/public/primer.html:100` |
|
|
@@ -758,7 +760,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
758
760
|
| `7d4149cee474` | certain | Repo Atlas — a self-drawing map of the codebase | `modules/hall-ui/public/atlas.html:6` |
|
|
759
761
|
| `4d40a68605e1` | certain | Repo atlas | `modules/hall-ui/public/atlas.html:30` |
|
|
760
762
|
| `52d7d4309540` | certain | Repo health | `modules/hall-ui/public/watch.html:111` |
|
|
761
|
-
| `e6629398d47c` | certain | Report {…}. | `modules/hall-ui/public/watch.js:
|
|
763
|
+
| `e6629398d47c` | certain | Report {…}. | `modules/hall-ui/public/watch.js:550` |
|
|
762
764
|
| `ab456f09c0f6` | certain | Request access | `modules/hall-ui/public/hall-render.js:284` |
|
|
763
765
|
| `ab456f09c0f6` | certain | Request access | `modules/hall-ui/public/hall-render.js:414` |
|
|
764
766
|
| `967f6d1ac068` | certain | Request dev box | `modules/hall-ui/public/box-panel.js:357` |
|
|
@@ -775,7 +777,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
775
777
|
| `0887725744f2` | certain | Restricted. | `modules/hall-ui/public/gate.js:219` |
|
|
776
778
|
| `0887725744f2` | certain | Restricted. | `modules/hall-ui/public/government.js:1104` |
|
|
777
779
|
| `0887725744f2` | certain | Restricted. | `modules/hall-ui/public/harbor.js:337` |
|
|
778
|
-
| `0887725744f2` | certain | Restricted. | `modules/hall-ui/public/watch.js:
|
|
780
|
+
| `0887725744f2` | certain | Restricted. | `modules/hall-ui/public/watch.js:1241` |
|
|
779
781
|
| `feb48b0d462c` | certain | Return to the Dev Box app and click “Connect” again for a fresh code. | `modules/hall-ui/public/pair.js:32` |
|
|
780
782
|
| `908a0d5d0685` | certain | Review how it judged this work, and teach it what good looked like. | `modules/hall-ui/public/studio.js:87` |
|
|
781
783
|
| `f1b2b158c3b1` | certain | Review quality | `modules/hall-ui/public/watch.html:82` |
|
|
@@ -861,7 +863,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
861
863
|
| `f79e1fb8ebd4` | certain | Suggested as you type; leave it on "no goal" and it waits for triage. | `modules/hall-ui/public/ideas.html:91` |
|
|
862
864
|
| `1e40f33483eb` | certain | Switch theme | `modules/hall-ui/public/shell.js:386` |
|
|
863
865
|
| `93fa2e97dd35` | certain | System default for this skill | `modules/hall-ui/public/settings.js:74` |
|
|
864
|
-
| `4894b1d9b0de` | certain | System oversight: people, operations and security. | `modules/hall-ui/public/watch.js:
|
|
866
|
+
| `4894b1d9b0de` | certain | System oversight: people, operations and security. | `modules/hall-ui/public/watch.js:1300` |
|
|
865
867
|
| `dfc967a63d57` | certain | Task lifecycle from backlog to shipped, showing states and transitions and the edge where credits are awarded. | `modules/hall-ui/public/diagrams.html:51` |
|
|
866
868
|
| `10cc12f37636` | certain | Task sections | `modules/hall-ui/public/work.html:53` |
|
|
867
869
|
| `0e636ea41b29` | certain | Task status | `modules/hall-ui/public/goals-render.js:331` |
|
|
@@ -939,6 +941,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
939
941
|
| `df316c3484de` | certain | Then drive it however you like: | `modules/hall-ui/public/hall-render.js:750` |
|
|
940
942
|
| `5151cf635644` | certain | They have asked to connect. | `modules/hall-ui/public/profile-connections.js:203` |
|
|
941
943
|
| `6e46811189db` | certain | This PR is held by the gate-review check. | `modules/hall-ui/public/gate.js:129` |
|
|
944
|
+
| `b7c288328f79` | certain | This builder hides their cross-project record. | `modules/hall-ui/public/watch.js:393` |
|
|
942
945
|
| `ed313d96b419` | certain | This builder keeps their track record private. | `modules/hall-ui/public/profile.js:270` |
|
|
943
946
|
| `3f9e476e22db` | certain | This clears {…}. The gate check re-runs and the PR merges once it goes green. Your approval applies only to co | `modules/hall-ui/public/gate.js:94` |
|
|
944
947
|
| `c2a0e726bd97` | certain | This goal is Archon-mediated — request to join instead. | `modules/hall-ui/public/goals-render.js:1025` |
|
|
@@ -1199,7 +1202,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1199
1202
|
| `4d8ee7d68974` | certain | task {…} | `modules/hall-ui/public/hall-render.js:605` |
|
|
1200
1203
|
| `4d8ee7d68974` | certain | task {…} | `modules/hall-ui/public/idea.js:207` |
|
|
1201
1204
|
| `4d8ee7d68974` | certain | task {…} | `modules/hall-ui/public/ideas.js:476` |
|
|
1202
|
-
| `4d8ee7d68974` | certain | task {…} | `modules/hall-ui/public/watch.js:
|
|
1205
|
+
| `4d8ee7d68974` | certain | task {…} | `modules/hall-ui/public/watch.js:1212` |
|
|
1203
1206
|
| `a41659dc2bee` | certain | tasks remaining | `modules/hall-ui/public/roadmap.js:285` |
|
|
1204
1207
|
| `bd3402efa59e` | certain | task{…} shipped | `modules/hall-ui/public/goals-render.js:748` |
|
|
1205
1208
|
| `95854f8315ca` | certain | the page everyone else reads | `modules/hall-ui/public/profile.html:32` |
|
|
@@ -1269,7 +1272,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1269
1272
|
| `b2db97589086` | certain | {…} will not be able to open or wake a dev box until you unblock them. A box they already have running is left | `modules/hall-ui/public/harbor.js:148` |
|
|
1270
1273
|
| `3ad8f32dd43b` | certain | {…} you have sent | `modules/hall-ui/public/profile-connections.js:137` |
|
|
1271
1274
|
| `8186b562553a` | certain | {…} {…} waiting | `modules/hall-ui/public/work.js:359` |
|
|
1272
|
-
| `0d4016a5531c` | certain | {…} {…}{…} | `modules/hall-ui/public/watch.js:
|
|
1275
|
+
| `0d4016a5531c` | certain | {…} {…}{…} | `modules/hall-ui/public/watch.js:450` |
|
|
1273
1276
|
| `0d4016a5531c` | certain | {…} {…}{…} | `modules/hall-ui/public/work.js:223` |
|
|
1274
1277
|
| `b3757ba3bb46` | certain | {…} · Stored encrypted; never shown again after saving. | `modules/hall-ui/public/settings.js:1055` |
|
|
1275
1278
|
| `94445e6ed5e8` | certain | {…} · code | `modules/hall-ui/public/pair.js:53` |
|
|
@@ -1422,7 +1425,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1422
1425
|
| `7667eb552781` | certain | {…}: {…}% ({…}/{…} checks) | `modules/status-ui/public/status.js:468` |
|
|
1423
1426
|
| `6d0d64f10bd9` | certain | ‹ earlier page | `modules/status-ui/public/index.html:321` |
|
|
1424
1427
|
|
|
1425
|
-
## `landing` —
|
|
1428
|
+
## `landing` — 372 strings
|
|
1426
1429
|
|
|
1427
1430
|
| id | conf | text | where |
|
|
1428
1431
|
|---|---|---|---|
|
|
@@ -1788,7 +1791,6 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1788
1791
|
| `5becfcad07c3` | certain | — people ask from the project’s hall, you approve each one from the hall’s Watch page, and then they sign in. | `modules/public-landing/public/projects.html:809` |
|
|
1789
1792
|
| `9ac56aa4e540` | certain | — projects hosted by the platform run on servers rented from DigitalOcean, with their web address and traffic | `modules/public-landing/public/privacy.html:65` |
|
|
1790
1793
|
| `39719e6e1d56` | certain | — shipped as | `modules/public-landing/public/projects.html:778` |
|
|
1791
|
-
| `78a1684630fa` | certain | — the map shows only that something is there; its name, and everything else about it, stay yours, and nobody c | `modules/public-landing/public/projects.html:828` |
|
|
1792
1794
|
| `b5bac008ba11` | certain | — the project is on the map under its name, and anyone who finds it can join. | `modules/public-landing/public/projects.html:828` |
|
|
1793
1795
|
| `728661ec4c4a` | certain | — when a shipped task is graded, the change it made (the code diff) is sent to the model the grader runs on, A | `modules/public-landing/public/privacy.html:64` |
|
|
1794
1796
|
| `ff1318762145` | certain | — whoever signs in with GitHub becomes a member at once, at the newcomer rank. | `modules/public-landing/public/projects.html:809` |
|