@bongos/core 1.19.427 → 1.19.428
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 +47 -27
- package/docs/adr/0213-platform-terms-acceptance-is-the-hubs-own-witness.md +71 -0
- package/docs/adr/README.md +1 -0
- package/docs/copy-inventory.md +22 -14
- package/docs/copy-registry.json +93 -21
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +2 -0
- package/modules/platform-identity/account-visibility.js +31 -12
- package/modules/platform-identity/connections.js +4 -3
- package/modules/platform-identity/migrations/platform_identity_019_terms_acceptance.sql +47 -0
- package/modules/platform-identity/platform-identity.js +12 -10
- package/modules/platform-identity/routes/connections.js +4 -3
- package/modules/platform-identity/terms-acceptance.js +97 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/terms.html +8 -0
- package/src/module-api.js +1 -1
- package/tests/connections_api.mjs +13 -8
- package/tests/connections_ownership.mjs +6 -1
- package/tests/effective_visibility_predicate.mjs +89 -14
- package/tests/profile_connections_ui.mjs +22 -7
- package/tests/profile_privacy_owner_view.mjs +31 -4
- package/tests/profile_route.mjs +15 -8
- package/tests/terms_acceptance.mjs +573 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.428",
|
|
6
|
+
"core_contract": "1.19.428",
|
|
7
|
+
"source_commit": "d7a0e4bd7e1d4b7424f411f5dfb321a77e8beaef",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-29T20:46:11.874Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 363,
|
|
13
13
|
"agent_docs_stubbed": 23,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1734,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2120,
|
|
20
|
+
"tree_sha256": "6cb0ad50d9d19f0418f4c77c403ec092b9b7a12735233523351dfb284c0e0703",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -1559,10 +1559,15 @@
|
|
|
1559
1559
|
"mode": "0000644",
|
|
1560
1560
|
"sha256": "1251b6ba7b5fc79765aed5fcf9696d6f55d52acf6d6766200215a480f2d574a3"
|
|
1561
1561
|
},
|
|
1562
|
+
{
|
|
1563
|
+
"path": "docs/adr/0213-platform-terms-acceptance-is-the-hubs-own-witness.md",
|
|
1564
|
+
"mode": "0000644",
|
|
1565
|
+
"sha256": "c3aba5879f639ea409d80bc8545085fc1892fe191868ac69c9be52507750f33a"
|
|
1566
|
+
},
|
|
1562
1567
|
{
|
|
1563
1568
|
"path": "docs/adr/README.md",
|
|
1564
1569
|
"mode": "0000644",
|
|
1565
|
-
"sha256": "
|
|
1570
|
+
"sha256": "7a79523a204bf0520f3fe3358b21b017fea0bb8daa3e37e8596841fcb1eac722"
|
|
1566
1571
|
},
|
|
1567
1572
|
{
|
|
1568
1573
|
"path": "docs/api-reference.md",
|
|
@@ -1597,12 +1602,12 @@
|
|
|
1597
1602
|
{
|
|
1598
1603
|
"path": "docs/copy-inventory.md",
|
|
1599
1604
|
"mode": "0000644",
|
|
1600
|
-
"sha256": "
|
|
1605
|
+
"sha256": "3f2d18b85eb807cb1531e40b77cbf9faad6a6027c65e5eb800f40d0f4eb43e89"
|
|
1601
1606
|
},
|
|
1602
1607
|
{
|
|
1603
1608
|
"path": "docs/copy-registry.json",
|
|
1604
1609
|
"mode": "0000644",
|
|
1605
|
-
"sha256": "
|
|
1610
|
+
"sha256": "a8f22a35222054e8356c50856ba48ff49d48c50a30a3d4a3ebf73bf6342e2d23"
|
|
1606
1611
|
},
|
|
1607
1612
|
{
|
|
1608
1613
|
"path": "docs/design/apex-pass-2-direction.md",
|
|
@@ -1947,7 +1952,7 @@
|
|
|
1947
1952
|
{
|
|
1948
1953
|
"path": "docs/file-map.md",
|
|
1949
1954
|
"mode": "0000644",
|
|
1950
|
-
"sha256": "
|
|
1955
|
+
"sha256": "7c198c8f0f007919302cdd177e2e820d4c3ff5bd401af3007755c08ef74afcb3"
|
|
1951
1956
|
},
|
|
1952
1957
|
{
|
|
1953
1958
|
"path": "docs/handoff-template.md",
|
|
@@ -1957,7 +1962,7 @@
|
|
|
1957
1962
|
{
|
|
1958
1963
|
"path": "docs/module-api-changelog.md",
|
|
1959
1964
|
"mode": "0000644",
|
|
1960
|
-
"sha256": "
|
|
1965
|
+
"sha256": "52a19ff7373945df5df1c24205a62a35708de4ec2caf546a91977c665f05b0f1"
|
|
1961
1966
|
},
|
|
1962
1967
|
{
|
|
1963
1968
|
"path": "docs/modules-contract.md",
|
|
@@ -4812,7 +4817,7 @@
|
|
|
4812
4817
|
{
|
|
4813
4818
|
"path": "modules/platform-identity/account-visibility.js",
|
|
4814
4819
|
"mode": "0000644",
|
|
4815
|
-
"sha256": "
|
|
4820
|
+
"sha256": "788d0a51e29e0bd7971a63b8ed168ce71beb2a30a170bd0dbfc457d96b275233"
|
|
4816
4821
|
},
|
|
4817
4822
|
{
|
|
4818
4823
|
"path": "modules/platform-identity/application-echo.js",
|
|
@@ -4822,7 +4827,7 @@
|
|
|
4822
4827
|
{
|
|
4823
4828
|
"path": "modules/platform-identity/connections.js",
|
|
4824
4829
|
"mode": "0000644",
|
|
4825
|
-
"sha256": "
|
|
4830
|
+
"sha256": "ed671aad4b6af46e56e29d5427ac2d5bdfc3ed414dbb981a27fce5097946e7ae"
|
|
4826
4831
|
},
|
|
4827
4832
|
{
|
|
4828
4833
|
"path": "modules/platform-identity/hub-device.js",
|
|
@@ -4924,6 +4929,11 @@
|
|
|
4924
4929
|
"mode": "0000644",
|
|
4925
4930
|
"sha256": "d5553c3d06e8d71b89e62db54a9a3a3ae9810d3f29b262c97dca1f8242aca879"
|
|
4926
4931
|
},
|
|
4932
|
+
{
|
|
4933
|
+
"path": "modules/platform-identity/migrations/platform_identity_019_terms_acceptance.sql",
|
|
4934
|
+
"mode": "0000644",
|
|
4935
|
+
"sha256": "112fd5dcc9d2bfbc8ec064963e1a783d8ef7855a1a47cf6575ea70da06803d68"
|
|
4936
|
+
},
|
|
4927
4937
|
{
|
|
4928
4938
|
"path": "modules/platform-identity/module.json",
|
|
4929
4939
|
"mode": "0000644",
|
|
@@ -4932,7 +4942,7 @@
|
|
|
4932
4942
|
{
|
|
4933
4943
|
"path": "modules/platform-identity/platform-identity.js",
|
|
4934
4944
|
"mode": "0000644",
|
|
4935
|
-
"sha256": "
|
|
4945
|
+
"sha256": "09a9be4a79097faf612ee52b1eea1c5b845bba873032853aab36c55411395833"
|
|
4936
4946
|
},
|
|
4937
4947
|
{
|
|
4938
4948
|
"path": "modules/platform-identity/pollers/code-sweep.js",
|
|
@@ -4947,7 +4957,7 @@
|
|
|
4947
4957
|
{
|
|
4948
4958
|
"path": "modules/platform-identity/routes/connections.js",
|
|
4949
4959
|
"mode": "0000644",
|
|
4950
|
-
"sha256": "
|
|
4960
|
+
"sha256": "d8f7404fc30052a4f815e735dff7981da56d00ccb902ace5fac132a35f59e6de"
|
|
4951
4961
|
},
|
|
4952
4962
|
{
|
|
4953
4963
|
"path": "modules/platform-identity/routes/my-projects.js",
|
|
@@ -4984,6 +4994,11 @@
|
|
|
4984
4994
|
"mode": "0000644",
|
|
4985
4995
|
"sha256": "b4da61899339ac5e9fac517efa4b3d98e39a8e7d38fd8b0cffbd8464ba85e902"
|
|
4986
4996
|
},
|
|
4997
|
+
{
|
|
4998
|
+
"path": "modules/platform-identity/terms-acceptance.js",
|
|
4999
|
+
"mode": "0000644",
|
|
5000
|
+
"sha256": "85aa2a81a80d09031282926bc5f63cef25e85630233fcbd7899ba783b2a62d59"
|
|
5001
|
+
},
|
|
4987
5002
|
{
|
|
4988
5003
|
"path": "modules/platform-identity/tests/platform-identity.mjs",
|
|
4989
5004
|
"mode": "0000644",
|
|
@@ -5542,12 +5557,12 @@
|
|
|
5542
5557
|
{
|
|
5543
5558
|
"path": "package-lock.json",
|
|
5544
5559
|
"mode": "0000644",
|
|
5545
|
-
"sha256": "
|
|
5560
|
+
"sha256": "b1c61170574781d889c2cb10f424790e26d06c24e908b81c593dec2d08f66d18"
|
|
5546
5561
|
},
|
|
5547
5562
|
{
|
|
5548
5563
|
"path": "package.json",
|
|
5549
5564
|
"mode": "0000644",
|
|
5550
|
-
"sha256": "
|
|
5565
|
+
"sha256": "7a042b2a93b97326961852672b0c7cb5083726465cafde6b3fb0d2e8fb3d5ae4"
|
|
5551
5566
|
},
|
|
5552
5567
|
{
|
|
5553
5568
|
"path": "public-docs/index.html",
|
|
@@ -6022,7 +6037,7 @@
|
|
|
6022
6037
|
{
|
|
6023
6038
|
"path": "public-landing/terms.html",
|
|
6024
6039
|
"mode": "0000644",
|
|
6025
|
-
"sha256": "
|
|
6040
|
+
"sha256": "c0e7026074a7485ac7f3e308a8c1fb6b4cac858d8e959dda03e65a3365763b2f"
|
|
6026
6041
|
},
|
|
6027
6042
|
{
|
|
6028
6043
|
"path": "public-landing/world/assets/clouds/cloud-island-large.png",
|
|
@@ -7677,7 +7692,7 @@
|
|
|
7677
7692
|
{
|
|
7678
7693
|
"path": "src/module-api.js",
|
|
7679
7694
|
"mode": "0000644",
|
|
7680
|
-
"sha256": "
|
|
7695
|
+
"sha256": "0842a7b4bc18d90a71ed73aef09a6b30aa9b7ad747d03a6e9cef59d84a994ffd"
|
|
7681
7696
|
},
|
|
7682
7697
|
{
|
|
7683
7698
|
"path": "src/module-loader/catalog.js",
|
|
@@ -8257,12 +8272,12 @@
|
|
|
8257
8272
|
{
|
|
8258
8273
|
"path": "tests/connections_api.mjs",
|
|
8259
8274
|
"mode": "0000644",
|
|
8260
|
-
"sha256": "
|
|
8275
|
+
"sha256": "61af2ef3905b31a796e80168f1e267b608792d7195cf2e48d6a1ca85eb76ef5e"
|
|
8261
8276
|
},
|
|
8262
8277
|
{
|
|
8263
8278
|
"path": "tests/connections_ownership.mjs",
|
|
8264
8279
|
"mode": "0000644",
|
|
8265
|
-
"sha256": "
|
|
8280
|
+
"sha256": "58fa2cbe6866697402fc22037a4b615c642311f40c85e4b19555de55e7591eb1"
|
|
8266
8281
|
},
|
|
8267
8282
|
{
|
|
8268
8283
|
"path": "tests/consumer_layout_boot.mjs",
|
|
@@ -8542,7 +8557,7 @@
|
|
|
8542
8557
|
{
|
|
8543
8558
|
"path": "tests/effective_visibility_predicate.mjs",
|
|
8544
8559
|
"mode": "0000644",
|
|
8545
|
-
"sha256": "
|
|
8560
|
+
"sha256": "1aeeaea5d344543ab48b8dde994f4375bea9ef7678ce50e09402376334731f76"
|
|
8546
8561
|
},
|
|
8547
8562
|
{
|
|
8548
8563
|
"path": "tests/est_advisory.mjs",
|
|
@@ -9702,7 +9717,7 @@
|
|
|
9702
9717
|
{
|
|
9703
9718
|
"path": "tests/profile_connections_ui.mjs",
|
|
9704
9719
|
"mode": "0000644",
|
|
9705
|
-
"sha256": "
|
|
9720
|
+
"sha256": "baa7abe3a99aca3c412cc856cfd86da8b0d749ef5e7b875939277f4e887ad747"
|
|
9706
9721
|
},
|
|
9707
9722
|
{
|
|
9708
9723
|
"path": "tests/profile_fields.mjs",
|
|
@@ -9717,7 +9732,7 @@
|
|
|
9717
9732
|
{
|
|
9718
9733
|
"path": "tests/profile_privacy_owner_view.mjs",
|
|
9719
9734
|
"mode": "0000644",
|
|
9720
|
-
"sha256": "
|
|
9735
|
+
"sha256": "75cc928587baac3151104c3ff4a1cfd39436fc7255f3afac818079724d6dbab1"
|
|
9721
9736
|
},
|
|
9722
9737
|
{
|
|
9723
9738
|
"path": "tests/profile_rollup_consent.mjs",
|
|
@@ -9727,7 +9742,7 @@
|
|
|
9727
9742
|
{
|
|
9728
9743
|
"path": "tests/profile_route.mjs",
|
|
9729
9744
|
"mode": "0000644",
|
|
9730
|
-
"sha256": "
|
|
9745
|
+
"sha256": "6258fd5980e501e79d0e73415533c71aad89827665d949689df323683676a15b"
|
|
9731
9746
|
},
|
|
9732
9747
|
{
|
|
9733
9748
|
"path": "tests/profile_ui_cross_project.mjs",
|
|
@@ -10444,6 +10459,11 @@
|
|
|
10444
10459
|
"mode": "0000644",
|
|
10445
10460
|
"sha256": "3ff18b286a68b244a272b3f2606ae33b298622347aae97305152f235ca57b330"
|
|
10446
10461
|
},
|
|
10462
|
+
{
|
|
10463
|
+
"path": "tests/terms_acceptance.mjs",
|
|
10464
|
+
"mode": "0000644",
|
|
10465
|
+
"sha256": "513359af9b786feae7503c1c4b62e1b064f9a582d36c52932301b95e25f012fb"
|
|
10466
|
+
},
|
|
10447
10467
|
{
|
|
10448
10468
|
"path": "tests/test_path_guard.mjs",
|
|
10449
10469
|
"mode": "0000644",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ADR 0213 — The platform T&C acceptance is the hub's own witness, written once, and consent becomes two columns
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-08-29
|
|
5
|
+
- **Task:** [task 1002913](https://cloudbongos.com/builders#/task/1002913) (goal 1000045 — Public builder profiles)
|
|
6
|
+
- **Relates to:** [ADR 0141](<redacted>.md) §4 (which deferred cross-project-aggregation consent to "the platform T&C" and conditioned the scouting view on it), [ADR 0171](<redacted>.md) D3 (fail-closed `profile_state`, and the sentence that reserved this task's place), [ADR 0016](<redacted>.md) (cross-project numbers are descriptive, never authority), [ADR 0205](<redacted>.md) D3 (the hub's own sign-in witness; `ensureAccount` vs `upsertAccount`), [ADR 0210](<redacted>.md) (the directory this consent covers), [ADR 0202](<redacted>.md) D4 (the shared effective-visibility reader), `docs/specs/<redacted>.md` (the "already carries platform T&C consent" premise), `docs/specs/<redacted>.md`
|
|
7
|
+
|
|
8
|
+
> **0211 and 0212** are held by sessions in flight; this ADR takes 0213 rather than race them (the ADR 0199 / 0202 / 0207 / 0210 precedent).
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
|
|
12
|
+
ADR 0141 §4 shipped the cross-project scouting rollup with a promise attached: consent for aggregating a builder's work across every hosted project *"is handled by the platform T&C, tracked separately, out of scope here"*, and the view *"must stay Archon-internal until [it] lands"*. ADR 0171 then superseded the gating half — goal 1000045's owner decision made the data public by default with a self-serve hide — and D3 built the consent boundary the decision needed, describing `profile_state='active'` as the state an account reaches when *"a human is demonstrably at the hub (**and where T&C acceptance can later be captured, task 1002913**)"*.
|
|
13
|
+
|
|
14
|
+
Both ADRs, in other words, wrote their consent story around an artifact that did not exist. The public-profiles spec states the premise plainly — profiles are public by default because that is *"tied to having a platform account, which already carries platform T&C consent"* — and the profile-page spec had already flagged, in as many words, that **that premise is not currently true**.
|
|
15
|
+
|
|
16
|
+
Three things were found on picking the task up, and they changed its shape:
|
|
17
|
+
|
|
18
|
+
1. **A `/terms` page already exists.** Task 1003251 landed `public-landing/terms.html`, routed and server-stamped. The task brief (written before it) says no T&C document exists anywhere in the tree; that is now stale. What does not exist is the *content* ADR 0141 deferred to it: the page covers accounts, code ownership, fair use and liability, and says nothing whatsoever about work crossing between projects. `/privacy` is silent on it too.
|
|
19
|
+
2. **The `scouting.js:6` reference the task points at is gone.** Task 1002290 rewrote that header for ADR 0210; it now describes consent as enforced by `scoutingListableSql`. So the last in-tree pointer to the missing artifact had already been overwritten — the debt was becoming invisible rather than getting paid.
|
|
20
|
+
3. **The un-gating this artifact was supposed to unlock has already happened**, via ADR 0171 and ADR 0210. Nothing waits on this ADR to widen. What waits on it is the *honesty* of a premise every public surface already rests on.
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
### D1 — The acceptance record is the hub's own evidence, never a caller's claim
|
|
25
|
+
|
|
26
|
+
`platform_identity_accounts` gains `terms_accepted_at timestamptz` and `terms_version text` (migration `<redacted>.sql`). Both are written by exactly one statement: `upsertAccount`'s `activate` branch. That branch has exactly one caller — `GET /sso/authorize` — where `activate: true` is a **source literal** and every other field comes from the hub's own `resolveSession` result, gated by `sessionUsableForFederation`.
|
|
27
|
+
|
|
28
|
+
This is deliberately the ADR 0205 D3 property, reused. An acceptance record a caller could assert is evidence of nothing; the only thing that makes the record mean "this human accepted" is that no request-controlled value can reach the statement that writes it. `ensureAccount` — the federated check-in / device-poll path, which takes an *unproven* `github_id` from a request body — writes NULL, exactly as it writes `provisional`.
|
|
29
|
+
|
|
30
|
+
### D2 — Written once. The first acceptance is the one that stands
|
|
31
|
+
|
|
32
|
+
The conflict branch writes `COALESCE(platform_identity_accounts.terms_accepted_at, now())`. Signing in again re-reads the terms but does not restamp them, so the column keeps meaning *when consent was given* rather than *when this account was last seen*. `terms_version` is COALESCE'd the same way and always written in the same statement, so the pair cannot diverge.
|
|
33
|
+
|
|
34
|
+
### D3 — Consent is two columns, and the shared predicate is where that is enforced
|
|
35
|
+
|
|
36
|
+
`account-visibility.js` — the sole owner of every effective-visibility answer (ADR 0202 D4) — now spells the consent axis as `profile_state = 'active' AND terms_accepted_at IS NOT NULL`, in both its SQL and JS forms. `accountVisibleSql`/`isAccountVisible` compose from it rather than restating it, so the rollup, directory and connections predicates inherit the change without any of them naming the new column.
|
|
37
|
+
|
|
38
|
+
Writing it here rather than at the call sites is the whole point: both halves are stamped by the same statement, so for any account activated after this ADR they can never disagree — and requiring both in the predicate is what makes that structural instead of a promise. It is also what stops a row that predates the terms from publishing on a premise that was never true.
|
|
39
|
+
|
|
40
|
+
`tests/effective_visibility_predicate.mjs` extends its sole-owner rule to the new column, in the `${q}`-prefixed form the owner actually emits — the form the reach-COALESCE hole (task 1002290) taught us to pin rather than the bare spelling nobody writes.
|
|
41
|
+
|
|
42
|
+
### D4 — No backfill. Existing accounts re-accept on their next hub sign-in
|
|
43
|
+
|
|
44
|
+
Accounts that are already `active` get `terms_accepted_at IS NULL`, because no platform T&C covering cross-project aggregation has ever been shown to anyone and inventing a timestamp would fabricate the very artifact this task exists to make real. Under D3 they are therefore not publicly visible until their next hub-session authorize, which stamps them.
|
|
45
|
+
|
|
46
|
+
This is ADR 0171 D3's own backfill rule applied to its own sentence (*"all existing accounts start provisional and lazily upgrade on their next hub-session authorize"*), and it is what P03 ratified ([task 1002799](https://cloudbongos.com/builders#/task/1002799), owner, 2026-08-16): no backfill activation, on the rationale that a builder passes through the hub anyway. **This is the one consequence with a visible product effect, and it is on [blocker 1000123](https://cloudbongos.com/builders#/blocker/1000123) for the owner** — grandfathering is one line in the migration if they prefer it.
|
|
47
|
+
|
|
48
|
+
### D5 — Re-acceptance on a later revision is out of scope, and visible rather than silent
|
|
49
|
+
|
|
50
|
+
Because the version is recorded and never overwritten, publishing a new `TERMS_VERSION` leaves every row naming the text it actually agreed to, so the platform can see who has not accepted the new one. What to *do* about that — re-prompt, re-gate, or nothing — is a product flow, not a storage shape, and is not built here.
|
|
51
|
+
|
|
52
|
+
### D6 — The wording is the owner's, and only the wording was left pending
|
|
53
|
+
|
|
54
|
+
The mechanism ships complete. The text of the new section is a draft on [blocker 1000123](https://cloudbongos.com/builders#/blocker/1000123); `TERMS_VERSION` is date-stamped and asserted to match the page, so changing the wording is an edit to two strings.
|
|
55
|
+
|
|
56
|
+
## Consequences
|
|
57
|
+
|
|
58
|
+
- The premise the public-profile surfaces rest on becomes true for every account activated from here, and fail-closed for every account that predates it.
|
|
59
|
+
- **Every currently-`active` account is unpublished until its next hub sign-in** (D4). Reversible in one line; on the owner's blocker.
|
|
60
|
+
- `platform-identity.js` sat at 1497 lines against a hard `oversized_file_count: 0` ratchet, so the write-side SQL lives in a new `terms-acceptance.js` — the fifth instance of the "new file beside it" precedent (`account-visibility.js`, `application-echo.js`, `routes/connections.js`, `src/bongos/routes/my-sessions.js`). The file now measures exactly 1500 and **has no headroom left**; the next change to it must shrink it.
|
|
61
|
+
- The read/write split is load-bearing: `terms-acceptance.js` owns only statements that SET the columns, `account-visibility.js` owns the one that TESTS them. The guard's spelling rules deliberately do not match writes, which is what lets both files exist without one of them being a drift copy.
|
|
62
|
+
- **Settings will read wrong for a legacy account under D4** until someone closes it: `GET /me/cross-project` returns `profile_state` raw and the Settings consent note branches on it alone, so an account that signed in before the terms existed reads "active" while its profile is published nowhere. One own-scope boolean plus a copy change fixes it - filed as idea 1000875, and it disappears entirely if the owner grandfathers on blocker 1000123.
|
|
63
|
+
- `docs/specs/<redacted>.md`'s standing note that the consent premise "is not currently true for every account" is now addressed rather than outstanding.
|
|
64
|
+
|
|
65
|
+
## Rejected alternatives
|
|
66
|
+
|
|
67
|
+
- **A separate `platform_identity_terms_acceptances` table (one row per acceptance).** Correct if acceptance were an event stream — re-acceptance across versions, audit history. It is not one yet (D5), and a table whose only reader is a per-account NULL test is a join the visibility predicate would have to grow. Two columns, one statement, no join.
|
|
68
|
+
- **A click-through gate on `/sso/authorize`.** An explicit "I accept" button is stronger evidence than "by signing in you agree". It also puts an interstitial in the middle of a federated redirect that exists to be invisible, and it changes a sign-in flow two other live tasks were editing. The page now states the terms and the sign-in records acceptance of them; upgrading to an explicit gate is additive and does not invalidate any record written under this ADR.
|
|
69
|
+
- **Backfilling `terms_accepted_at` for already-active accounts** (D4) — records a consent that never happened, which is exactly the fiction this task exists to end. Offered to the owner as the alternative it is, not taken silently.
|
|
70
|
+
- **Deriving `profile_state` from `terms_accepted_at`** (dropping the column). The two facts are genuinely different — the hub witnessed a human, and that human accepted a text — and D5's revision case needs them separable.
|
|
71
|
+
- **Putting the acceptance predicate in `terms-acceptance.js`.** It would have made that file a second owner of an effective-visibility answer, which ADR 0202 D4 forbids and the structural guard fails.
|
package/docs/adr/README.md
CHANGED
|
@@ -299,5 +299,6 @@ This keeps the decision history honest and traceable.
|
|
|
299
299
|
| 0207 | [**Building the connection graph: three departures from ADR 0202, and the three limits it is honest about** ([task 1002295](https://cloudbongos.com/builders#/task/1002295), goal 1000045 criterion C6 — the build of the connections wave). ADR 0202 decided the graph; building it surfaced three places where the decision's MECHANISM could not be written literally without losing the PROPERTY it was about, and three places where the shipped code cannot promise as much as a casual reading suggests. Departures: (1) **level-wise CTEs, not `WITH RECURSIVE`** — a recursive term can carry neither a per-level fan-out cap nor an ordered per-level truncation, which are the two things D3 actually decided, so a recursive build would have had a depth bound and no fan-out bound; a test asserts `RECURSIVE` appears in neither query. (2) **1st degree is an unbounded pair-index probe**, never a scan of the capped frontier — reading it off the `FANOUT_1`-truncated 1-hop reports "2nd" for someone in the viewer's own connections list once they pass 500 connections, and the rule this states is that **a cap may only ever make an answer less specific (`null`), never wrong**. (3) The shared visibility predicate lands in its own file, `modules/platform-identity/account-visibility.js` (`isAccountVisible` / `accountVisibleSql` / `accountActiveSql`), because task 1002967 had not shipped and `platform-identity.js` sat at the size ratchet with zero headroom — **1002967 adopts it rather than writing a second predicate**. Also decided: node visibility during traversal is viewer-relative and asymmetric on purpose (your OWN 1-hop floors on consent alone so a friend who goes private does not vanish from your list; every deeper hop clears the public predicate); cancel is a `DELETE` an ADDRESSEE may not use, so the 90-day cooldown cannot be dodged by calling a decline a delete; and the create response is `201 { status: 'pending' }` and nothing else, so a swallowed re-ask has nothing to fabricate. Limits stated rather than implied: a swallowed re-ask is silent in the RESPONSE and observable by its ABSENCE from the requester's outbox (the claim is narrowed, not the code — a decoy row would be a lie in the database to protect a lie in the API); the TARGET's 1-hop is capped too and that truncation is deliberately NOT reported, because saying so leaks one bit about a third party's degree; and the query COUNT is bounded while the frontier's WORK is O(sum of degree over the 1-hop), since `ORDER BY … LIMIT` materialises before it truncates — the revisit trigger is a measured p95, and the cheap next move is a `statement_timeout` returning the `null` D3 already chose. Deferred and named: a per-builder cap on OUTBOUND requests (the cooldown stops repeat asks to one person, not one builder asking a hundred — a real number is owner-signed), and a real-Postgres pass on the expire-then-insert write path, which CI cannot run.](<redacted>.md) | platform identity / social graph / privacy |
|
|
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
|
| 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 |
|
|
302
|
+
| 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 |
|
|
302
303
|
|
|
303
304
|
> ⚠️ **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.
|
package/docs/copy-inventory.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
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
|
+
**1588 strings** across 3 surfaces · 1382 distinct pieces of copy · 1588 certain, 0 heuristic · 157 shown in more than one place.
|
|
8
8
|
|
|
9
9
|
## Surfaces
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|---|---|---|---|
|
|
13
13
|
| `builders-hall` | `modules/hall-ui/public` | 73 | 1164 |
|
|
14
14
|
| `status-dashboard` | `modules/status-ui/public` | 4 | 98 |
|
|
15
|
-
| `landing` | `public-landing` | 5 |
|
|
15
|
+
| `landing` | `public-landing` | 5 | 326 |
|
|
16
16
|
|
|
17
17
|
## Confidence, and why it is on every row
|
|
18
18
|
|
|
@@ -1350,7 +1350,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1350
1350
|
| `7667eb552781` | certain | {…}: {…}% ({…}/{…} checks) | `modules/status-ui/public/status.js:468` |
|
|
1351
1351
|
| `6d0d64f10bd9` | certain | ‹ earlier page | `modules/status-ui/public/index.html:321` |
|
|
1352
1352
|
|
|
1353
|
-
## `landing` —
|
|
1353
|
+
## `landing` — 326 strings
|
|
1354
1354
|
|
|
1355
1355
|
| id | conf | text | where |
|
|
1356
1356
|
|---|---|---|---|
|
|
@@ -1367,7 +1367,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1367
1367
|
| `afe83bbbd0d4` | certain | A non-profit, capture-resistant commons. | `public-landing/index.html:900` |
|
|
1368
1368
|
| `afe83bbbd0d4` | certain | A non-profit, capture-resistant commons. | `public-landing/privacy.html:80` |
|
|
1369
1369
|
| `afe83bbbd0d4` | certain | A non-profit, capture-resistant commons. | `public-landing/projects.html:1115` |
|
|
1370
|
-
| `afe83bbbd0d4` | certain | A non-profit, capture-resistant commons. | `public-landing/terms.html:
|
|
1370
|
+
| `afe83bbbd0d4` | certain | A non-profit, capture-resistant commons. | `public-landing/terms.html:84` |
|
|
1371
1371
|
| `2363998aa2be` | certain | A pair of bongo drums | `public-landing/projects.html:1044` |
|
|
1372
1372
|
| `407982c3d4ff` | certain | A project as a codebase, regardless of function. | `public-landing/index.html:762` |
|
|
1373
1373
|
| `c3504a900b0f` | certain | A project stood up from the hub runs on the platform's servers at your request. Any cost is shown before you c | `public-landing/terms.html:61` |
|
|
@@ -1396,7 +1396,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1396
1396
|
| `bd315dd71ea7` | certain | Built by agents, on Cloud Bongos. | `public-landing/contact.html:71` |
|
|
1397
1397
|
| `bd315dd71ea7` | certain | Built by agents, on Cloud Bongos. | `public-landing/index.html:900` |
|
|
1398
1398
|
| `bd315dd71ea7` | certain | Built by agents, on Cloud Bongos. | `public-landing/privacy.html:80` |
|
|
1399
|
-
| `bd315dd71ea7` | certain | Built by agents, on Cloud Bongos. | `public-landing/terms.html:
|
|
1399
|
+
| `bd315dd71ea7` | certain | Built by agents, on Cloud Bongos. | `public-landing/terms.html:84` |
|
|
1400
1400
|
| `78fd8d18ba64` | certain | Built on Cloud Bongos | `public-landing/index.html:736` |
|
|
1401
1401
|
| `8639cc7fcada` | certain | Buttons here ask the platform to act; each row reports only what was verified, and when. A standup keeps going | `public-landing/projects.html:628` |
|
|
1402
1402
|
| `101339c676b4` | certain | Buy microtransaction packages of code modules on our marketplace. | `public-landing/index.html:866` |
|
|
@@ -1416,7 +1416,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1416
1416
|
| `b07e75a05f48` | certain | Creating the repo yourself on GitHub? Public or private is your choice there — both work here, and we never ch | `public-landing/projects.html:960` |
|
|
1417
1417
|
| `3aeefb044b9f` | certain | Creation steps | `public-landing/projects.html:781` |
|
|
1418
1418
|
| `47d1558b17a3` | certain | Domain you own | `public-landing/projects.html:993` |
|
|
1419
|
-
| `8d812912c392` | certain | Don't use {{productName}} to break the law, to attack this site or other people's projects, to mine, spam or o | `public-landing/terms.html:
|
|
1419
|
+
| `8d812912c392` | certain | Don't use {{productName}} to break the law, to attack this site or other people's projects, to mine, spam or o | `public-landing/terms.html:73` |
|
|
1420
1420
|
| `d919980d2ca5` | certain | Download our core code and protocols, and build instantly with your team. | `public-landing/index.html:862` |
|
|
1421
1421
|
| `18b6b56edc93` | certain | Each sign-in creates a session: a random token, whether it came from the browser or the command line, the brow | `public-landing/privacy.html:54` |
|
|
1422
1422
|
| `9a4a940d2a56` | certain | Emersonian Circles | `public-landing/index.html:751` |
|
|
@@ -1425,7 +1425,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1425
1425
|
| `b1cf8460ad34` | certain | Every project is a real GitHub repository that you own. Start from a clean slate, or bring a repo you already | `public-landing/projects.html:904` |
|
|
1426
1426
|
| `71b0ef2552c4` | certain | Every project you own, in one place — its live status, its address, and the controls that matter. Sign in with | `public-landing/projects.html:590` |
|
|
1427
1427
|
| `478bc7f0e492` | certain | Every project you own: what it is, whether it is answering, and the controls that matter. Each row says what t | `public-landing/projects.html:582` |
|
|
1428
|
-
| `2585087f4873` | certain | Fair use | `public-landing/terms.html:
|
|
1428
|
+
| `2585087f4873` | certain | Fair use | `public-landing/terms.html:72` |
|
|
1429
1429
|
| `fec69b6c7458` | certain | Filter by state | `public-landing/projects.html:612` |
|
|
1430
1430
|
| `0208e4bbba9c` | certain | Find a project | `public-landing/index.html:892` |
|
|
1431
1431
|
| `0208e4bbba9c` | certain | Find a project | `public-landing/projects.html:378` |
|
|
@@ -1437,6 +1437,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1437
1437
|
| `655cfdd22c8d` | certain | Found a way in? Please don't put the details in a public issue. Reach the owner through the hall, or open an i | `public-landing/contact.html:62` |
|
|
1438
1438
|
| `aab2b51efeab` | certain | Free while we find our feet. Your project’s repo and server are yours — | `public-landing/projects.html:813` |
|
|
1439
1439
|
| `aab2b51efeab` | certain | Free while we find our feet. Your project’s repo and server are yours — | `public-landing/projects.html:834` |
|
|
1440
|
+
| `0808df6e434c` | certain | From your settings you can hide your statistics, drop out of the recruiting directory, or make your account pr | `public-landing/terms.html:69` |
|
|
1440
1441
|
| `8bb1f00b1558` | certain | Get access to our advanced project presets and module packages. | `public-landing/index.html:868` |
|
|
1441
1442
|
| `98eb6344d39e` | certain | GitHub owner | `public-landing/projects.html:952` |
|
|
1442
1443
|
| `4995791c6449` | certain | Go to the hall | `public-landing/contact.html:56` |
|
|
@@ -1469,6 +1470,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1469
1470
|
| `f8665480baf6` | certain | Nothing is sold, and nothing is shared for advertising. | `public-landing/privacy.html:67` |
|
|
1470
1471
|
| `837fdaa0936a` | certain | Nothing matches that. | `public-landing/projects.html:620` |
|
|
1471
1472
|
| `2c951d1c7f72` | certain | Example | `public-landing/index.html:741` |
|
|
1473
|
+
| `69400ca12477` | certain | Once you have signed in here and accepted these terms, your profile and that record are public by default: at | `public-landing/terms.html:68` |
|
|
1472
1474
|
| `8329bb1a3693` | certain | One tap files the request and the platform starts standing your project up — server, database, address. Here's | `public-landing/projects.html:1013` |
|
|
1473
1475
|
| `86cde1930d84` | certain | Only mine | `public-landing/projects.html:385` |
|
|
1474
1476
|
| `f82fe1982ab3` | certain | Open an issue on the repository | `public-landing/contact.html:52` |
|
|
@@ -1476,7 +1478,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1476
1478
|
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/index.html:900` |
|
|
1477
1479
|
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/privacy.html:80` |
|
|
1478
1480
|
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/projects.html:1115` |
|
|
1479
|
-
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/terms.html:
|
|
1481
|
+
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/terms.html:84` |
|
|
1480
1482
|
| `275ca0d5ce65` | certain | Open source. | `public-landing/index.html:862` |
|
|
1481
1483
|
| `74cdcd87d1fa` | certain | Open the map | `public-landing/index.html:755` |
|
|
1482
1484
|
| `b4a3643706ac` | certain | Open → | `public-landing/projects.html:520` |
|
|
@@ -1492,9 +1494,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1492
1494
|
| `edab0ed81a40` | certain | Project name | `public-landing/projects.html:826` |
|
|
1493
1495
|
| `9685afcf24b1` | certain | Project type | `public-landing/projects.html:848` |
|
|
1494
1496
|
| `b76fce69822b` | certain | Projects aren’t created from this instance — this is a project, not the platform that hosts them. | `public-landing/projects.html:1107` |
|
|
1495
|
-
| `351a61f190a6` | certain | Questions go through the | `public-landing/terms.html:
|
|
1497
|
+
| `351a61f190a6` | certain | Questions go through the | `public-landing/terms.html:80` |
|
|
1496
1498
|
| `664f5731ddc3` | certain | Read the source. | `public-landing/privacy.html:75` |
|
|
1497
|
-
| `664f5731ddc3` | certain | Read the source. | `public-landing/terms.html:
|
|
1499
|
+
| `664f5731ddc3` | certain | Read the source. | `public-landing/terms.html:79` |
|
|
1498
1500
|
| `45f7bea67776` | certain | Reading the project’s settings… | `public-landing/projects.html:725` |
|
|
1499
1501
|
| `45f7bea67776` | certain | Reading the project’s settings… | `public-landing/projects.html:740` |
|
|
1500
1502
|
| `0fbe47b01d2c` | certain | Reading the project… | `public-landing/projects.html:677` |
|
|
@@ -1548,6 +1550,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1548
1550
|
| `fb416bf1a26b` | certain | The handle names your project on the platform — and its address comes with it. Once it stands up, a few GitHub | `public-landing/projects.html:981` |
|
|
1549
1551
|
| `a954f0dce9a3` | certain | The platform | `public-landing/contact.html:65` |
|
|
1550
1552
|
| `4fd8f5746cc5` | certain | The platform is run as a non-profit, capture-resistant commons. | `public-landing/terms.html:50` |
|
|
1553
|
+
| `198f1eac5a95` | certain | The platform stores the date you accepted these terms, and which version, on your account. It is written only | `public-landing/terms.html:70` |
|
|
1551
1554
|
| `20fcebaa85c4` | certain | The project hub needs JavaScript — the map, your projects, and starting a new one all live here. You can read | `public-landing/projects.html:438` |
|
|
1552
1555
|
| `4a740b5afe73` | certain | The project map | `public-landing/projects.html:448` |
|
|
1553
1556
|
| `345fec12e5d8` | certain | The repository | `public-landing/contact.html:50` |
|
|
@@ -1555,13 +1558,14 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1555
1558
|
| `502ab071ba33` | certain | The short version: this is free software run by its owner, your code stays yours, and you are responsible for | `public-landing/terms.html:46` |
|
|
1556
1559
|
| `62377d81c52c` | certain | The six most recent, straight from the ledger. | `public-landing/index.html:798` |
|
|
1557
1560
|
| `2b193468bbb5` | certain | These are the same steps however a project is created — nothing here is special to this page. | `public-landing/projects.html:1035` |
|
|
1558
|
-
| `
|
|
1561
|
+
| `02e596cc4569` | certain | These numbers describe; they do not govern. | `public-landing/terms.html:67` |
|
|
1562
|
+
| `ea7de26ce2f0` | certain | These terms ship with the software and change with it. The version served on this page is the one that applies | `public-landing/terms.html:79` |
|
|
1559
1563
|
| `1eff94c94b66` | certain | This files the request; the control plane does the real standup and nothing touches servers from this page. Yo | `public-landing/projects.html:1020` |
|
|
1560
1564
|
| `d83b739afb1e` | certain | This is a project’s management page — it answers only to the person who owns it. Sign in with GitHub to open y | `public-landing/projects.html:662` |
|
|
1561
1565
|
| `406e774e0952` | certain | This project’s deploys read its code from GitHub with an older key that only works on public repositories — so | `public-landing/projects.html:712` |
|
|
1562
1566
|
| `11c244aec5c3` | certain | This statement describes the software as it ships and changes when the software does. Revised August 2026. | `public-landing/privacy.html:76` |
|
|
1563
1567
|
| `e34d363aa4a4` | certain | To have your account records, or a torn-down project's data, cleared for good, ask the owner through either do | `public-landing/contact.html:59` |
|
|
1564
|
-
| `1652025c0635` | certain | To the extent the law allows, the people running {{productName}} are not liable for loss arising from its use. | `public-landing/terms.html:
|
|
1568
|
+
| `1652025c0635` | certain | To the extent the law allows, the people running {{productName}} are not liable for loss arising from its use. | `public-landing/terms.html:76` |
|
|
1565
1569
|
| `9b514fce13d7` | certain | Torn down | `public-landing/projects.html:617` |
|
|
1566
1570
|
| `b1dd149424ea` | certain | Turn the filter off to see what everyone else is building — or start your own. | `public-landing/projects.html:474` |
|
|
1567
1571
|
| `6ca9f17bdfb5` | certain | Two doors. Both are public, and both are how {{productName}} itself works day to day. | `public-landing/contact.html:47` |
|
|
@@ -1573,10 +1577,12 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1573
1577
|
| `b61aa2d43200` | certain | We’ll create an empty | `public-landing/projects.html:948` |
|
|
1574
1578
|
| `a92fc4987ec9` | certain | What are you building? | `public-landing/projects.html:880` |
|
|
1575
1579
|
| `a8e7cb7ab874` | certain | What each choice changes | `public-landing/projects.html:742` |
|
|
1580
|
+
| `9b3312899fb1` | certain | What is public. | `public-landing/terms.html:68` |
|
|
1576
1581
|
| `b19e6b7ddc42` | certain | What kind of project is it? | `public-landing/projects.html:845` |
|
|
1577
1582
|
| `186d0f85f7be` | certain | What should it be called? | `public-landing/projects.html:826` |
|
|
1578
1583
|
| `e6146707c41a` | certain | What this is | `public-landing/terms.html:49` |
|
|
1579
1584
|
| `75c051ff8da1` | certain | What this removes — and what it keeps | `public-landing/projects.html:763` |
|
|
1585
|
+
| `6130dcb60532` | certain | What you control. | `public-landing/terms.html:69` |
|
|
1580
1586
|
| `b938baf0f723` | certain | What {{productName}} keeps about you and your project, who else sees it, and how long it stays — in plain word | `public-landing/privacy.html:46` |
|
|
1581
1587
|
| `6833e88a3744` | certain | What “only signed-in members” changes | `public-landing/projects.html:727` |
|
|
1582
1588
|
| `369c1eaf71fc` | certain | Where the code lives | `public-landing/projects.html:903` |
|
|
@@ -1589,6 +1595,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1589
1595
|
| `3ca8811b40cd` | certain | You don’t own or build on anything here yet. | `public-landing/projects.html:473` |
|
|
1590
1596
|
| `af11ac12fd91` | certain | You sign in through GitHub; we never see your GitHub password. From GitHub we receive and keep your numeric Gi | `public-landing/privacy.html:53` |
|
|
1591
1597
|
| `23a75f39643e` | certain | You sign in with GitHub and are responsible for that account. Who may join {{productName}}, and at what rank, | `public-landing/terms.html:53` |
|
|
1598
|
+
| `0f06f7e72ea7` | certain | Your acceptance is recorded. | `public-landing/terms.html:70` |
|
|
1592
1599
|
| `a4d2357d486b` | certain | Your account | `public-landing/terms.html:52` |
|
|
1593
1600
|
| `3b85c9182b9d` | certain | Your builder record and your shipped work stay attributed to you after you leave — the ledger of who built wha | `public-landing/privacy.html:71` |
|
|
1594
1601
|
| `28e8cc65790f` | certain | Your code is not kept here as the source of truth. It lives in your GitHub repository; the project's server ho | `public-landing/privacy.html:59` |
|
|
@@ -1601,6 +1608,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1601
1608
|
| `878439d60f78` | certain | Your projects and your code | `public-landing/terms.html:55` |
|
|
1602
1609
|
| `f04dcdea0f96` | certain | Your repositories | `public-landing/projects.html:936` |
|
|
1603
1610
|
| `8391cfe0dd03` | certain | Your steps — the parts only you can play | `public-landing/projects.html:1033` |
|
|
1611
|
+
| `cd379e3e0111` | certain | Your work across projects | `public-landing/terms.html:65` |
|
|
1604
1612
|
| `bb158e10340b` | certain | Yours from the moment it stands up. You can point a domain you own at it any time. | `public-landing/projects.html:989` |
|
|
1605
1613
|
| `b7cee0f10353` | certain | a game, 11 builders | `public-landing/index.html:742` |
|
|
1606
1614
|
| `9cebd20afcba` | certain | about it, and the controls you have today. | `public-landing/projects.html:656` |
|
|
@@ -1610,7 +1618,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1610
1618
|
| `c16cf5f7fe01` | certain | built in its own worktree | `public-landing/index.html:773` |
|
|
1611
1619
|
| `2735c2eb8bc6` | certain | click a project | `public-landing/projects.html:477` |
|
|
1612
1620
|
| `c9435fd3a8c0` | certain | contact page | `public-landing/privacy.html:72` |
|
|
1613
|
-
| `c9435fd3a8c0` | certain | contact page | `public-landing/terms.html:
|
|
1621
|
+
| `c9435fd3a8c0` | certain | contact page | `public-landing/terms.html:80` |
|
|
1614
1622
|
| `cce8a45fd1ad` | certain | erase the project: it stays in your list marked | `public-landing/projects.html:764` |
|
|
1615
1623
|
| `b55e0a82615f` | certain | every project | `public-landing/projects.html:492` |
|
|
1616
1624
|
| `94a3462373d2` | certain | five questions and a home | `public-landing/index.html:692` |
|
|
@@ -1628,7 +1636,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1628
1636
|
| `54b2ecb33701` | certain | or enter it manually | `public-landing/projects.html:930` |
|
|
1629
1637
|
| `af9fcc3a4124` | certain | paid only once it lands | `public-landing/index.html:788` |
|
|
1630
1638
|
| `7a053a51ee5f` | certain | privacy page | `public-landing/contact.html:59` |
|
|
1631
|
-
| `7a053a51ee5f` | certain | privacy page | `public-landing/terms.html:
|
|
1639
|
+
| `7a053a51ee5f` | certain | privacy page | `public-landing/terms.html:80` |
|
|
1632
1640
|
| `370e51d318b8` | certain | project: its own repository, its own home on the web, and a hall of AI builders who do the building. You set t | `public-landing/projects.html:795` |
|
|
1633
1641
|
| `646b1e72622d` | certain | read by a panel | `public-landing/index.html:778` |
|
|
1634
1642
|
| `cb0b8873d563` | certain | repo — projects here are open by design. Want private code? Create the repo yourself on GitHub and “adopt” it | `public-landing/projects.html:948` |
|