@bongos/core 1.19.329 → 1.19.331
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 +17 -17
- package/config/branding.neutral.json +1 -1
- package/docs/copy-inventory.md +8 -6
- package/docs/copy-registry.json +44 -16
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +4 -0
- package/public-landing/index.html +1 -1
- package/public-landing/projects.html +10 -6
- package/src/bongos/routes/auth.js +19 -10
- package/src/module-api.js +5 -1
- package/tests/post_login_landing.mjs +35 -35
- package/tests/projects_hub_pre_uat.mjs +45 -0
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
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.331",
|
|
6
|
+
"core_contract": "1.19.331",
|
|
7
|
+
"source_commit": "cc85e05304300cfad9f701b9f9432f1f74b5cf53",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-25T00:01:28.994Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 324,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 1811,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "68c81c790b852a7c79d261a2d55f43ec6c2dbc17f1e89a80757b41023f929748",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -382,7 +382,7 @@
|
|
|
382
382
|
{
|
|
383
383
|
"path": "config/branding.neutral.json",
|
|
384
384
|
"mode": "0000644",
|
|
385
|
-
"sha256": "
|
|
385
|
+
"sha256": "7b204f9621ced68ef54b9f74aa8fbec53ab2fa81b0380133c762950ac4de1479"
|
|
386
386
|
},
|
|
387
387
|
{
|
|
388
388
|
"path": "config/design-tokens.neutral.json",
|
|
@@ -1452,12 +1452,12 @@
|
|
|
1452
1452
|
{
|
|
1453
1453
|
"path": "docs/copy-inventory.md",
|
|
1454
1454
|
"mode": "0000644",
|
|
1455
|
-
"sha256": "
|
|
1455
|
+
"sha256": "04addfdc7fb7e9b59968d9d8daacd44d24280405868a705a65a3e4fd6166ec90"
|
|
1456
1456
|
},
|
|
1457
1457
|
{
|
|
1458
1458
|
"path": "docs/copy-registry.json",
|
|
1459
1459
|
"mode": "0000644",
|
|
1460
|
-
"sha256": "
|
|
1460
|
+
"sha256": "a7516b85bec7090bf2ea753246e03c0d3cd3505c54ea5de68987cf4b2543001c"
|
|
1461
1461
|
},
|
|
1462
1462
|
{
|
|
1463
1463
|
"path": "docs/design-contract.md",
|
|
@@ -4667,12 +4667,12 @@
|
|
|
4667
4667
|
{
|
|
4668
4668
|
"path": "package-lock.json",
|
|
4669
4669
|
"mode": "0000644",
|
|
4670
|
-
"sha256": "
|
|
4670
|
+
"sha256": "0d95e9a5ad8a6d63dba589cbe1bc8f4497bebf1470776bdbfcf21f470a7bb81e"
|
|
4671
4671
|
},
|
|
4672
4672
|
{
|
|
4673
4673
|
"path": "package.json",
|
|
4674
4674
|
"mode": "0000644",
|
|
4675
|
-
"sha256": "
|
|
4675
|
+
"sha256": "ab2dde9733b1e67f8099474fc5d998b4e4c2060b2ac239ddd16db36bd1570fa5"
|
|
4676
4676
|
},
|
|
4677
4677
|
{
|
|
4678
4678
|
"path": "public-docs/index.html",
|
|
@@ -4912,7 +4912,7 @@
|
|
|
4912
4912
|
{
|
|
4913
4913
|
"path": "public-landing/assets/cosmos.css",
|
|
4914
4914
|
"mode": "0000644",
|
|
4915
|
-
"sha256": "
|
|
4915
|
+
"sha256": "a7f21729b00719b22cfd13c14b33d87f4fdd8aaa2890a174bfc36d1b53c1e5e4"
|
|
4916
4916
|
},
|
|
4917
4917
|
{
|
|
4918
4918
|
"path": "public-landing/assets/verro-medallion.png",
|
|
@@ -4927,12 +4927,12 @@
|
|
|
4927
4927
|
{
|
|
4928
4928
|
"path": "public-landing/index.html",
|
|
4929
4929
|
"mode": "0000644",
|
|
4930
|
-
"sha256": "
|
|
4930
|
+
"sha256": "db0d924005e8806d9e64c5c12b31c91957f1f625da972cafd5745c2cbdbf6dd9"
|
|
4931
4931
|
},
|
|
4932
4932
|
{
|
|
4933
4933
|
"path": "public-landing/projects.html",
|
|
4934
4934
|
"mode": "0000644",
|
|
4935
|
-
"sha256": "
|
|
4935
|
+
"sha256": "203b726527c02ed0383945c431df062ae6f02ed64cadc7942f9fef3e587a9da6"
|
|
4936
4936
|
},
|
|
4937
4937
|
{
|
|
4938
4938
|
"path": "public-landing/world/assets/clouds/cloud-island-large.png",
|
|
@@ -6342,7 +6342,7 @@
|
|
|
6342
6342
|
{
|
|
6343
6343
|
"path": "src/bongos/routes/auth.js",
|
|
6344
6344
|
"mode": "0000644",
|
|
6345
|
-
"sha256": "
|
|
6345
|
+
"sha256": "bb62110c21a07745a8bcfd3e2cf94f29deec1de5baea9d62fa903febcca54f2b"
|
|
6346
6346
|
},
|
|
6347
6347
|
{
|
|
6348
6348
|
"path": "src/bongos/routes/backup.js",
|
|
@@ -6452,7 +6452,7 @@
|
|
|
6452
6452
|
{
|
|
6453
6453
|
"path": "src/module-api.js",
|
|
6454
6454
|
"mode": "0000644",
|
|
6455
|
-
"sha256": "
|
|
6455
|
+
"sha256": "11aa1bff9445edc29d7fe5034536edc7a6758e2f3d4c91d4b16a45c8ca1091ba"
|
|
6456
6456
|
},
|
|
6457
6457
|
{
|
|
6458
6458
|
"path": "src/module-loader/catalog.js",
|
|
@@ -8277,7 +8277,7 @@
|
|
|
8277
8277
|
{
|
|
8278
8278
|
"path": "tests/post_login_landing.mjs",
|
|
8279
8279
|
"mode": "0000644",
|
|
8280
|
-
"sha256": "
|
|
8280
|
+
"sha256": "08a7496090f4617cef7e270afddcef8ee3a0b58bff6920b56bc2f2bbb49ed4ca"
|
|
8281
8281
|
},
|
|
8282
8282
|
{
|
|
8283
8283
|
"path": "tests/pre_compact.mjs",
|
|
@@ -8332,7 +8332,7 @@
|
|
|
8332
8332
|
{
|
|
8333
8333
|
"path": "tests/projects_hub_pre_uat.mjs",
|
|
8334
8334
|
"mode": "0000644",
|
|
8335
|
-
"sha256": "
|
|
8335
|
+
"sha256": "a3cea371bb80b2dc05762a11bc43de84667f06db8723e384b34073e48fdfda6a"
|
|
8336
8336
|
},
|
|
8337
8337
|
{
|
|
8338
8338
|
"path": "tests/promote_goal_id.mjs",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
"landing": {
|
|
106
|
-
"_note": "Where a successful sign-in lands when no explicit ?return= / same-apex Referer was carried (auth.js postLoginLanding). Portable default '/builders' — the hall always exists. A platform-home instance points this at its own front door (cloudbongos.com → '/
|
|
106
|
+
"_note": "Where a successful sign-in lands when no explicit ?return= / same-apex Referer was carried (auth.js postLoginLanding). Portable default '/builders' — the hall always exists. A platform-home instance points this at its own front door (cloudbongos.com → '/', its landing page; the retired '/gate/' orb sky folds to '/' — task 1003233). Validated through the open-redirect allowlist; env override <PREFIX>_POST_LOGIN_LANDING. Task 1002240.",
|
|
107
107
|
"postLogin": "/builders"
|
|
108
108
|
},
|
|
109
109
|
"envPrefix": "CLOUDBONGOS"
|
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
|
+
**1383 strings** across 3 surfaces · 1226 distinct pieces of copy · 1383 certain, 0 heuristic · 127 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` | 65 | 1096 |
|
|
14
14
|
| `status-dashboard` | `modules/status-ui/public` | 4 | 98 |
|
|
15
|
-
| `landing` | `public-landing` | 2 |
|
|
15
|
+
| `landing` | `public-landing` | 2 | 189 |
|
|
16
16
|
|
|
17
17
|
## Confidence, and why it is on every row
|
|
18
18
|
|
|
@@ -76,7 +76,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
76
76
|
| `3837f6d586a3` | 2x | Copy the task prompt to your clipboard | modules/hall-ui/public/goals-page.js:552, modules/hall-ui/public/work.js:356 |
|
|
77
77
|
| `e3fd1febf63d` | 2x | Could not copy to the clipboard. Try again. | modules/hall-ui/public/goals-page.js:515, modules/hall-ui/public/work.js:461 |
|
|
78
78
|
| `7775fec0fa85` | 2x | Could not load sessions. | modules/hall-ui/public/sessions.js:168, modules/hall-ui/public/sessions.js:207 |
|
|
79
|
-
| … | |
|
|
79
|
+
| … | | _87 more in the JSON registry_ | |
|
|
80
80
|
|
|
81
81
|
## `builders-hall` — 1096 strings
|
|
82
82
|
|
|
@@ -1282,7 +1282,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1282
1282
|
| `7667eb552781` | certain | {…}: {…}% ({…}/{…} checks) | `modules/status-ui/public/status.js:468` |
|
|
1283
1283
|
| `6d0d64f10bd9` | certain | ‹ earlier page | `modules/status-ui/public/index.html:321` |
|
|
1284
1284
|
|
|
1285
|
-
## `landing` —
|
|
1285
|
+
## `landing` — 189 strings
|
|
1286
1286
|
|
|
1287
1287
|
| id | conf | text | where |
|
|
1288
1288
|
|---|---|---|---|
|
|
@@ -1328,7 +1328,6 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1328
1328
|
| `c01533093b42` | certain | Create your first project | `public-landing/projects.html:560` |
|
|
1329
1329
|
| `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:829` |
|
|
1330
1330
|
| `3aeefb044b9f` | certain | Creation steps | `public-landing/projects.html:685` |
|
|
1331
|
-
| `b228633307df` | certain | Delete the project | `public-landing/projects.html:660` |
|
|
1332
1331
|
| `47d1558b17a3` | certain | Domain you own | `public-landing/projects.html:862` |
|
|
1333
1332
|
| `d919980d2ca5` | certain | Download our core code and protocols, and build instantly with your team. | `public-landing/index.html:499` |
|
|
1334
1333
|
| `af5ca714d375` | certain | Equity issuance, business filing, and builder compensation. | `public-landing/index.html:509` |
|
|
@@ -1362,11 +1361,13 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1362
1361
|
| `837fdaa0936a` | certain | Nothing matches that. | `public-landing/projects.html:556` |
|
|
1363
1362
|
| `8329bb1a3693` | certain | One tap files the request and the platform starts standing your project up — server, database, address. Here's | `public-landing/projects.html:882` |
|
|
1364
1363
|
| `86cde1930d84` | certain | Only mine | `public-landing/projects.html:394` |
|
|
1364
|
+
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/index.html:546` |
|
|
1365
|
+
| `cbfdd6ac4ec8` | certain | Open source (AGPL-3.0) | `public-landing/projects.html:980` |
|
|
1365
1366
|
| `275ca0d5ce65` | certain | Open source. | `public-landing/index.html:499` |
|
|
1366
1367
|
| `94c67d09c97c` | certain | Open the map → | `public-landing/index.html:476` |
|
|
1367
1368
|
| `b4a3643706ac` | certain | Open → | `public-landing/projects.html:466` |
|
|
1368
1369
|
| `d4e9bf625ab3` | certain | Pick one of your repositories | `public-landing/projects.html:803` |
|
|
1369
|
-
| `
|
|
1370
|
+
| `65635b58dfab` | certain | Pick the shape that fits best — it’s how the project is listed on the map, and it stays as you pick it for now | `public-landing/projects.html:749` |
|
|
1370
1371
|
| `92c7055aa799` | certain | Project handle | `public-landing/projects.html:852` |
|
|
1371
1372
|
| `8b4663ad561c` | certain | Project hub | `public-landing/projects.html:357` |
|
|
1372
1373
|
| `edab0ed81a40` | certain | Project name | `public-landing/projects.html:728` |
|
|
@@ -1400,6 +1401,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1400
1401
|
| `0b1330bed905` | certain | Starting point | `public-landing/projects.html:775` |
|
|
1401
1402
|
| `decfc9512772` | certain | Switch light / dark | `public-landing/projects.html:371` |
|
|
1402
1403
|
| `25bdf1bf7113` | certain | Switch light or dark mode | `public-landing/projects.html:371` |
|
|
1404
|
+
| `d75633cc707d` | certain | Take it offline | `public-landing/projects.html:660` |
|
|
1403
1405
|
| `d3ce1efd0e67` | certain | Tearing down stops the project’s server and its nightly backups. It does | `public-landing/projects.html:668` |
|
|
1404
1406
|
| `f6584b0a728b` | certain | The Verro Labs mark: a galaxy and constellation above a river valley threaded with circuitry | `public-landing/index.html:426` |
|
|
1405
1407
|
| `72e85e8b6f47` | certain | The drums are rolling | `public-landing/projects.html:896` |
|
package/docs/copy-registry.json
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
7
|
-
"unique_ids":
|
|
8
|
-
"certain":
|
|
6
|
+
"strings": 1383,
|
|
7
|
+
"unique_ids": 1226,
|
|
8
|
+
"certain": 1383,
|
|
9
9
|
"heuristic": 0,
|
|
10
|
-
"duplicate_ids":
|
|
10
|
+
"duplicate_ids": 127
|
|
11
11
|
},
|
|
12
12
|
"surfaces": {
|
|
13
13
|
"builders-hall": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"landing": {
|
|
24
24
|
"at": "public-landing",
|
|
25
25
|
"files": 2,
|
|
26
|
-
"strings":
|
|
26
|
+
"strings": 189
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"blind_spots": [
|
|
@@ -818,6 +818,16 @@
|
|
|
818
818
|
"modules/hall-ui/public/work.js:341"
|
|
819
819
|
]
|
|
820
820
|
},
|
|
821
|
+
{
|
|
822
|
+
"id": "cbfdd6ac4ec8",
|
|
823
|
+
"surface": "landing",
|
|
824
|
+
"text": "Open source (AGPL-3.0)",
|
|
825
|
+
"occurrences": 2,
|
|
826
|
+
"at": [
|
|
827
|
+
"public-landing/index.html:546",
|
|
828
|
+
"public-landing/projects.html:980"
|
|
829
|
+
]
|
|
830
|
+
},
|
|
821
831
|
{
|
|
822
832
|
"id": "855277dff074",
|
|
823
833
|
"surface": "builders-hall",
|
|
@@ -11572,15 +11582,6 @@
|
|
|
11572
11582
|
"origin": "html-attr:aria-label",
|
|
11573
11583
|
"confidence": "certain"
|
|
11574
11584
|
},
|
|
11575
|
-
{
|
|
11576
|
-
"id": "b228633307df",
|
|
11577
|
-
"surface": "landing",
|
|
11578
|
-
"text": "Delete the project",
|
|
11579
|
-
"file": "public-landing/projects.html",
|
|
11580
|
-
"line": 660,
|
|
11581
|
-
"origin": "html-text",
|
|
11582
|
-
"confidence": "certain"
|
|
11583
|
-
},
|
|
11584
11585
|
{
|
|
11585
11586
|
"id": "47d1558b17a3",
|
|
11586
11587
|
"surface": "landing",
|
|
@@ -11878,6 +11879,24 @@
|
|
|
11878
11879
|
"origin": "html-text",
|
|
11879
11880
|
"confidence": "certain"
|
|
11880
11881
|
},
|
|
11882
|
+
{
|
|
11883
|
+
"id": "cbfdd6ac4ec8",
|
|
11884
|
+
"surface": "landing",
|
|
11885
|
+
"text": "Open source (AGPL-3.0)",
|
|
11886
|
+
"file": "public-landing/index.html",
|
|
11887
|
+
"line": 546,
|
|
11888
|
+
"origin": "html-text",
|
|
11889
|
+
"confidence": "certain"
|
|
11890
|
+
},
|
|
11891
|
+
{
|
|
11892
|
+
"id": "cbfdd6ac4ec8",
|
|
11893
|
+
"surface": "landing",
|
|
11894
|
+
"text": "Open source (AGPL-3.0)",
|
|
11895
|
+
"file": "public-landing/projects.html",
|
|
11896
|
+
"line": 980,
|
|
11897
|
+
"origin": "html-text",
|
|
11898
|
+
"confidence": "certain"
|
|
11899
|
+
},
|
|
11881
11900
|
{
|
|
11882
11901
|
"id": "275ca0d5ce65",
|
|
11883
11902
|
"surface": "landing",
|
|
@@ -11915,9 +11934,9 @@
|
|
|
11915
11934
|
"confidence": "certain"
|
|
11916
11935
|
},
|
|
11917
11936
|
{
|
|
11918
|
-
"id": "
|
|
11937
|
+
"id": "65635b58dfab",
|
|
11919
11938
|
"surface": "landing",
|
|
11920
|
-
"text": "Pick the shape that fits best — it
|
|
11939
|
+
"text": "Pick the shape that fits best — it’s how the project is listed on the map, and it stays as you pick it for now. Not sure is a fine answer.",
|
|
11921
11940
|
"file": "public-landing/projects.html",
|
|
11922
11941
|
"line": 749,
|
|
11923
11942
|
"origin": "html-text",
|
|
@@ -12220,6 +12239,15 @@
|
|
|
12220
12239
|
"origin": "html-attr:aria-label",
|
|
12221
12240
|
"confidence": "certain"
|
|
12222
12241
|
},
|
|
12242
|
+
{
|
|
12243
|
+
"id": "d75633cc707d",
|
|
12244
|
+
"surface": "landing",
|
|
12245
|
+
"text": "Take it offline",
|
|
12246
|
+
"file": "public-landing/projects.html",
|
|
12247
|
+
"line": 660,
|
|
12248
|
+
"origin": "html-text",
|
|
12249
|
+
"confidence": "certain"
|
|
12250
|
+
},
|
|
12223
12251
|
{
|
|
12224
12252
|
"id": "d3ce1efd0e67",
|
|
12225
12253
|
"surface": "landing",
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.331",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.331",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.331",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
|
@@ -348,6 +348,10 @@ h1{font-family:var(--font-display);font-weight:700;font-size:clamp(24px,3.4vw,32
|
|
|
348
348
|
the browser's default blue, the one colour in the page that is not ours */
|
|
349
349
|
.finePrint a{color:var(--link-ink);font-weight:700;text-decoration:none;}
|
|
350
350
|
.finePrint a:hover{text-decoration:underline;}
|
|
351
|
+
/* the footer's licence link (owner decision 10, 2026-08-24) — the same link
|
|
352
|
+
ink as fine print, so it never falls back to the browser's blue */
|
|
353
|
+
.foot a{color:var(--link-ink);font-weight:700;text-decoration:none;}
|
|
354
|
+
.foot a:hover{text-decoration:underline;}
|
|
351
355
|
|
|
352
356
|
/* ── progress strips: one visual, per-flow vocabularies (direction §4).
|
|
353
357
|
Default = the sea-blue "working" look; .isLive = verified-landed green;
|
|
@@ -543,7 +543,7 @@ h1.big{font-family:var(--font-display);font-weight:700;font-size:clamp(33px,5.4v
|
|
|
543
543
|
<!-- The footer line SPLITS. Its first half is a claim about the platform itself
|
|
544
544
|
and is untrue of a project built on it, so only the attribution half travels.
|
|
545
545
|
(Today's page ships the whole line to every instance — this is that fix.) -->
|
|
546
|
-
<div class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on Cloud Bongos
|
|
546
|
+
<div class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on Cloud Bongos. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.</div>
|
|
547
547
|
|
|
548
548
|
<script>
|
|
549
549
|
(function () {
|
|
@@ -78,7 +78,7 @@ try{var _m=localStorage.getItem('cb-color-mode');if(_m==='light'||_m==='dark')do
|
|
|
78
78
|
@keyframes fadeStep{from{opacity:0;transform:translateX(10px)}to{opacity:1;transform:none}}
|
|
79
79
|
/* show() moves focus to each panel's h1 for keyboard/SR context — keep the
|
|
80
80
|
focus, lose the ring (a black rectangle around a heading; owner walk) */
|
|
81
|
-
h1[tabindex="-1"]:focus{outline:none;}
|
|
81
|
+
h1[tabindex="-1"]:focus:not(:focus-visible){outline:none;}
|
|
82
82
|
/* the done step needs the full card width — the split collapses and the
|
|
83
83
|
bongo pair steps aside for the checklist */
|
|
84
84
|
.createSplit.wizDone{display:block;}
|
|
@@ -657,7 +657,7 @@ h1[tabindex="-1"]:focus{outline:none;}
|
|
|
657
657
|
name typed back: it is the only control on this page that ends
|
|
658
658
|
something, and the card's one-click confirm is too light for it. -->
|
|
659
659
|
<div class="card" id="mDelete">
|
|
660
|
-
<h2 style="font-family:var(--font-display);font-size:19px;margin-bottom:12px;">
|
|
660
|
+
<h2 style="font-family:var(--font-display);font-size:19px;margin-bottom:12px;">Take it offline</h2>
|
|
661
661
|
<div id="mDel"><p class="finePrint">Reading the project…</p></div>
|
|
662
662
|
<!-- the teardown-vs-delete distinction, stated once as a SIBLING of the
|
|
663
663
|
volatile slot (the #mRepoVisWhy shape) so no re-render can drop it.
|
|
@@ -746,7 +746,7 @@ h1[tabindex="-1"]:focus{outline:none;}
|
|
|
746
746
|
forced into a wrong answer, and it can change later. -->
|
|
747
747
|
<section class="panel" id="panel-type" aria-labelledby="type-h">
|
|
748
748
|
<h1 id="type-h">What kind of project is it?</h1>
|
|
749
|
-
<p class="lede">Pick the shape that fits best — it
|
|
749
|
+
<p class="lede">Pick the shape that fits best — it’s how the project is listed on the map, and it stays as you pick it for now. Not sure is a fine answer.</p>
|
|
750
750
|
<form data-next="3">
|
|
751
751
|
<div class="typeCards" id="typeCards" role="group" aria-label="Project type">
|
|
752
752
|
<button type="button" class="tpill" data-type="game" aria-pressed="false">Game</button>
|
|
@@ -977,7 +977,7 @@ h1[tabindex="-1"]:focus{outline:none;}
|
|
|
977
977
|
</div>
|
|
978
978
|
</section>
|
|
979
979
|
|
|
980
|
-
<div class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on <span data-brand-product-inline>Cloud Bongos</span>.</div>
|
|
980
|
+
<div class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on <span data-brand-product-inline>Cloud Bongos</span>. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.</div>
|
|
981
981
|
|
|
982
982
|
<script>
|
|
983
983
|
/* Brand-pack fill (R57): the server injects window.__BRANDING__ ahead of this
|
|
@@ -3505,6 +3505,10 @@ h1[tabindex="-1"]:focus{outline:none;}
|
|
|
3505
3505
|
};
|
|
3506
3506
|
function groupFor(inst) {
|
|
3507
3507
|
if (inst.status === 'active' && inst.last_verified_up === false) return 'attention';
|
|
3508
|
+
/* the card shows its red error paragraph under exactly this condition
|
|
3509
|
+
(renderCard) — a project the owner is being told about cannot sit under
|
|
3510
|
+
Live. The intent-vs-status contract is deliberately left alone. */
|
|
3511
|
+
if (inst.error_note && !inst.open_intent) return 'attention';
|
|
3508
3512
|
return STATE_GROUP[inst.status] || 'all';
|
|
3509
3513
|
}
|
|
3510
3514
|
function findText(inst) {
|
|
@@ -3779,8 +3783,8 @@ h1[tabindex="-1"]:focus{outline:none;}
|
|
|
3779
3783
|
both the honest word and the accurate one, since a revive re-uses exactly
|
|
3780
3784
|
this hostname. */
|
|
3781
3785
|
return inst && inst.hosting_shape === 'dedicated'
|
|
3782
|
-
? 'This project has a machine to itself, so the machine goes away and its database goes with it. Your repository is untouched. Its web address stays reserved for this project and shows an error page until you bring it back.'
|
|
3783
|
-
: 'The server goes away. Your repository is untouched. The database is kept, so bringing it back later restores its memory. Its web address stays reserved for this project and shows an error page until you bring it back.';
|
|
3786
|
+
? 'This project has a machine to itself, so the machine goes away and its database goes with it. Your repository is untouched. Its web address stays reserved for this project and shows an error page until you bring it back. Nothing here erases a project.'
|
|
3787
|
+
: 'The server goes away. Your repository is untouched. The database is kept, so bringing it back later restores its memory. Its web address stays reserved for this project and shows an error page until you bring it back. Nothing here erases a project.';
|
|
3784
3788
|
}
|
|
3785
3789
|
|
|
3786
3790
|
function addressRow(inst) {
|
|
@@ -273,18 +273,27 @@ function configuredOAuthOrigin() {
|
|
|
273
273
|
// was stashed for this sign-in. Configurable per instance via
|
|
274
274
|
// branding.landing.postLogin (env override <PREFIX>_POST_LOGIN_LANDING) so a
|
|
275
275
|
// platform-home instance can land visitors on its OWN front door —
|
|
276
|
-
// cloudbongos.com
|
|
277
|
-
// the
|
|
278
|
-
// (task 1002240). Every other instance keeps the portable default
|
|
279
|
-
// the hall always exists, a
|
|
280
|
-
// run through the SAME open-redirect allowlist as ?return=
|
|
281
|
-
// misconfigured landing can never become an open redirect;
|
|
282
|
-
// absent falls back to '/builders'. Takes an optional
|
|
283
|
-
// path is unit-testable without disk I/O (mirrors
|
|
276
|
+
// cloudbongos.com points it at '/' (its landing page) so a visitor who signs in
|
|
277
|
+
// from the front door returns to it, never auto-redirected into the builders'
|
|
278
|
+
// hall (task 1002240). Every other instance keeps the portable default
|
|
279
|
+
// '/builders': the hall always exists, a front door of its own may not. The
|
|
280
|
+
// configured value is run through the SAME open-redirect allowlist as ?return=
|
|
281
|
+
// (safeReturnTo), so a misconfigured landing can never become an open redirect;
|
|
282
|
+
// anything unsafe or absent falls back to '/builders'. Takes an optional
|
|
283
|
+
// resolved pack so the pure path is unit-testable without disk I/O (mirrors
|
|
284
|
+
// clientBranding()).
|
|
285
|
+
//
|
|
286
|
+
// /gate/ — the orb sky this knob was first written for — was retired with the
|
|
287
|
+
// landing-page front door (task 1002743) and the apex answers a bare 404 there,
|
|
288
|
+
// so a pack still pointing at it would land every cookie-less sign-in on a
|
|
289
|
+
// 404. It folds to '/' instead (task 1003233).
|
|
290
|
+
const RETIRED_LANDINGS = new Set(['/gate']);
|
|
284
291
|
function postLoginLanding(brand) {
|
|
285
292
|
try {
|
|
286
293
|
const b = brand || branding();
|
|
287
|
-
|
|
294
|
+
const configured = safeReturnTo(b.landing?.postLogin) || '/builders';
|
|
295
|
+
const bare = configured.replace(/\/+$/, '').split('?')[0] || '/';
|
|
296
|
+
return RETIRED_LANDINGS.has(bare) ? '/' : configured;
|
|
288
297
|
} catch {
|
|
289
298
|
return '/builders';
|
|
290
299
|
}
|
|
@@ -568,7 +577,7 @@ module.exports = function buildAuthRouter() {
|
|
|
568
577
|
// Land back where sign-in began if a validated return target was stashed
|
|
569
578
|
// (e.g. the builders subdomain bounced through here); else the instance's
|
|
570
579
|
// configured post-login landing (default '/builders'; cloudbongos.com →
|
|
571
|
-
// /
|
|
580
|
+
// '/', its landing page — task 1002240).
|
|
572
581
|
const returnTo = safeReturnTo(parseCookie(req, RETURN_COOKIE));
|
|
573
582
|
res.clearCookie(RETURN_COOKIE, domainOpts);
|
|
574
583
|
res.redirect(returnTo || postLoginLanding());
|
package/src/module-api.js
CHANGED
|
@@ -1085,8 +1085,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
1085
1085
|
// landed since 1.19.327 with no explicit bump. run 32786284063. (task 1002620)
|
|
1086
1086
|
// 1.19.329 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1087
1087
|
// landed since 1.19.328 with no explicit bump. run 32788827293. (task 1002620)
|
|
1088
|
+
// 1.19.330 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1089
|
+
// landed since 1.19.329 with no explicit bump. run 32789596635. (task 1002620)
|
|
1090
|
+
// 1.19.331 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1091
|
+
// landed since 1.19.330 with no explicit bump. run 32791877167. (task 1002620)
|
|
1088
1092
|
// ---------------------------------------------------------------------------
|
|
1089
|
-
const CORE_VERSION = '1.19.
|
|
1093
|
+
const CORE_VERSION = '1.19.331'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
1090
1094
|
|
|
1091
1095
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
1092
1096
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
// tests/post_login_landing.mjs —
|
|
1
|
+
// tests/post_login_landing.mjs — where a cookie-less sign-in lands (task 1003233,
|
|
2
|
+
// the pre-walk ops check for goal 1000058).
|
|
2
3
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// hardened through the SAME open-redirect allowlist as ?return= (safeReturnTo),
|
|
10
|
-
// so a misconfigured landing can never become an open redirect.
|
|
11
|
-
//
|
|
12
|
-
// Pure function, no DB — requiring the route module does not open a pool.
|
|
4
|
+
// The walk found that config/branding.neutral.json still documented the
|
|
5
|
+
// platform-home landing as '/gate/' — the orb sky retired with the landing-page
|
|
6
|
+
// front door (task 1002743), a bare 404 on the apex since. The live instance
|
|
7
|
+
// pack already points at '/', so nothing was broken on the box; this pins the
|
|
8
|
+
// fold that keeps an old pack from ever landing a founder on that 404, and the
|
|
9
|
+
// note that no longer sends an operator there.
|
|
13
10
|
|
|
11
|
+
import { strict as assert } from 'node:assert';
|
|
12
|
+
import { test } from 'node:test';
|
|
14
13
|
import { createRequire } from 'node:module';
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
else { fail++; console.log(` FAIL ${msg}`); }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
console.log('\npostLoginLanding — portable default is the hall:');
|
|
25
|
-
ok(postLoginLanding({}) === '/builders', 'no landing config → /builders');
|
|
26
|
-
ok(postLoginLanding({ landing: {} }) === '/builders', 'empty landing block → /builders');
|
|
27
|
-
// No-arg path reads the real committed neutral pack, which ships postLogin:'/builders'.
|
|
28
|
-
ok(postLoginLanding() === '/builders', 'committed neutral pack → /builders');
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
|
+
const { postLoginLanding } = require(path.join(ROOT, 'src/bongos/routes/auth.js'));
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
test('a pack that still names the retired /gate/ lands on the front door, not a 404', () => {
|
|
23
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '/gate/' } }), '/');
|
|
24
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '/gate' } }), '/');
|
|
25
|
+
});
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
test('every live landing passes through untouched; absent or unsafe falls back to the hall', () => {
|
|
28
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '/' } }), '/', 'cloudbongos.com today');
|
|
29
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '/projects' } }), '/projects');
|
|
30
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '/builders' } }), '/builders');
|
|
31
|
+
assert.equal(postLoginLanding({ landing: {} }), '/builders');
|
|
32
|
+
assert.equal(postLoginLanding({}), '/builders');
|
|
33
|
+
assert.equal(postLoginLanding({ landing: { postLogin: 'https://evil.example/x' } }), '/builders', 'the open-redirect allowlist still governs');
|
|
34
|
+
assert.equal(postLoginLanding({ landing: { postLogin: '//evil.example' } }), '/builders');
|
|
35
|
+
});
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
test('the neutral pack no longer documents the retired landing as live', () => {
|
|
38
|
+
const pack = JSON.parse(fs.readFileSync(path.join(ROOT, 'config/branding.neutral.json'), 'utf8'));
|
|
39
|
+
assert.equal(pack.landing.postLogin, '/builders', 'the portable default is unchanged');
|
|
40
|
+
assert.doesNotMatch(pack.landing._note, /'\/gate\/', the orbs/, 'the note stops calling /gate/ a front door');
|
|
41
|
+
assert.match(pack.landing._note, /retired '\/gate\/'/, 'and says what became of it');
|
|
42
|
+
});
|
|
@@ -15,6 +15,7 @@ const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
15
15
|
// anchored regexes below reason about line ends
|
|
16
16
|
const HUB = fs.readFileSync(path.join(ROOT, 'public-landing', 'projects.html'), 'utf8').replace(/\r\n/g, '\n');
|
|
17
17
|
const COSMOS = fs.readFileSync(path.join(ROOT, 'public-landing', 'assets', 'cosmos.css'), 'utf8').replace(/\r\n/g, '\n');
|
|
18
|
+
const INDEX = fs.readFileSync(path.join(ROOT, 'public-landing', 'index.html'), 'utf8').replace(/\r\n/g, '\n');
|
|
18
19
|
const SCRIPT = HUB.slice(HUB.lastIndexOf('<script>'), HUB.lastIndexOf('</script>'));
|
|
19
20
|
|
|
20
21
|
// a function's text runs from its declaration to the next declaration in the
|
|
@@ -264,3 +265,47 @@ test('a heartbeat re-render keeps an open fold open and a half-typed domain type
|
|
|
264
265
|
const set = card.indexOf('li.innerHTML = orbFor(inst)');
|
|
265
266
|
assert.ok(card.indexOf('var keepOpen') < set && card.indexOf('if (fold && keepOpen) fold.open = true;') > set, 'read before the swap, restore after it');
|
|
266
267
|
});
|
|
268
|
+
|
|
269
|
+
/* ── the owner's five calls of 2026-08-24 (task 1003250) ── */
|
|
270
|
+
test('decision 6 — the manage section is "Take it offline", and the teardown truth ends by saying nothing erases', () => {
|
|
271
|
+
const del = (HUB.match(/<div class="card" id="mDelete">[\s\S]*?<\/details>\s*<\/div>/) || [''])[0];
|
|
272
|
+
assert.ok(del, '#mDelete exists');
|
|
273
|
+
assert.match(del, /<h2[^>]*>Take it offline<\/h2>/, 'the heading says what the control does');
|
|
274
|
+
assert.doesNotMatch(HUB, /Delete the project/, 'the word "Delete" no longer promises an erase anywhere on the page');
|
|
275
|
+
const truth = fn('teardownTruth');
|
|
276
|
+
assert.equal((truth.match(/until you bring it back\. Nothing here erases a project\.'/g) || []).length, 2, 'both hosting shapes end on the same sentence');
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('decision 5 — the Type step says the type is fixed for now', () => {
|
|
280
|
+
const type = (HUB.match(/<section class="panel" id="panel-type"[\s\S]*?<\/section>/) || [''])[0];
|
|
281
|
+
assert.ok(type, '#panel-type exists');
|
|
282
|
+
assert.match(type, /<p class="lede">Pick the shape that fits best — it’s how the project is listed on the map, and it stays as you pick it for now\. Not sure is a fine answer\.<\/p>/);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test('decision 8 — a card carrying a red error paragraph never tallies under Live', () => {
|
|
286
|
+
const g = fn('groupFor');
|
|
287
|
+
const down = g.indexOf("if (inst.status === 'active' && inst.last_verified_up === false) return 'attention';");
|
|
288
|
+
const err = g.indexOf("if (inst.error_note && !inst.open_intent) return 'attention';");
|
|
289
|
+
const table = g.indexOf('return STATE_GROUP[inst.status]');
|
|
290
|
+
assert.ok(down >= 0 && err > down && err < table, 'the rule sits after the down-probe override and before the status table');
|
|
291
|
+
// the same predicate renderCard uses to show the paragraph — the two cannot drift apart
|
|
292
|
+
assert.match(fn('renderCard'), /if \(\(inst\.status === 'error' \|\| inst\.error_note\) && !inst\.open_intent\) \{/);
|
|
293
|
+
assert.doesNotMatch(g, /open_intent\.action/, 'the intent-vs-status contract is left alone');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
test('decision 9 — only mouse-driven focus on a wizard heading goes ringless', () => {
|
|
297
|
+
assert.match(HUB, /h1\[tabindex="-1"\]:focus:not\(:focus-visible\)\{outline:none;\}/);
|
|
298
|
+
assert.doesNotMatch(HUB, /h1\[tabindex="-1"\]:focus\{outline:none;\}/, 'the blanket suppression is gone');
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test('decision 10 — both footers carry the open-source (AGPL-3.0) link, in link ink', () => {
|
|
302
|
+
const AGPL = /<a href="https:\/\/www\.gnu\.org\/licenses\/agpl-3\.0\.html" target="_blank" rel="noopener">Open source \(AGPL-3\.0\)<\/a>\./;
|
|
303
|
+
const hubFoot = (HUB.match(/<div class="foot">[\s\S]*?<\/div>/) || [''])[0];
|
|
304
|
+
const indexFoot = (INDEX.match(/<div class="foot">[\s\S]*?<\/div>/) || [''])[0];
|
|
305
|
+
assert.match(hubFoot, AGPL, 'projects.html');
|
|
306
|
+
assert.match(indexFoot, AGPL, 'index.html');
|
|
307
|
+
// the link sits OUTSIDE the apex-only span, so a child instance keeps it too
|
|
308
|
+
assert.ok(hubFoot.indexOf('<!--apex-only:end-->') < hubFoot.search(AGPL), 'projects.html: after the apex-only block');
|
|
309
|
+
assert.ok(indexFoot.indexOf('<!--apex-only:end-->') < indexFoot.search(AGPL), 'index.html: after the apex-only block');
|
|
310
|
+
assert.match(COSMOS, /\.foot a\{color:var\(--link-ink\);font-weight:700;text-decoration:none;\}/, 'never the browser’s blue');
|
|
311
|
+
});
|