@bongos/core 1.25.17 → 1.25.18
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 +131 -61
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +10 -0
- package/clients/bongos-client/index.cjs +10 -0
- package/clients/bongos-client/index.d.ts +15 -1
- package/clients/bongos-client/index.mjs +10 -0
- package/docs/adr/0408-a-genesis-stage-is-three-doors-onto-one-record.md +1 -0
- package/docs/api/openapi.json +243 -6
- package/docs/api-reference.md +12 -3
- package/docs/copy-inventory.md +118 -108
- package/docs/copy-registry.json +315 -172
- package/docs/file-map.md +2 -1
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-inventory.json +3 -0
- package/docs/page-readings.json +62 -62
- package/modules/app-host/CLAUDE.md +15 -0
- package/modules/app-host/module.json +20 -0
- package/modules/app-host/public/settings-widget.js +143 -0
- package/modules/app-host/routes/app-host.js +88 -0
- package/modules/government/charter-advice.js +103 -0
- package/modules/government/presets.js +42 -0
- package/modules/government/recommendations.js +102 -7
- package/modules/government/routes/government.js +1 -0
- package/modules/lifecycle/first-read-catalog.js +62 -0
- package/modules/lifecycle/first-read-db.js +47 -9
- package/modules/lifecycle/first-read.js +88 -23
- package/modules/lifecycle/migrations/lifecycle_023_repo_map_dismissed.sql +19 -0
- package/modules/lifecycle/routes/first-read.js +27 -5
- package/modules/onboarding/genesis-work.js +101 -4
- package/modules/onboarding/routes/genesis-work.js +2 -2
- package/modules/platform-identity/module.json +1 -1
- package/modules/platform-identity/routes/sso-app-status.js +65 -0
- package/modules/provisioning/module.json +1 -0
- package/modules/provisioning/seams.js +32 -1
- package/modules/provisioning/starter-bundles.js +1 -0
- package/modules/public-landing/public/assets/guide-core.js +475 -0
- package/modules/public-landing/public/assets/guide-hall.css +121 -0
- package/modules/public-landing/public/assets/guide-hall.js +164 -0
- package/modules/public-landing/public/assets/guide-scene.css +9 -0
- package/modules/public-landing/public/assets/guide-scene.js +58 -381
- package/modules/public-landing/public/index.html +46 -1
- package/modules/public-landing/public/projects.html +11 -2
- package/modules/ui-design/kit/serve.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +18 -0
- package/scripts/bongos/first-read.js +45 -11
- package/scripts/bongos/genesis.js +21 -1
- package/scripts/bongos/publish-manifest.js +1 -0
- package/scripts/bongos/seam-wiring-guard.js +3 -2
- package/scripts/hall-preview/server.js +2 -0
- package/src/bongos/auth-admission.js +64 -0
- package/src/bongos/auth.js +2 -1
- package/src/bongos/module-scope-map.js +4 -0
- package/src/bongos/routes/core-update.js +3 -16
- package/src/bongos/routes/modules.js +11 -0
- package/src/bongos/serve-internal.js +20 -6
- package/src/module-api.js +6 -1
- package/src/module-loader/loader.js +2 -2
- package/tests/app_host.mjs +413 -0
- package/tests/first_read.mjs +184 -8
- package/tests/genesis_work.mjs +74 -3
- package/tests/government_charter_advice.mjs +150 -0
- package/tests/landing_guide_hall.mjs +364 -0
- package/tests/landing_guide_scene.mjs +8 -5
- package/tests/module_api.mjs +1 -0
- package/tests/module_loader.mjs +1 -1
- package/tests/npm_release_where.mjs +13 -3
package/docs/file-map.md
CHANGED
|
@@ -116,7 +116,8 @@
|
|
|
116
116
|
│ ├── copy-desk/ ← CORE-DOMAIN module (task 1003113 / R02 of goal 1000074, default-on): the COPY half of the design contract — ADR 0081 gave design TOKENS a repo-owned source of truth, text had none. Owns the FLAG (anyone in any role marks a string or a whole surface as needing an artist's attention, with a reason required in BOTH the route and a CHECK constraint) and the QUEUE an artist reads it from. READS R01's committed registry (docs/copy-registry.json, generated by scripts/bongos/copy-inventory.js) and never writes it. NO LIVE CMS is the hard non-goal: no column here could hold replacement text, and copy_no_cms.mjs pins that. Key is `copy-desk`, not `copy` — the branding contract already owns a `copy` block, so the bare word reds the "core carries no module code" fitness check. R03 (task 1003114, ADR 0233) added the PROPOSAL: an artist writes the replacement wording and it becomes a Bongos task carrying a fenced copy-proposal patch — no row, NO second migration (a proposals table is the forbidden column with extra steps), and scripts/bongos/copy-apply.js lands it as a real diff under a claim. BV2.TW05 (task 1004316, ADR 0341 D8) added Tweak Mode's three derived READS — GET /copy-desk/pages, /copy-desk/pages/:pageId, /copy-desk/tally: page status and count, changelog, drift, "N of M tweaked" per surface, and the artist's tally — over the page-tweak tasks (lifecycle port), docs/page-inventory.json and docs/page-readings.json (both now in the publish manifest), with no status table. BV2.TW06 (task 1004317, ADR 0341 D2, D5, D6) added its first two page WRITES: POST /copy-desk/pages/:pageId/claim (an artist-craft builder opens or takes the page's tweak round as a web-claimed task, through the lifecycle port's webClaimPageTweak, under an advisory lock on the page) and POST /copy-desk/pages/:pageId/asks (anyone files a page ask, a copy_desk_flags row with scope 'page', added by copy_desk_002_page_asks.sql). CLAUDE.md, module.json, registry.js, flags.js, proposals.js, pages.js (the page-tweak block format), page-status.js (the pure derivation), page-data.js (the page artifacts' read side), routes/copy-desk.js, migrations/copy_desk_001_flags.sql, migrations/copy_desk_002_page_asks.sql, tests/{copy_flags,copy_queue,copy_no_cms,copy_proposals,copy_page_status}.mjs + tests/fixtures/page-tweak.cjs. Its hall surface lives with hall-ui (public/copy-desk.{html,js,css}), per the one-key-per-web-surface precedent. skills/tweak/SKILL.md is the /tweak skill (contributes.skills; moved out of .claude/skills/ in task 1004471, hidden from the model listing, typed as /tweak).
|
|
117
117
|
│ ├── page-notes/ ← the artist's page feedback docs (task 1004496, default-on): the Artistry palette button's store. A doc about one hall page, with up to eight reference images (stored in the DB, images only), turned into ideas by an AI split on submit and kept as the page's reference (?note=N). Apart from copy-desk, which may hold no wording. module.json, CLAUDE.md, notes.js (pure), split.js, db.js, routes/, migrations/.
|
|
118
118
|
│ ├── ai-studio/ ← AI generation for artists (task 1004916, ADR 0392, default-off; hub first): a sketch or image set plus a prompt gets a Gemini reply and generated images on our key (processor-held balance, one named price multiplier, funds held first, released on failure) or the builder's own key (no charge). Keys entered only in Settings, never leave the server. module.json, CLAUDE.md, routes/.
|
|
119
|
-
│ ├──
|
|
119
|
+
│ ├── app-host/ ← where the app runs (task 1004571, default-on): the options menu's panel showing where a hosted project's app runs (no platform, or Render with its stage and address), read from the hub over POST /sso/app-status; the owner (core.pin.move) gets Connect Render / retry links to the hub's Manage panel. module.json, CLAUDE.md, routes/app-host.js, public/settings-widget.js.
|
|
120
|
+
│ ├── front-door-guide/ ← the start-a-project guide (task 1005272, goal 1000106, default-off; hub first): a signed-out visitor talks with an AI guide for a few capped messages before signing up, on the platform's own Anthropic key from the environment. Every cap on the server (messages and spend per visitor, daily and monthly site budget, message length, rate limits, bot check); a spent budget or no key answers the plain form. module.json, CLAUDE.md (the response shape), settings.js, guide.js, claude.js, limits.js, db.js, routes/, migrations/.
|
|
120
121
|
│ ├── market-watch/ ← Market Watch (task 1004935, goal 1000137, default-off): a weekly AI watch on a project's competitors, partners and topics. No routes yet; the manifest declares spend.requiresPayer. Kept out of the creation picker (HUB_ONLY_MODULES) until it does something. Data layer (task 1004936): migrations/ (market_watch_* tables), db.js (read queries), seed.js + seed/ (the 2026-10-28 research, hub only), pollers/hub-seed.js. module.json, CLAUDE.md.
|
|
121
122
|
│ ├── raise/ ← the /raise investor page (task 1004847, ADR 0384, default-off; hub only): password-gated for investors (signing in accepts the NDA, non-binding interest), edited in place by any active builder with every change logged. The copy in content/ is the owner's words — never reword it in code. module.json, CLAUDE.md, raise.js (pure), page.js, web.js (the GET-only raise.web port core mounts at /raise), db.js, routes/ (every write), migrations/, content/, views/, public/.
|
|
122
123
|
│ ├── npm-release/ ← the deploy page for a project that publishes an npm package from GitHub (task 1002622, default-OFF — on only in the Bongos hall, which publishes @bongos/core). "Where the work is": every task finished in the last 14 days, placed in the stage it has actually reached (not merged · merged, no version yet · published, not running here · running here, not released · released · in no version), plus the version history — each version's tasks. The version↔task join reads the release-notes.json the package itself carries (scripts/bongos/release-notes.js writes it at pack time), streamed out of the NEWEST version's npm tarball in-process (no child process, no sync call) when the running core's own copy stops short. module.json, work.js (the reading + the stage placement — the packument, tarball stream and tar reader it uses are the core's src/bongos/package-registry.js, reached through the doorway's readPackageRegistry since task 1004296), routes/work.js (GET /npm-release/work, gated core.pin.move like the page), public/work.{js,css} (the two sections /deploy lends it: #nr-work, #nr-versions). Task 1004301 added the same line on a task's own page: routes/task-where.js (GET /npm-release/task/:id, any signed-in builder — it shows nothing not already public) + public/task-widget.js, injected into task.html by the loader's uiSections seam (hallWidgetScripts file task-widget.js) to fill #task-contrib on otb:task-shown. Tests sit at the repo root — tests/npm_release_{work,page}.mjs — because a default-off module's own tests/ is skipped by the unit runner.
|
|
@@ -3472,5 +3472,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3472
3472
|
landed since 1.25.14 with no explicit bump. run 43503871976. (task 1002620)
|
|
3473
3473
|
1.25.17 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3474
3474
|
landed since 1.25.16 with no explicit bump. run 43506364199. (task 1002620)
|
|
3475
|
+
1.25.18 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3476
|
+
landed since 1.25.17 with no explicit bump. run 43517532785. (task 1002620)
|
|
3475
3477
|
---------------------------------------------------------------------------
|
|
3476
3478
|
```
|
package/docs/page-inventory.json
CHANGED
|
@@ -1677,7 +1677,10 @@
|
|
|
1677
1677
|
"modules/ui-design/public/tokens.css",
|
|
1678
1678
|
"modules/public-landing/public/assets/world.css",
|
|
1679
1679
|
"modules/public-landing/public/assets/guide-scene.css",
|
|
1680
|
+
"modules/public-landing/public/assets/guide-hall.css",
|
|
1681
|
+
"modules/public-landing/public/assets/guide-core.js",
|
|
1680
1682
|
"modules/public-landing/public/assets/guide-scene.js",
|
|
1683
|
+
"modules/public-landing/public/assets/guide-hall.js",
|
|
1681
1684
|
"modules/public-landing/public/assets/artist-review.js"
|
|
1682
1685
|
],
|
|
1683
1686
|
"states_files": [
|
package/docs/page-readings.json
CHANGED
|
@@ -3909,97 +3909,97 @@
|
|
|
3909
3909
|
"surface": "landing",
|
|
3910
3910
|
"title": "{{productName}}: {{tagline}}",
|
|
3911
3911
|
"states_read": ["out","in","out-projects","in-profile","cli-out"],
|
|
3912
|
-
"files_hash": "
|
|
3912
|
+
"files_hash": "50e2a85506962213",
|
|
3913
3913
|
"reading_hash": "50e33d9c2cb09eb0",
|
|
3914
3914
|
"counts": {"lines":85,"placed":50,"shared":16,"unplaced":19},
|
|
3915
3915
|
"omitted": {"data":6},
|
|
3916
3916
|
"notes": [],
|
|
3917
3917
|
"lines": [
|
|
3918
|
-
{"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3918
|
+
{"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/public-landing/public/index.html","line":702,"string_id":"a061df49e6cb"},
|
|
3919
3919
|
{"key":"L0002","section":"top bar","text":"Community","placement":"shared"},
|
|
3920
3920
|
{"key":"L0003","section":"top bar","text":"Projects","placement":"shared"},
|
|
3921
|
-
{"key":"L0004","section":"top bar","text":"New account","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3921
|
+
{"key":"L0004","section":"top bar","text":"New account","placement":"shared","file":"modules/public-landing/public/index.html","line":724,"string_id":"bb78cca99fe5"},
|
|
3922
3922
|
{"key":"L0005","section":"top bar","text":"Review","placement":"shared","state":"in"},
|
|
3923
|
-
{"key":"L0006","section":"page top","text":"My projects","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3923
|
+
{"key":"L0006","section":"page top","text":"My projects","placement":"placed","file":"modules/public-landing/public/index.html","line":765,"string_id":"4a167ef6e515","state":"in-profile"},
|
|
3924
3924
|
{"key":"L0007","section":"page top","text":"Invitations","placement":"unplaced","state":"in-profile"},
|
|
3925
3925
|
{"key":"L0008","section":"page top","text":"Connections","placement":"unplaced","state":"in-profile"},
|
|
3926
3926
|
{"key":"L0009","section":"page top","text":"Account","placement":"unplaced","state":"in-profile"},
|
|
3927
|
-
{"key":"L0010","section":"page top","text":"Sign out","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3928
|
-
{"key":"L0011","section":"top bar","text":"Sign in","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3927
|
+
{"key":"L0010","section":"page top","text":"Sign out","placement":"placed","file":"modules/public-landing/public/index.html","line":774,"string_id":"f9af2d90ce5b","state":"in-profile"},
|
|
3928
|
+
{"key":"L0011","section":"top bar","text":"Sign in","placement":"shared","file":"modules/public-landing/public/index.html","line":726,"string_id":"ad80586f802a"},
|
|
3929
3929
|
{"key":"L0012","section":"page top","text":"Sky","placement":"unplaced","state":"out-projects"},
|
|
3930
|
-
{"key":"L0013","section":"page top","text":"a universe of Projects","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3930
|
+
{"key":"L0013","section":"page top","text":"a universe of Projects","placement":"placed","file":"modules/public-landing/public/index.html","line":751,"string_id":"ed075e6e5f3a","state":"out-projects"},
|
|
3931
3931
|
{"key":"L0014","section":"page top","text":"Table","placement":"unplaced","state":"out-projects"},
|
|
3932
|
-
{"key":"L0015","section":"page top","text":"sky project directory","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3933
|
-
{"key":"L0016","section":"page top","text":"+ Create New Project","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3934
|
-
{"key":"L0017","section":"page top","text":"fresh start/fresh idea","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3935
|
-
{"key":"L0018","section":"Building Digitally,as simple as Bongos.","text":"Building Digitally,","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3936
|
-
{"key":"L0019","section":"Building Digitally,as simple as Bongos.","text":"as simple as Bongos.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3937
|
-
{"key":"L0020","section":"Building Digitally,as simple as Bongos.","text":"Bringing AI to the artisan and the artist in everyone.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3938
|
-
{"key":"L0021","section":"Building Digitally,as simple as Bongos.","text":"Find a project to join","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3939
|
-
{"key":"L0022","section":"Building Digitally,as simple as Bongos.","text":"Start a project","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3940
|
-
{"key":"L0023","section":"Built on Bongos.","text":"Built on Bongos.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3941
|
-
{"key":"L0024","section":"Built on Bongos.","text":"Example World","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3942
|
-
{"key":"L0025","section":"Built on Bongos.","text":"a game, 11 builders","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3932
|
+
{"key":"L0015","section":"page top","text":"sky project directory","placement":"placed","file":"modules/public-landing/public/index.html","line":752,"string_id":"dd8f15e45e84","state":"out-projects"},
|
|
3933
|
+
{"key":"L0016","section":"page top","text":"+ Create New Project","placement":"placed","file":"modules/public-landing/public/index.html","line":754,"string_id":"205f6e9eab89","state":"out-projects"},
|
|
3934
|
+
{"key":"L0017","section":"page top","text":"fresh start/fresh idea","placement":"placed","file":"modules/public-landing/public/index.html","line":754,"string_id":"46c35bc7dcdf","state":"out-projects"},
|
|
3935
|
+
{"key":"L0018","section":"Building Digitally,as simple as Bongos.","text":"Building Digitally,","placement":"placed","file":"modules/public-landing/public/index.html","line":788,"string_id":"16bc370da814"},
|
|
3936
|
+
{"key":"L0019","section":"Building Digitally,as simple as Bongos.","text":"as simple as Bongos.","placement":"placed","file":"modules/public-landing/public/index.html","line":788,"string_id":"acbabdef6f40"},
|
|
3937
|
+
{"key":"L0020","section":"Building Digitally,as simple as Bongos.","text":"Bringing AI to the artisan and the artist in everyone.","placement":"placed","file":"modules/public-landing/public/index.html","line":790,"string_id":"c6bc1f427fd0"},
|
|
3938
|
+
{"key":"L0021","section":"Building Digitally,as simple as Bongos.","text":"Find a project to join","placement":"placed","file":"modules/public-landing/public/index.html","line":794,"string_id":"483a7eff25f2"},
|
|
3939
|
+
{"key":"L0022","section":"Building Digitally,as simple as Bongos.","text":"Start a project","placement":"placed","file":"modules/public-landing/public/index.html","line":795,"string_id":"2ae36be1c531"},
|
|
3940
|
+
{"key":"L0023","section":"Built on Bongos.","text":"Built on Bongos.","placement":"placed","file":"modules/public-landing/public/index.html","line":804,"string_id":"20b4fa9a0424"},
|
|
3941
|
+
{"key":"L0024","section":"Built on Bongos.","text":"Example World","placement":"placed","file":"modules/public-landing/public/index.html","line":809,"string_id":"1b5a6cfc494c"},
|
|
3942
|
+
{"key":"L0025","section":"Built on Bongos.","text":"a game, 11 builders","placement":"placed","file":"modules/public-landing/public/index.html","line":810,"string_id":"b7cee0f10353"},
|
|
3943
3943
|
{"key":"L0026","section":"Built on Bongos.","text":"0 builders","placement":"unplaced"},
|
|
3944
|
-
{"key":"L0027","section":"Built on Bongos.","text":"Emersonian Circles","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3945
|
-
{"key":"L0028","section":"Built on Bongos.","text":"1 builder","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3946
|
-
{"key":"L0029","section":"Built on Bongos.","text":"View Projects","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3947
|
-
{"key":"L0030","section":"A project as a codebase, regardless of function.","text":"A project as a codebase, regardless of function.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3948
|
-
{"key":"L0031","section":"A project as a codebase, regardless of function.","text":"A laddered beat progresses all tasks.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3944
|
+
{"key":"L0027","section":"Built on Bongos.","text":"Emersonian Circles","placement":"placed","file":"modules/public-landing/public/index.html","line":819,"string_id":"9a4a940d2a56"},
|
|
3945
|
+
{"key":"L0028","section":"Built on Bongos.","text":"1 builder","placement":"placed","file":"modules/public-landing/public/index.html","line":815,"string_id":"22825067f4c5"},
|
|
3946
|
+
{"key":"L0029","section":"Built on Bongos.","text":"View Projects","placement":"placed","file":"modules/public-landing/public/index.html","line":823,"string_id":"b97287183335"},
|
|
3947
|
+
{"key":"L0030","section":"A project as a codebase, regardless of function.","text":"A project as a codebase, regardless of function.","placement":"placed","file":"modules/public-landing/public/index.html","line":830,"string_id":"407982c3d4ff"},
|
|
3948
|
+
{"key":"L0031","section":"A project as a codebase, regardless of function.","text":"A laddered beat progresses all tasks.","placement":"placed","file":"modules/public-landing/public/index.html","line":831,"string_id":"545c82e99696"},
|
|
3949
3949
|
{"key":"L0032","section":"A project as a codebase, regardless of function.","text":"claim","placement":"unplaced"},
|
|
3950
|
-
{"key":"L0033","section":"A project as a codebase, regardless of function.","text":"Take on a task","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3950
|
+
{"key":"L0033","section":"A project as a codebase, regardless of function.","text":"Take on a task","placement":"placed","file":"modules/public-landing/public/index.html","line":836,"string_id":"c160ff80c611"},
|
|
3951
3951
|
{"key":"L0034","section":"A project as a codebase, regardless of function.","text":"build","placement":"unplaced"},
|
|
3952
|
-
{"key":"L0035","section":"A project as a codebase, regardless of function.","text":"run your preferred model","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3952
|
+
{"key":"L0035","section":"A project as a codebase, regardless of function.","text":"run your preferred model","placement":"placed","file":"modules/public-landing/public/index.html","line":841,"string_id":"efbb62ff5488"},
|
|
3953
3953
|
{"key":"L0036","section":"A project as a codebase, regardless of function.","text":"grade","placement":"unplaced"},
|
|
3954
|
-
{"key":"L0037","section":"A project as a codebase, regardless of function.","text":"evaluated by agentic agents","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3954
|
+
{"key":"L0037","section":"A project as a codebase, regardless of function.","text":"evaluated by agentic agents","placement":"placed","file":"modules/public-landing/public/index.html","line":846,"string_id":"f8d9d6f2490f"},
|
|
3955
3955
|
{"key":"L0038","section":"A project as a codebase, regardless of function.","text":"ship","placement":"unplaced"},
|
|
3956
|
-
{"key":"L0039","section":"A project as a codebase, regardless of function.","text":"agentically merged and made live","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3956
|
+
{"key":"L0039","section":"A project as a codebase, regardless of function.","text":"agentically merged and made live","placement":"placed","file":"modules/public-landing/public/index.html","line":851,"string_id":"eedec34758da"},
|
|
3957
3957
|
{"key":"L0040","section":"A project as a codebase, regardless of function.","text":"credit","placement":"unplaced"},
|
|
3958
|
-
{"key":"L0041","section":"A project as a codebase, regardless of function.","text":"equity or cash payouts","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3959
|
-
{"key":"L0042","section":"A project as a codebase, regardless of function.","text":"1,111 of 1,561 shipped on V1","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3960
|
-
{"key":"L0043","section":"A project as a codebase, regardless of function.","text":"The six most recent shipped tasks.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3961
|
-
{"key":"L0044","section":"A project as a codebase, regardless of function.","text":"Landing composition round: three versions of the approved world","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3962
|
-
{"key":"L0045","section":"A project as a codebase, regardless of function.","text":"Percy Jackson","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3958
|
+
{"key":"L0041","section":"A project as a codebase, regardless of function.","text":"equity or cash payouts","placement":"placed","file":"modules/public-landing/public/index.html","line":856,"string_id":"a7767cf28a36"},
|
|
3959
|
+
{"key":"L0042","section":"A project as a codebase, regardless of function.","text":"1,111 of 1,561 shipped on V1","placement":"placed","file":"modules/public-landing/public/index.html","line":864,"string_id":"14277fea260d"},
|
|
3960
|
+
{"key":"L0043","section":"A project as a codebase, regardless of function.","text":"The six most recent shipped tasks.","placement":"placed","file":"modules/public-landing/public/index.html","line":866,"string_id":"40ed6300ba27"},
|
|
3961
|
+
{"key":"L0044","section":"A project as a codebase, regardless of function.","text":"Landing composition round: three versions of the approved world","placement":"placed","file":"modules/public-landing/public/index.html","line":870,"string_id":"376b549bf7c8"},
|
|
3962
|
+
{"key":"L0045","section":"A project as a codebase, regardless of function.","text":"Percy Jackson","placement":"placed","file":"modules/public-landing/public/index.html","line":871,"string_id":"3eb67b892dea","occurrences":4},
|
|
3963
3963
|
{"key":"L0046","section":"A project as a codebase, regardless of function.","text":"27 Aug","placement":"unplaced","occurrences":4},
|
|
3964
|
-
{"key":"L0047","section":"A project as a codebase, regardless of function.","text":"See what you did, by role, including every idea you filed and what became of it","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3965
|
-
{"key":"L0048","section":"A project as a codebase, regardless of function.","text":"ship.js still writes no session record when the session is rooted in another project dir","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3966
|
-
{"key":"L0049","section":"A project as a codebase, regardless of function.","text":"World round: PRODUCT.md and four style candidates across landing, hall and status","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3967
|
-
{"key":"L0050","section":"A project as a codebase, regardless of function.","text":"Footer doors before launch: privacy, terms and contact pages linked from the landing page and the hub","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3964
|
+
{"key":"L0047","section":"A project as a codebase, regardless of function.","text":"See what you did, by role, including every idea you filed and what became of it","placement":"placed","file":"modules/public-landing/public/index.html","line":876,"string_id":"67b61947244d"},
|
|
3965
|
+
{"key":"L0048","section":"A project as a codebase, regardless of function.","text":"ship.js still writes no session record when the session is rooted in another project dir","placement":"placed","file":"modules/public-landing/public/index.html","line":882,"string_id":"156d37716e14"},
|
|
3966
|
+
{"key":"L0049","section":"A project as a codebase, regardless of function.","text":"World round: PRODUCT.md and four style candidates across landing, hall and status","placement":"placed","file":"modules/public-landing/public/index.html","line":888,"string_id":"8a4892d03781"},
|
|
3967
|
+
{"key":"L0050","section":"A project as a codebase, regardless of function.","text":"Footer doors before launch: privacy, terms and contact pages linked from the landing page and the hub","placement":"placed","file":"modules/public-landing/public/index.html","line":894,"string_id":"0a0667aea2db"},
|
|
3968
3968
|
{"key":"L0051","section":"A project as a codebase, regardless of function.","text":"26 Aug","placement":"unplaced","occurrences":2},
|
|
3969
|
-
{"key":"L0052","section":"A project as a codebase, regardless of function.","text":"Task titles are write-once, no route can edit one, so a wrong title is permanent","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3970
|
-
{"key":"L0053","section":"A project as a codebase, regardless of function.","text":"For founders","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3971
|
-
{"key":"L0054","section":"Types of projects","text":"Types of projects","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3972
|
-
{"key":"L0055","section":"Types of projects","text":"Open source.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3973
|
-
{"key":"L0056","section":"Types of projects","text":"Download our core code and protocols, and build instantly with your team.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3974
|
-
{"key":"L0057","section":"Types of projects","text":"Bongos Managed.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3975
|
-
{"key":"L0058","section":"Types of projects","text":"Buy microtransaction packages of code modules on our marketplace.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3976
|
-
{"key":"L0059","section":"Types of projects","text":"Have us handle your hosting.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3977
|
-
{"key":"L0060","section":"Types of projects","text":"Get access to our advanced project presets and module packages.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3978
|
-
{"key":"L0061","section":"Types of projects","text":"Equity issuance, business filing, and builder compensation.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3979
|
-
{"key":"L0062","section":"Types of projects","text":"For builders","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3980
|
-
{"key":"L0063","section":"Ways to get paid/rewarded","text":"Ways to get paid/rewarded","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3981
|
-
{"key":"L0064","section":"Ways to get paid/rewarded","text":"Build equity in multiple projects.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3982
|
-
{"key":"L0065","section":"Ways to get paid/rewarded","text":"Work as a paid contractor for companies big, medium and small.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3983
|
-
{"key":"L0066","section":"Ways to get paid/rewarded","text":"Play as a: game or learning experience.","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3984
|
-
{"key":"L0067","section":"Ways to get paid/rewarded","text":"Start a project","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3985
|
-
{"key":"L0068","section":"Ways to get paid/rewarded","text":"Find a project","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3986
|
-
{"key":"L0069","section":"Ways to get paid/rewarded","text":"Download the CLI","placement":"placed","file":"modules/public-landing/public/index.html","line":
|
|
3969
|
+
{"key":"L0052","section":"A project as a codebase, regardless of function.","text":"Task titles are write-once, no route can edit one, so a wrong title is permanent","placement":"placed","file":"modules/public-landing/public/index.html","line":900,"string_id":"052e2da986c2"},
|
|
3970
|
+
{"key":"L0053","section":"A project as a codebase, regardless of function.","text":"For founders","placement":"placed","file":"modules/public-landing/public/index.html","line":929,"string_id":"dbced351ca0d"},
|
|
3971
|
+
{"key":"L0054","section":"Types of projects","text":"Types of projects","placement":"placed","file":"modules/public-landing/public/index.html","line":930,"string_id":"a165999f36a9"},
|
|
3972
|
+
{"key":"L0055","section":"Types of projects","text":"Open source.","placement":"placed","file":"modules/public-landing/public/index.html","line":932,"string_id":"275ca0d5ce65"},
|
|
3973
|
+
{"key":"L0056","section":"Types of projects","text":"Download our core code and protocols, and build instantly with your team.","placement":"placed","file":"modules/public-landing/public/index.html","line":932,"string_id":"d919980d2ca5"},
|
|
3974
|
+
{"key":"L0057","section":"Types of projects","text":"Bongos Managed.","placement":"placed","file":"modules/public-landing/public/index.html","line":934,"string_id":"4782de01c86b"},
|
|
3975
|
+
{"key":"L0058","section":"Types of projects","text":"Buy microtransaction packages of code modules on our marketplace.","placement":"placed","file":"modules/public-landing/public/index.html","line":936,"string_id":"101339c676b4"},
|
|
3976
|
+
{"key":"L0059","section":"Types of projects","text":"Have us handle your hosting.","placement":"placed","file":"modules/public-landing/public/index.html","line":937,"string_id":"41778f67b4c9"},
|
|
3977
|
+
{"key":"L0060","section":"Types of projects","text":"Get access to our advanced project presets and module packages.","placement":"placed","file":"modules/public-landing/public/index.html","line":938,"string_id":"8bb1f00b1558"},
|
|
3978
|
+
{"key":"L0061","section":"Types of projects","text":"Equity issuance, business filing, and builder compensation.","placement":"placed","file":"modules/public-landing/public/index.html","line":939,"string_id":"af5ca714d375"},
|
|
3979
|
+
{"key":"L0062","section":"Types of projects","text":"For builders","placement":"placed","file":"modules/public-landing/public/index.html","line":945,"string_id":"f510ba460300"},
|
|
3980
|
+
{"key":"L0063","section":"Ways to get paid/rewarded","text":"Ways to get paid/rewarded","placement":"placed","file":"modules/public-landing/public/index.html","line":946,"string_id":"3597d73ce7f9"},
|
|
3981
|
+
{"key":"L0064","section":"Ways to get paid/rewarded","text":"Build equity in multiple projects.","placement":"placed","file":"modules/public-landing/public/index.html","line":948,"string_id":"0f1ec6cf9dfa"},
|
|
3982
|
+
{"key":"L0065","section":"Ways to get paid/rewarded","text":"Work as a paid contractor for companies big, medium and small.","placement":"placed","file":"modules/public-landing/public/index.html","line":949,"string_id":"a581f96fb2c8"},
|
|
3983
|
+
{"key":"L0066","section":"Ways to get paid/rewarded","text":"Play as a: game or learning experience.","placement":"placed","file":"modules/public-landing/public/index.html","line":950,"string_id":"384c5b38f500"},
|
|
3984
|
+
{"key":"L0067","section":"Ways to get paid/rewarded","text":"Start a project","placement":"placed","file":"modules/public-landing/public/index.html","line":795,"string_id":"2ae36be1c531"},
|
|
3985
|
+
{"key":"L0068","section":"Ways to get paid/rewarded","text":"Find a project","placement":"placed","file":"modules/public-landing/public/index.html","line":962,"string_id":"0208e4bbba9c"},
|
|
3986
|
+
{"key":"L0069","section":"Ways to get paid/rewarded","text":"Download the CLI","placement":"placed","file":"modules/public-landing/public/index.html","line":965,"string_id":"41c49e22002d","state":"cli-out"},
|
|
3987
3987
|
{"key":"L0070","section":"Ways to get paid/rewarded","text":"Windows · v0.4.2","placement":"unplaced","state":"cli-out"},
|
|
3988
3988
|
{"key":"L0071","section":"Ways to get paid/rewarded","text":"Also for","placement":"unplaced","state":"cli-out"},
|
|
3989
3989
|
{"key":"L0072","section":"Ways to get paid/rewarded","text":"macOS, Apple silicon","placement":"unplaced","state":"cli-out"},
|
|
3990
3990
|
{"key":"L0073","section":"Ways to get paid/rewarded","text":"macOS, Intel","placement":"unplaced","state":"cli-out"},
|
|
3991
3991
|
{"key":"L0074","section":"Ways to get paid/rewarded","text":"Linux, x64","placement":"unplaced","state":"cli-out"},
|
|
3992
3992
|
{"key":"L0075","section":"Ways to get paid/rewarded","text":"Linux, ARM64","placement":"unplaced","state":"cli-out"},
|
|
3993
|
-
{"key":"L0076","section":"footer","text":"A non-profit, capture-resistant commons.","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3994
|
-
{"key":"L0077","section":"footer","text":"Built by agents, on Cloud Bongos.","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3995
|
-
{"key":"L0078","section":"footer","text":"Open source","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
3993
|
+
{"key":"L0076","section":"footer","text":"A non-profit, capture-resistant commons.","placement":"shared","file":"modules/public-landing/public/index.html","line":1060,"string_id":"afe83bbbd0d4"},
|
|
3994
|
+
{"key":"L0077","section":"footer","text":"Built by agents, on Cloud Bongos.","placement":"shared","file":"modules/public-landing/public/index.html","line":1060,"string_id":"bd315dd71ea7"},
|
|
3995
|
+
{"key":"L0078","section":"footer","text":"Open source","placement":"shared","file":"modules/public-landing/public/index.html","line":1060,"string_id":"d6314ddcc1d0"},
|
|
3996
3996
|
{"key":"L0079","section":"footer","text":"AGPL-3.0","placement":"shared"},
|
|
3997
3997
|
{"key":"L0080","section":"footer","text":"About","placement":"shared"},
|
|
3998
3998
|
{"key":"L0081","section":"footer","text":"Docs","placement":"shared"},
|
|
3999
3999
|
{"key":"L0082","section":"footer","text":"Privacy","placement":"shared"},
|
|
4000
4000
|
{"key":"L0083","section":"footer","text":"Terms","placement":"shared"},
|
|
4001
4001
|
{"key":"L0084","section":"footer","text":"Contact","placement":"shared"},
|
|
4002
|
-
{"key":"L0085","section":"footer","text":"Builders' hall","placement":"shared","file":"modules/public-landing/public/index.html","line":
|
|
4002
|
+
{"key":"L0085","section":"footer","text":"Builders' hall","placement":"shared","file":"modules/public-landing/public/index.html","line":1066,"string_id":"90a128c97eae"}
|
|
4003
4003
|
]
|
|
4004
4004
|
},
|
|
4005
4005
|
{
|
|
@@ -4138,8 +4138,8 @@
|
|
|
4138
4138
|
"surface": "landing",
|
|
4139
4139
|
"title": "{{productName}} — projects",
|
|
4140
4140
|
"states_read": ["out-map","in-map","in-map-projects","in-map-profile","in-map-kbd","in-map-search","in-map-mine-on","in-table","in-table-by-builders","in-mine","in-manage","in-manage-address","in-manage-planet","in-manage-card","in-manage-look","in-manage-kind","in-manage-invite","in-manage-invite-handoff","in-manage-invite-guild","in-manage-app-live","in-manage-app-building","in-manage-app-failed","in-manage-app-retry","in-manage-app-offer","in-manage-app-connect","in-manage-snag","in-manage-gone","in-manage-missing","out-manage","in-new","in-new-named","in-new-ready","in-new-name-prefilled","in-new-demo","in-new-demo-used","in-new-checks-filled","in-new-checks-entity","in-new-row-code","in-new-row-address","in-new-row-team","in-new-row-extras","in-new-row-rewards","in-new-row-app","in-new-row-run","in-new-row-ship","in-new-look","in-new-look-custom","in-new-create-blocked","in-new-done","in-new-resume-offer","out-new","out-map-projects","card","card-noart","card-self","in-manage-demo","in-mine-dns-pending","in-manage-dns-pending","in-mine-empty","card-floor","card-backdrop","in-google","in-new-done-live","setup-just-created","setup-waiting-on-github","setup-installing","setup-stopped","setup-all-done","setup-cloud-hop-open"],
|
|
4141
|
-
"files_hash": "
|
|
4142
|
-
"reading_hash": "
|
|
4141
|
+
"files_hash": "7b2088fa77af5b51",
|
|
4142
|
+
"reading_hash": "b1b60799f9b3f5c8",
|
|
4143
4143
|
"counts": {"lines":687,"placed":239,"shared":23,"unplaced":425},
|
|
4144
4144
|
"omitted": {"data":135},
|
|
4145
4145
|
"notes": ["in-new-checks-filled: an action failed (page.selectOption: Error: Element is not a <select> element); read as it stood"],
|
|
@@ -4306,7 +4306,7 @@
|
|
|
4306
4306
|
{"key":"L0160","section":"Its kind","text":"This project has never said what kind it is. Saying so puts the word beside its name wherever it is listed; it changes nothing else.","placement":"unplaced","state":"in-manage"},
|
|
4307
4307
|
{"key":"L0161","section":"Its kind","text":"What the choice changes","placement":"placed","file":"modules/public-landing/public/projects.html","line":1341,"string_id":"ed394c66d49c","state":"in-manage"},
|
|
4308
4308
|
{"key":"L0162","section":"Its extras","text":"Its extras","placement":"placed","file":"modules/public-landing/public/projects.html","line":1358,"string_id":"218224e0007c","state":"in-manage"},
|
|
4309
|
-
{"key":"L0163","section":"Its extras","text":"Every project also starts with the same
|
|
4309
|
+
{"key":"L0163","section":"Its extras","text":"Every project also starts with the same 19 core parts — the platform itself, the way it tracks work, and the builders’ hall. They are always on, so they are not part of this choice.","placement":"unplaced","state":"in-manage"},
|
|
4310
4310
|
{"key":"L0164","section":"Its extras","text":"What an extra is — and what is always on","placement":"placed","file":"modules/public-landing/public/projects.html","line":1361,"string_id":"4bc11236f997","state":"in-manage"},
|
|
4311
4311
|
{"key":"L0165","section":"Its environment variables","text":"Its environment variables","placement":"placed","file":"modules/public-landing/public/projects.html","line":1373,"string_id":"7ad12a8a0b97","state":"in-manage"},
|
|
4312
4312
|
{"key":"L0166","section":"Its environment variables","text":"Why there is nowhere to type the value","placement":"placed","file":"modules/public-landing/public/projects.html","line":1376,"string_id":"101301013616","state":"in-manage"},
|
|
@@ -4706,7 +4706,7 @@
|
|
|
4706
4706
|
{"key":"L0560","section":"02How it’s run filled in from your answers","text":"1 suggested for a {…}","placement":"unplaced","state":"in-new-ready"},
|
|
4707
4707
|
{"key":"L0561","section":"02How it’s run filled in from your answers","text":"Extras for this project","placement":"placed","file":"modules/public-landing/public/projects.html","line":1890,"string_id":"7c8dcf228e70","state":"in-new-row-extras"},
|
|
4708
4708
|
{"key":"L0562","section":"02How it’s run filled in from your answers","text":"Search extras…","placement":"placed","file":"modules/public-landing/public/projects.html","line":1891,"string_id":"74f80d9e1abc","attr":"placeholder","state":"in-new-row-extras"},
|
|
4709
|
-
{"key":"L0563","section":"02How it’s run filled in from your answers","text":"Every project also has the same
|
|
4709
|
+
{"key":"L0563","section":"02How it’s run filled in from your answers","text":"Every project also has the same 19 core parts, always on: the platform, its work tracking and the builders’ hall.","placement":"unplaced","state":"in-new-row-extras"},
|
|
4710
4710
|
{"key":"L0564","section":"02How it’s run filled in from your answers","text":"Just the core for now","placement":"unplaced","state":"in-new"},
|
|
4711
4711
|
{"key":"L0565","section":"02How it’s run filled in from your answers","text":"Pick a kind and we suggest extras for it.","placement":"unplaced","state":"in-new"},
|
|
4712
4712
|
{"key":"L0566","section":"02How it’s run filled in from your answers","text":"Rewards","placement":"unplaced","state":"in-new"},
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @bongos/core — installed platform dependency (not your project's CLAUDE.md)
|
|
2
|
+
|
|
3
|
+
This file is a placeholder shipped inside the **@bongos/core** package. The core's own
|
|
4
|
+
internal agent notes are intentionally omitted from the published artifact so they cannot
|
|
5
|
+
load into your instance's context.
|
|
6
|
+
|
|
7
|
+
**It does not govern this repository.** Your own root `CLAUDE.md`, your `.claude/`
|
|
8
|
+
directory, and the live Bongos database are the source of truth for how work happens here
|
|
9
|
+
and who may do what.
|
|
10
|
+
|
|
11
|
+
You are seeing this only because an agent opened a file under `node_modules/@bongos/core/`.
|
|
12
|
+
Nothing in here needs to be read to use the platform — run `bongos help` for commands.
|
|
13
|
+
|
|
14
|
+
_To work ON the platform core itself, use the standalone @bongos/core source repository,
|
|
15
|
+
not this vendored copy._
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key": "app-host",
|
|
3
|
+
"title": "Where the app runs",
|
|
4
|
+
"description": "Shows, in a project's options menu, where the project's own app runs: no platform yet, or Render with its stage (creating, building, live, failed) and its address once live. Read from the hub with the project's own credentials, never from Render. The owner gets a Connect Render link to the hub's existing connect flow, and a failure says what went wrong and where to retry it; every other builder sees the state alone (task 1004571).",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"coreVersion": "^1.25.0",
|
|
7
|
+
"category": { "parent": "hosting" },
|
|
8
|
+
"default": true,
|
|
9
|
+
"author": "Cloud Bongos",
|
|
10
|
+
"origin": "Cloud Bongos core",
|
|
11
|
+
"license": "AGPL-3.0",
|
|
12
|
+
"maintainer": "Cloud Bongos maintainers",
|
|
13
|
+
"maintenance": { "status": "core-maintained" },
|
|
14
|
+
"contributes": {
|
|
15
|
+
"routes": ["app-host"],
|
|
16
|
+
"uiSections": ["app-host"]
|
|
17
|
+
},
|
|
18
|
+
"provides": [],
|
|
19
|
+
"consumes": []
|
|
20
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// modules/app-host/public/settings-widget.js — the options menu's "Where the app runs" panel
|
|
2
|
+
// (task 1004571).
|
|
3
|
+
//
|
|
4
|
+
// A module's panel in the one options menu (V3G.R04): registered through the settings-panel
|
|
5
|
+
// seam (window.OTB.contributeSettingsPanel), injected before settings.js only while this
|
|
6
|
+
// module is on. It draws GET /api/bongos/app-host and decides nothing: which actions a viewer
|
|
7
|
+
// gets is the server's answer (`owner`, `connect_url`), and every sentence about a failure is
|
|
8
|
+
// the setup's own (app-status.js oneSentence). It never offers a second Render form — Connect
|
|
9
|
+
// Render and Retry are links to the hub's own Manage panel, where that flow already lives.
|
|
10
|
+
(() => {
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const OTB = window.OTB || {};
|
|
14
|
+
if (typeof OTB.contributeSettingsPanel !== 'function') return;
|
|
15
|
+
if (typeof OTB.escapeHtml !== 'function') return;
|
|
16
|
+
const esc = OTB.escapeHtml;
|
|
17
|
+
|
|
18
|
+
// Only these shapes are ever put in an href: the app's onrender.com address, Render's own
|
|
19
|
+
// dashboard, and the hub page the server named. Anything else draws no link.
|
|
20
|
+
const APP_URL_RE = /^https:\/\/[a-z0-9-]{1,63}\.onrender\.com\/?$/;
|
|
21
|
+
const RENDER_RE = /^https:\/\/dashboard\.render\.com\//;
|
|
22
|
+
const HUB_RE = /^https?:\/\/[^\s"'<>]+$/i;
|
|
23
|
+
const safe = (url, re) => (typeof url === 'string' && re.test(url) ? url : null);
|
|
24
|
+
|
|
25
|
+
function pill(tone, word) {
|
|
26
|
+
return `<span class="status-pill status-pill--${tone}">${esc(word)}</span>`;
|
|
27
|
+
}
|
|
28
|
+
function row(label, desc, ctl) {
|
|
29
|
+
return `<div class="prow">
|
|
30
|
+
<div class="prow__main"><span class="prow__label">${label}</span>${desc ? `<span class="prow__desc">${desc}</span>` : ''}</div>
|
|
31
|
+
${ctl ? `<div class="prow__ctl">${ctl}</div>` : ''}
|
|
32
|
+
</div>`;
|
|
33
|
+
}
|
|
34
|
+
const hint = (text) => `<p class="panel-hint">${text}</p>`;
|
|
35
|
+
const where = (d) => (d.hub_host ? `this project's page on ${esc(d.hub_host)}` : "this project's page");
|
|
36
|
+
|
|
37
|
+
/** The owner's action, or the line that says who can act. */
|
|
38
|
+
function action(d, ownerLabel, othersLine) {
|
|
39
|
+
const href = safe(d.connect_url, HUB_RE);
|
|
40
|
+
if (d.owner && href) {
|
|
41
|
+
return `<div class="row-end"><a class="pbtn pbtn--save" href="${esc(href)}">${esc(ownerLabel)}</a></div>`
|
|
42
|
+
+ hint(`Opens ${where(d)}, where it is set up.`);
|
|
43
|
+
}
|
|
44
|
+
return hint(othersLine);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The stage, in the words a builder reads: what is happening and which step it is.
|
|
48
|
+
const STAGE = {
|
|
49
|
+
creating: ['info', 'creating', 'Render is creating the app’s service. Step 1 of 3.'],
|
|
50
|
+
building: ['info', 'building', 'Render is building the app. Step 2 of 3.'],
|
|
51
|
+
quiet: ['warn', 'no answer yet', 'Render hasn’t answered for over 20 minutes. It may have stopped the build.'],
|
|
52
|
+
live: ['ok', 'live', 'The app is live. Step 3 of 3.'],
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// The sandbox beside a Render app (task 1005289): a free copy on the owner's Render account
|
|
56
|
+
// that follows main. Drawn only when the server sent one, in the same words and pills.
|
|
57
|
+
const SANDBOX_STAGE = {
|
|
58
|
+
creating: ['info', 'creating', 'Render is creating the sandbox.'],
|
|
59
|
+
building: ['info', 'building', 'Render is building the sandbox.'],
|
|
60
|
+
quiet: ['warn', 'no answer yet', 'Render hasn’t answered about the sandbox for a while.'],
|
|
61
|
+
live: ['ok', 'live', 'The sandbox is live. It updates with every finished change.'],
|
|
62
|
+
};
|
|
63
|
+
function sandboxRow(sb) {
|
|
64
|
+
if (!sb || typeof sb !== 'object') return '';
|
|
65
|
+
if (sb.state === 'left') return row('Sandbox', esc(sb.error || 'The sandbox is still on the Render account.'), pill('neutral', 'left'));
|
|
66
|
+
if (sb.state === 'failed') return row('Sandbox', `Setting up the sandbox stopped. ${esc(sb.error || '')}`.trim(), pill('danger', 'failed'));
|
|
67
|
+
const own = Object.prototype.hasOwnProperty.call(SANDBOX_STAGE, sb.stage);
|
|
68
|
+
const [tone, word, line] = own ? SANDBOX_STAGE[sb.stage] : SANDBOX_STAGE.creating;
|
|
69
|
+
let desc = esc(sb.state === 'requested' && sb.message ? sb.message : line);
|
|
70
|
+
const url = safe(sb.url, APP_URL_RE);
|
|
71
|
+
if (sb.stage === 'live' && url) desc += ` <a href="${esc(url)}" target="_blank" rel="noopener">${esc(url.replace(/^https:\/\//, ''))}</a>`;
|
|
72
|
+
return row('Sandbox', desc, pill(tone, word));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The panel's body for one server answer. PURE (exported on window for the test). */
|
|
76
|
+
function render(d) {
|
|
77
|
+
if (!d || d.hub !== true) {
|
|
78
|
+
return hint('This project runs on its own server, so where its app runs is set up there, not here.');
|
|
79
|
+
}
|
|
80
|
+
if (!d.reachable) {
|
|
81
|
+
return row('Platform', `Couldn’t ask ${d.hub_host ? esc(d.hub_host) : 'the platform'} just now.`, pill('neutral', 'unknown'))
|
|
82
|
+
+ '<div class="row-end"><button type="button" class="pbtn" data-app-host-retry>Check again</button></div>';
|
|
83
|
+
}
|
|
84
|
+
if (!d.known) {
|
|
85
|
+
return hint(`This project’s app isn’t set up through ${d.hub_host ? esc(d.hub_host) : 'the platform'}, so there is nothing to show here.`);
|
|
86
|
+
}
|
|
87
|
+
const app = d.app;
|
|
88
|
+
if (!app || app.platform !== 'render' || app.state === 'disconnected') {
|
|
89
|
+
const was = app && app.state === 'disconnected' ? ' Render was disconnected.' : '';
|
|
90
|
+
return row('Platform', `No platform yet. The app isn’t running anywhere.${was}`, pill('neutral', 'no platform'))
|
|
91
|
+
+ action(d, 'Connect Render', 'The project’s owner can connect Render to run the app.');
|
|
92
|
+
}
|
|
93
|
+
if (app.state === 'failed') {
|
|
94
|
+
const why = app.error ? esc(app.error) : 'The setup stopped without saying why.';
|
|
95
|
+
return row('Render', `Setting the app up on Render stopped. ${why}`, pill('danger', 'failed'))
|
|
96
|
+
+ action(d, 'Retry on the project page', `The project’s owner can retry it from ${where(d)}.`)
|
|
97
|
+
+ sandboxRow(d.sandbox);
|
|
98
|
+
}
|
|
99
|
+
const [tone, word, line] = Object.prototype.hasOwnProperty.call(STAGE, app.stage) ? STAGE[app.stage] : STAGE.creating;
|
|
100
|
+
let desc = esc(line);
|
|
101
|
+
if (app.waiting && app.stage === 'creating') desc = 'Waiting to start. The setup begins shortly. Step 1 of 3.';
|
|
102
|
+
const url = safe(app.url, APP_URL_RE);
|
|
103
|
+
if (app.stage === 'live' && url) desc += ` <a href="${esc(url)}" target="_blank" rel="noopener">${esc(url.replace(/^https:\/\//, ''))}</a>`;
|
|
104
|
+
let out = row('Render', desc, pill(tone, word));
|
|
105
|
+
const links = app.links || {};
|
|
106
|
+
const deploys = safe(links.deploys, RENDER_RE);
|
|
107
|
+
const service = safe(links.service, RENDER_RE);
|
|
108
|
+
if (app.stage === 'quiet' && deploys) {
|
|
109
|
+
out += `<div class="row-end"><a class="pbtn" href="${esc(deploys)}" target="_blank" rel="noopener">Open Render’s deploy history</a></div>`;
|
|
110
|
+
} else if (service) {
|
|
111
|
+
out += `<div class="row-end"><a class="pbtn" href="${esc(service)}" target="_blank" rel="noopener">Open in Render</a></div>`;
|
|
112
|
+
}
|
|
113
|
+
return out + sandboxRow(d.sandbox);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function load(el) {
|
|
117
|
+
el.setAttribute('aria-busy', 'true');
|
|
118
|
+
el.innerHTML = hint('Checking where the app runs…');
|
|
119
|
+
let d = null;
|
|
120
|
+
try {
|
|
121
|
+
const res = await fetch('/api/bongos/app-host', { credentials: 'same-origin', headers: { Accept: 'application/json' } });
|
|
122
|
+
d = res.ok ? await res.json() : null;
|
|
123
|
+
} catch { d = null; }
|
|
124
|
+
el.innerHTML = d ? render(d) : row('Platform', 'Couldn’t load this just now.', pill('neutral', 'unknown'))
|
|
125
|
+
+ '<div class="row-end"><button type="button" class="pbtn" data-app-host-retry>Check again</button></div>';
|
|
126
|
+
el.removeAttribute('aria-busy');
|
|
127
|
+
const again = el.querySelector('[data-app-host-retry]');
|
|
128
|
+
if (again) again.addEventListener('click', () => { load(el).then(() => { const b = el.querySelector('.pbtn, a'); if (b) b.focus(); }); });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
OTB.contributeSettingsPanel({
|
|
132
|
+
id: 'app-host',
|
|
133
|
+
title: 'Where the app runs',
|
|
134
|
+
order: 10,
|
|
135
|
+
mount(el) {
|
|
136
|
+
el.setAttribute('aria-live', 'polite');
|
|
137
|
+
el.insertAdjacentHTML('beforebegin', '<p class="scroll__lede">The app is what your users open. This hall is hosted for you; the app runs on a platform the project’s owner connects.</p>');
|
|
138
|
+
load(el);
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
window.OTBAppHost = { render };
|
|
143
|
+
})();
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// modules/app-host/routes/app-host.js — GET /app-host: where this project's app runs, for
|
|
2
|
+
// the options menu's "Where the app runs" panel (task 1004571).
|
|
3
|
+
//
|
|
4
|
+
// We host every project's hall; its app runs on the owner's Render account (ADR 0345), and
|
|
5
|
+
// the setup's state is the hub's provisioning row. So this asks the hub through the kernel's
|
|
6
|
+
// narrow port (api.readAppStatusFromHub — the project's own credentials, no argument), and
|
|
7
|
+
// passes on modules/provisioning/app-status.js's shape. It never calls Render.
|
|
8
|
+
//
|
|
9
|
+
// WHO SEES WHAT IS DECIDED HERE, NOT IN THE PAGE. Every signed-in builder sees the state:
|
|
10
|
+
// the stage, the address once live, and a failure in the setup's own words. Only a builder
|
|
11
|
+
// holding `core.pin.move` — the owner's hard gate over what runs for users, the atom the
|
|
12
|
+
// deploy door and Software update read — is handed the owner's actions: the Connect Render
|
|
13
|
+
// link, the Render dashboard links, and where to retry. The link only names the hub page;
|
|
14
|
+
// the hub's own Manage panel is still the door, and it opens only for the project's owner.
|
|
15
|
+
//
|
|
16
|
+
// TOLERANT OF NEW FIELDS. The hub's shape grows (a sandbox address is coming, task
|
|
17
|
+
// 1005289), so the reply passes the status through and only REMOVES the owner-only fields
|
|
18
|
+
// for everyone else, rather than rebuilding it from a list that would silently drop them.
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
const express = require('express');
|
|
22
|
+
const api = require('../../../src/module-api');
|
|
23
|
+
|
|
24
|
+
const log = api.logger('app-host');
|
|
25
|
+
|
|
26
|
+
// What only the owner is handed from the hub's status: the Render dashboard links, the
|
|
27
|
+
// workspace id, and the answers a retry re-sends (the retry itself happens on the hub).
|
|
28
|
+
const OWNER_ONLY = Object.freeze(['links', 'workspace', 'retry', 'can_add']);
|
|
29
|
+
// The hub page's section for the app (modules/public-landing/public/projects.html #mAppCard).
|
|
30
|
+
const APP_SECTION = '#mAppCard';
|
|
31
|
+
|
|
32
|
+
/** Does this viewer hold the owner's atom? Fail-closed: authority that cannot be read is no. */
|
|
33
|
+
async function holdsOwnerAtom(req) {
|
|
34
|
+
try {
|
|
35
|
+
const government = api.resolveOptional('government');
|
|
36
|
+
if (!government || typeof government.resolveBuilderPermissions !== 'function') return false;
|
|
37
|
+
const held = (await government.resolveBuilderPermissions(req.builder && req.builder.id)) || [];
|
|
38
|
+
return held.includes('core.pin.move');
|
|
39
|
+
} catch { return false; }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The reply for one viewer, from the hub read. PURE — the route's whole decision.
|
|
44
|
+
* read: { hub: false } | { hub: true, reachable, known?, app?, sandbox?, manage? }
|
|
45
|
+
* The sandbox (render-sandbox.js's shape, task 1005289) is filtered the same way, and left
|
|
46
|
+
* out while there is none: adding one is the owner's, on the hub's page.
|
|
47
|
+
*/
|
|
48
|
+
function viewFor(read, { owner = false } = {}) {
|
|
49
|
+
const r = read && typeof read === 'object' ? read : { hub: false };
|
|
50
|
+
if (r.hub !== true) return { hub: false, reachable: false, known: false, app: null, sandbox: null, owner: false, connect_url: null, hub_host: null };
|
|
51
|
+
const manage = r.manage && typeof r.manage.manage_url === 'string' ? r.manage : null;
|
|
52
|
+
let app = r.app && typeof r.app === 'object' ? { ...r.app } : null;
|
|
53
|
+
if (app && !owner) for (const k of OWNER_ONLY) delete app[k];
|
|
54
|
+
if (app && owner && 'retry' in app) delete app.retry; // the retry form is the hub's; the hall only links to it
|
|
55
|
+
let sandbox = r.sandbox && typeof r.sandbox === 'object' && r.sandbox.state !== 'none' ? { ...r.sandbox } : null;
|
|
56
|
+
if (sandbox) for (const k of OWNER_ONLY) if (!owner || k === 'retry' || k === 'can_add') delete sandbox[k];
|
|
57
|
+
return {
|
|
58
|
+
hub: true,
|
|
59
|
+
reachable: r.reachable === true,
|
|
60
|
+
known: r.reachable === true && r.known === true,
|
|
61
|
+
app,
|
|
62
|
+
sandbox: app ? sandbox : null,
|
|
63
|
+
owner: !!owner,
|
|
64
|
+
connect_url: owner && manage ? manage.manage_url + APP_SECTION : null,
|
|
65
|
+
hub_host: manage ? manage.hub_host || null : null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = function buildAppHostRouter({ readHub = () => api.readAppStatusFromHub(), isOwner = holdsOwnerAtom } = {}) {
|
|
70
|
+
const router = express.Router();
|
|
71
|
+
|
|
72
|
+
// GET /app-host — rank: any signed-in builder; owner-only parts gated on core.pin.move.
|
|
73
|
+
router.get('/app-host', api.requireBuilder, async (req, res) => {
|
|
74
|
+
try {
|
|
75
|
+
const [read, owner] = await Promise.all([readHub(), isOwner(req)]);
|
|
76
|
+
res.set('Cache-Control', 'no-store');
|
|
77
|
+
res.json({ ok: true, ...viewFor(read, { owner: owner === true }) });
|
|
78
|
+
} catch (err) {
|
|
79
|
+
log.error('[app-host] GET /app-host', err && err.message);
|
|
80
|
+
res.fail('app_host_failed', { status: 500, message: 'Could not read where the app runs.' });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return router;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
module.exports.viewFor = viewFor;
|
|
88
|
+
module.exports.OWNER_ONLY = OWNER_ONLY;
|