@bongos/core 1.19.995 → 1.19.996

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 CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.995",
6
- "core_contract": "1.19.995",
7
- "source_commit": "5289c5d78570e086cd6f6d7ee4c154883c7adb78",
5
+ "core_version": "1.19.996",
6
+ "core_contract": "1.19.996",
7
+ "source_commit": "5929da0385a4022562ebd43a5a71d81400e45836",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-23T23:25:13.365Z",
9
+ "built_at": "2026-09-23T23:40:05.075Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 519,
12
+ "docs_redacted": 520,
13
13
  "agent_docs_stubbed": 26,
14
14
  "functional_verbatim": 2405,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2950,
20
- "tree_sha256": "ca075a6b55f5c4d672bea732dad07148b251ceceabcea4a3823702e708fc28c7",
19
+ "file_count": 2951,
20
+ "tree_sha256": "cd26f1916edf3136e53591dc18c37ed45254dd805880bf4b25bc1af1c59baf93",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2717,7 +2717,7 @@
2717
2717
  {
2718
2718
  "path": "docs/module-api-changelog.md",
2719
2719
  "mode": "0000644",
2720
- "sha256": "42c93e21972b2c4cf9e69574fbd72957a80d03ce51f5a86e6d28579981de11df"
2720
+ "sha256": "950ea34b2bb315e54fc02aa22753b3370ee009ab06727238002aa3a54e78782e"
2721
2721
  },
2722
2722
  {
2723
2723
  "path": "docs/modules-contract.md",
@@ -2924,6 +2924,11 @@
2924
2924
  "mode": "0000644",
2925
2925
  "sha256": "f6d2bb1da53f03f54080b8e0aec9f63390d3343c32917b64225ac47ae4ba7b42"
2926
2926
  },
2927
+ {
2928
+ "path": "docs/recipes/render-pilot.md",
2929
+ "mode": "0000644",
2930
+ "sha256": "7b5f391285931a5f5e1bd31683702d534e9876d55ce5a0794e7d8eeec52fc2f3"
2931
+ },
2927
2932
  {
2928
2933
  "path": "docs/recipes/reranking-a-goals-board.md",
2929
2934
  "mode": "0000644",
@@ -8182,12 +8187,12 @@
8182
8187
  {
8183
8188
  "path": "package-lock.json",
8184
8189
  "mode": "0000644",
8185
- "sha256": "1b91fb64b2d18219b4433b0ef6589de4488e9d7d78db9a1af45268a1f2a51944"
8190
+ "sha256": "6d4291f9e503ac170998451d6607d15f831d39cd43aaa2443ada021e10386f13"
8186
8191
  },
8187
8192
  {
8188
8193
  "path": "package.json",
8189
8194
  "mode": "0000644",
8190
- "sha256": "6b994df4ca85e51d032ee640a4aa4b6dfb57d82581a840eb5de5f05a0b831ee3"
8195
+ "sha256": "50946900cdbd241bfe7a8ac94d4b50b65a9adb622f2debdd2048354a2ead38e4"
8191
8196
  },
8192
8197
  {
8193
8198
  "path": "public-docs/index.html",
@@ -10232,7 +10237,7 @@
10232
10237
  {
10233
10238
  "path": "src/module-api.js",
10234
10239
  "mode": "0000644",
10235
- "sha256": "34e569846f695b7f3b69061619a97ab92cda5a4262a67f6c016f31edaf984714"
10240
+ "sha256": "899926ec43a4f0087125deada1bf430aa5f34bd1b3f32ab65ff2ffea981431a3"
10236
10241
  },
10237
10242
  {
10238
10243
  "path": "src/module-loader/catalog.js",
@@ -2464,5 +2464,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2464
2464
  landed since 1.19.993 with no explicit bump. run 35929622479. (task 1002620)
2465
2465
  1.19.995 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2466
2466
  landed since 1.19.994 with no explicit bump. run 35933457545. (task 1002620)
2467
+ 1.19.996 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2468
+ landed since 1.19.995 with no explicit bump. run 35934673169. (task 1002620)
2467
2469
  ---------------------------------------------------------------------------
2468
2470
  ```
@@ -0,0 +1,218 @@
1
+ # Recipe — the Render pilot, on a throwaway `mercury` clone
2
+
3
+ The executable half of [task 1004142](https://cloudbongos.com/builders#/task/1004142): stand one Bongos instance up on Render, end to end, and answer the questions [task 1004183](https://cloudbongos.com/builders#/task/1004183) (the standup leg) will be written against. Governed by [ADR 0327](../adr/0327-a-cloud-host-runs-on-the-owners-account-and-the-key-is-borrowed.md); platform choice from [ADR 0323](../adr/0323-hosting-is-three-shapes-and-we-are-not-the-landlord.md).
4
+
5
+ **Who runs this.** Whoever holds the Render key — under ADR 0327 that is the *project owner*, and for the pilot it is the platform owner. An agent session cannot run it unless someone has put a key in front of it, and a key must never be pasted into a chat.
6
+
7
+ **The API shape below was read from Render's own reference on 2026-09-23** (`api-docs.render.com`), not inferred. Where this recipe and a live response disagree, the response wins and this file is the bug.
8
+
9
+ ---
10
+
11
+ ## 0. Before you start — three things worth knowing
12
+
13
+ **The pilot costs money, and the free tier cannot prove it.** Done-when clause 4 is "its database is backed up by Render rather than by our timer". Render's **free Postgres has no backups of any kind** — no logical backups, no PITR. Only paid databases are continually backed up (3 days of recovery window on Hobby, 7 on Pro). So the pilot must run a **paid** Postgres or clause 4 is unprovable. Budget `0.1c-256mb` ($6/mo) + `0.5c-512mb` web ($7/mo), prorated for the hours the pilot is up, and tear it down when finished.
14
+
15
+ **The key is account-wide, not workspace-wide.** `GET /owners` returns every workspace the key's *user* can reach, including other people's teams. This is the finding that produced ADR 0327, and step 1 exists to confirm it on live responses before anything is created.
16
+
17
+ **Do not touch live `mercury`.** Row 31 is a real owner's project, serving from our box today. Clone its *repo* to a scratch repo under an account we control, and stand the clone up under a scratch slug. Nothing in this recipe writes to row 31, to `willHermesLines/mercury_bongos`, or to that owner's Render account.
18
+
19
+ Set up once:
20
+
21
+ ```bash
22
+ export RENDER_TOKEN=... # in your shell, not in a file, not in chat
23
+ export R="curl -sS -H \"Authorization: Bearer $RENDER_TOKEN\" -H 'Content-Type: application/json'"
24
+ ```
25
+
26
+ Base URL is `https://api.render.com/v1`; auth is `Authorization: Bearer <key>`.
27
+
28
+ ---
29
+
30
+ ## 1. The `ownerId` guard — confirm the finding BEFORE creating anything
31
+
32
+ This is the pilot's most important output, because every call the standup leg later writes depends on it.
33
+
34
+ ```bash
35
+ curl -sS -H "Authorization: Bearer $RENDER_TOKEN" https://api.render.com/v1/owners | jq
36
+ ```
37
+
38
+ Each element is `{ owner: { id, name, email, type }, cursor }`, where `type` is `user` or `team`.
39
+
40
+ **Record:** how many workspaces come back, which are not ours, and their ids. Then pick the Bongos workspace's `id` and pin it:
41
+
42
+ ```bash
43
+ export RENDER_OWNER_ID=...
44
+ ```
45
+
46
+ **Then prove the hazard rather than assuming it.** List a resource *without* `ownerId` and check whether another workspace's resources appear:
47
+
48
+ ```bash
49
+ curl -sS -H "Authorization: Bearer $RENDER_TOKEN" 'https://api.render.com/v1/services?limit=100' \
50
+ | jq '[.[].service | {id, name, ownerId}] | group_by(.ownerId) | map({ownerId: .[0].ownerId, n: length})'
51
+ ```
52
+
53
+ If more than one `ownerId` comes back from a key that was only ever meant for one workspace, the finding is confirmed and the guard is mandatory. **Record the actual output either way** — a negative result is just as useful and would narrow ADR 0327's §"required guard".
54
+
55
+ **The rule the standup leg must implement, whatever this shows:**
56
+
57
+ - Send an explicit `ownerId` on every call. It is *required* on `POST /services` and `POST /postgres`, and it is *optional* on the list calls — which is exactly where the hazard lives.
58
+ - Assert `ownerId` on the **response**, not the request. A request you got right tells you nothing about a response that came from elsewhere.
59
+ - Treat missing or mismatched as a hard error. Never default it, and never derive the workspace by taking the first element of `/owners`.
60
+
61
+ ---
62
+
63
+ ## 2. Clone the repo
64
+
65
+ `mercury`'s instance row carries `target_ref=willHermesLines/mercury_bongos` and `onboard_mode=adopt`. Clone it to a scratch repo you own — this is the pilot's subject and it is disposable.
66
+
67
+ ```bash
68
+ git clone https://github.com/willHermesLines/mercury_bongos /tmp/mercury-clone
69
+ cd /tmp/mercury-clone && git remote remove origin
70
+ gh repo create <you>/render-pilot --private --source=. --push
71
+ ```
72
+
73
+ **Record:** whether the repo is public or private, and under which account. That feeds the open question in step 5.
74
+
75
+ ---
76
+
77
+ ## 3. Create the Postgres
78
+
79
+ ```bash
80
+ curl -sS -X POST -H "Authorization: Bearer $RENDER_TOKEN" -H 'Content-Type: application/json' \
81
+ https://api.render.com/v1/postgres -d '{
82
+ "name": "render-pilot-db",
83
+ "ownerId": "'"$RENDER_OWNER_ID"'",
84
+ "plan": "basic_256mb",
85
+ "region": "virginia",
86
+ "version": "16"
87
+ }' | jq
88
+ ```
89
+
90
+ `plan`, `ownerId`, `name` and `version` are all required. `databaseName` and `databaseUser` are generated if omitted. **`plan` must not be `free`** — see §0. Region `virginia` is the closest US region to the current droplet (`PROVISION_REGION=nyc3`).
91
+
92
+ Then read the connection string:
93
+
94
+ ```bash
95
+ curl -sS -H "Authorization: Bearer $RENDER_TOKEN" \
96
+ https://api.render.com/v1/postgres/<postgresId>/connection-info | jq
97
+ ```
98
+
99
+ Returns `password`, `internalConnectionString`, `externalConnectionString`, `psqlCommand`, and optionally the pooled variants. **Assert the `ownerId` on the create response before going further.**
100
+
101
+ ---
102
+
103
+ ## 4. Create the web service
104
+
105
+ Bongos reads `DATABASE_URL` first and falls back to the `PG*` family (`src/bongos/pool.js:56`), so Render's connection string wires in directly — **none of the `PGHOST`/`PGDATABASE`/`PGUSER`/`PGPASSWORD` lines `webEnvBody` writes on the box are needed here.** That is the single biggest simplification Render buys, and it is worth stating in the standup leg's comments.
106
+
107
+ The env prefix is **`BONGOS`** (`config/branding.neutral.json` → `envPrefix`). The variables below are the Render translation of `webEnvBody` in `scripts/gds/provision-units.js:192` — read that function, not this list, if the two ever disagree.
108
+
109
+ ```bash
110
+ curl -sS -X POST -H "Authorization: Bearer $RENDER_TOKEN" -H 'Content-Type: application/json' \
111
+ https://api.render.com/v1/services -d '{
112
+ "type": "web_service",
113
+ "name": "render-pilot",
114
+ "ownerId": "'"$RENDER_OWNER_ID"'",
115
+ "repo": "https://github.com/<you>/render-pilot",
116
+ "branch": "main",
117
+ "autoDeploy": "yes",
118
+ "serviceDetails": {
119
+ "runtime": "node",
120
+ "plan": "0.5c-512mb",
121
+ "region": "virginia",
122
+ "healthCheckPath": "/healthz",
123
+ "envSpecificDetails": {
124
+ "buildCommand": "npm ci",
125
+ "startCommand": "npm start"
126
+ }
127
+ },
128
+ "envVars": [
129
+ { "key": "DATABASE_URL", "value": "<internalConnectionString>" },
130
+ { "key": "BONGOS_GITHUB_CLIENT_ID", "value": "" },
131
+ { "key": "BONGOS_GITHUB_CLIENT_SECRET", "value": "" },
132
+ { "key": "BONGOS_FIRST_ADMIN", "value": "<your-github-login>" },
133
+ { "key": "BONGOS_PUBLIC_ORIGIN", "value": "https://render-pilot.onrender.com" },
134
+ { "key": "BONGOS_BUILDERS_ORIGIN", "value": "https://render-pilot.onrender.com" },
135
+ { "key": "BONGOS_STATUS_ORIGIN", "value": "https://render-pilot.onrender.com" },
136
+ { "key": "BONGOS_OAUTH_ORIGIN", "value": "https://render-pilot.onrender.com" }
137
+ ]
138
+ }' | jq
139
+ ```
140
+
141
+ Notes that matter:
142
+
143
+ - **`PORT` is not set by us.** Render injects it; `webEnvBody` writes it because the box allocates ports itself. One more line the standup leg drops.
144
+ - **The four origin overrides are load-bearing, not cosmetic.** Without them `src/branding.js` stays on neutral localhost and the hall never loads (task 1972). They must be the Render hostname, and they must all four be the same host — a single-host instance has no separate `builders.`/`status.` subdomain.
145
+ - **`BONGOS_FIRST_ADMIN` is what seats you as Archon** on first sign-in. Omit it and the instance has no owner and you can never claim it (the 2026-07-07 `demo` regression).
146
+ - **OAuth creds start blank** and are filled after the app exists — see step 5.
147
+ - `PGPOOL_MAX` is read bare and still applies. On `basic_256mb` the connection ceiling is low; if the app struggles to connect, set it small (the box uses `PROVISION_INSTANCE_PGPOOL_MAX`).
148
+ - Do **not** send a `secretFiles` entry for the GitHub App PEM until you know whether the App path is in scope for the pilot; blank OAuth is enough to prove boot.
149
+
150
+ ---
151
+
152
+ ## 5. Sign-in, and the open question the pilot exists to answer
153
+
154
+ Create a GitHub OAuth app (or App) whose callback is the Render hostname, then set `BONGOS_GITHUB_CLIENT_ID` / `_SECRET` via `PATCH /services/{id}/env-vars/{key}` and redeploy.
155
+
156
+ **The question ADR 0327 left for this pilot:** can Render's GitHub App reach a repo under a **personal** account rather than an org, and what does that mean for a project whose repo we do not own? Record:
157
+
158
+ - Which GitHub account/org the pilot repo sits under, and whether Render's GitHub App installed onto it without friction.
159
+ - Whether a *private* repo under someone else's personal account is reachable at all.
160
+ - What the owner has to click, since under ADR 0327 the repo and the Render account are both theirs.
161
+
162
+ This is the answer that decides whether `cloud-host` standup is one API sequence or a sequence plus a human step — and therefore how much friction `cloud-host` actually removes over `byo-host`.
163
+
164
+ ---
165
+
166
+ ## 6. Migrations
167
+
168
+ Run `migrate.sh` against the Render database. Prefer a Render **job** or the service's own shell over your laptop, so the run happens from inside Render's network on the `internalConnectionString`; the `externalConnectionString` works from outside but is not what production will use.
169
+
170
+ Then confirm no schema lag:
171
+
172
+ ```bash
173
+ curl -sS https://render-pilot.onrender.com/version | jq
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 7. Custom domain (optional for the pilot, required for the model)
179
+
180
+ ADR 0323 keeps **Cloudflare DNS as the front door** and drops the Caddy site block, because Render terminates TLS. Prove the chain end to end at least once:
181
+
182
+ ```bash
183
+ curl -sS -X POST -H "Authorization: Bearer $RENDER_TOKEN" -H 'Content-Type: application/json' \
184
+ https://api.render.com/v1/services/<serviceId>/custom-domains -d '{"name": "render-pilot.cloudbongos.com"}' | jq
185
+ ```
186
+
187
+ Then point the Cloudflare record at Render and confirm the response header is **no longer `via: 1.1 Caddy`** — that header is precisely how we established the live `mercury` instance is still on our box, and its absence is the cleanest proof the front door moved.
188
+
189
+ ---
190
+
191
+ ## 8. Capture the evidence — the five done-when clauses
192
+
193
+ Record each in the session log, with the actual output, not a claim that it worked:
194
+
195
+ | # | Clause | Evidence |
196
+ |---|---|---|
197
+ | 1 | Boots | `GET /healthz` → 200, and the header does **not** say `via: 1.1 Caddy` |
198
+ | 2 | Signs in | the OAuth round trip completes and seats you as Archon |
199
+ | 3 | Migrations run | `migrate.sh` completes; `/version` reports no schema lag |
200
+ | 4 | **Render backs up the DB** | a backup exists in Render's dashboard/API that we did not create — this is the clause that retires `provision-units.js`'s backup service + timer, and it needs a **paid** database |
201
+ | 5 | GitHub App reach | written answer to §5 |
202
+
203
+ Plus the three the standup leg is written from: the **exact call sequence** above with real request/response shapes, the **`ownerId` guard's live behaviour** from §1, and whether the **default plan sizes** held or mercury's larger choice was right.
204
+
205
+ ---
206
+
207
+ ## 9. Tear the clone down
208
+
209
+ The pilot is disposable and it is costing money. Delete the web service, delete the Postgres, delete the scratch repo, and remove the Cloudflare record if you made one.
210
+
211
+ **Note the asymmetry deliberately:** you are deleting resources in *your own* account, by hand. ADR 0327 decision 3 says the platform must never hold the ability to destroy infrastructure it does not own — `provision-teardown.js` retargets to *forgetting*, not to a Render delete call ([task 1004183](https://cloudbongos.com/builders#/task/1004183)). The fact that this step is manual is the design working, not a gap in it.
212
+
213
+ ---
214
+
215
+ ## Sources
216
+
217
+ - [Render API reference](https://api-docs.render.com/reference/introduction) — endpoints, required fields, plan and region enums, read 2026-09-23
218
+ - [Render Postgres Recovery and Backups](https://render.com/docs/postgresql-backups) — free plans have no backups; paid plans get PITR with 3-day (Hobby) / 7-day (Pro) windows
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.995",
3
+ "version": "1.19.996",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.995",
9
+ "version": "1.19.996",
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.995",
3
+ "version": "1.19.996",
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",
package/src/module-api.js CHANGED
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
71
71
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
72
72
  // the entry to that file. Look for a version's history there, not here.
73
73
  // ---------------------------------------------------------------------------
74
- const CORE_VERSION = '1.19.995'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.996'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
75
75
 
76
76
  // A namespaced logger so a module's log lines are attributable + consistent.
77
77
  // Usage: const log = api.logger('dev-box'); log.info('mounted');