@bongos/core 1.19.206 → 1.19.208

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.206",
6
- "core_contract": "1.19.206",
7
- "source_commit": "6ef49e744b96d37db9a338979fb85bb56fb6aa6f",
5
+ "core_version": "1.19.208",
6
+ "core_contract": "1.19.208",
7
+ "source_commit": "6dabd2e84af8785ac779f8a6801b951d80ecad3b",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-17T20:15:14.217Z",
9
+ "built_at": "2026-08-17T20:55:34.065Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 310,
13
13
  "agent_docs_stubbed": 21,
14
- "functional_verbatim": 1296,
14
+ "functional_verbatim": 1299,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1627,
20
- "tree_sha256": "f7017bc51e10af4dd65ab8df53ce22c7a0e611c7fb948ee6598ce8c4f7831a6a",
19
+ "file_count": 1630,
20
+ "tree_sha256": "63df68d9f034ba54b42011a4bfc310a811d2c53cb550a586bf40d5d35228a258",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -187,7 +187,7 @@
187
187
  {
188
188
  "path": ".claude/skills/new-project/SKILL.md",
189
189
  "mode": "0000644",
190
- "sha256": "9b36d441850c335fa634d892088e4c15a2a87acaa9e52808b74a8b2e6e9af39f"
190
+ "sha256": "1d6f60e8fa3cbf06cc5f8901ccf21fd8cac8050f81b3296039b659d700eba242"
191
191
  },
192
192
  {
193
193
  "path": ".claude/skills/otb-character-review/SKILL.md",
@@ -347,12 +347,12 @@
347
347
  {
348
348
  "path": "clients/bongos-client/README.md",
349
349
  "mode": "0000644",
350
- "sha256": "4801db32c6f4ba6220bce8e664be063f8d8483bc22a57df08205b0fc36788b8b"
350
+ "sha256": "2755203dec4a1450c5950c39a767bc093d1d1227f952193001cdfa94205e995f"
351
351
  },
352
352
  {
353
353
  "path": "clients/bongos-client/bongos-client.global.js",
354
354
  "mode": "0000644",
355
- "sha256": "c3ff3f8c529ac99fe6f968bd3ec110bb6a03c5788caf4dbbab5f59147af28b4c"
355
+ "sha256": "7b4e5ecf6c6d12a3c9e603a0f5b4bd28ba8cd991399ed8941181b6aeae53772d"
356
356
  },
357
357
  {
358
358
  "path": "clients/bongos-client/examples/hello-world.mjs",
@@ -362,17 +362,17 @@
362
362
  {
363
363
  "path": "clients/bongos-client/index.cjs",
364
364
  "mode": "0000644",
365
- "sha256": "9de16e178984c7c9ac9c20de3de8ca074bb904423b20a8459a93ce838c1507ea"
365
+ "sha256": "a92355ef21073634500f6806f1e495c955a0b67e889cf07264ed8d1169b119be"
366
366
  },
367
367
  {
368
368
  "path": "clients/bongos-client/index.d.ts",
369
369
  "mode": "0000644",
370
- "sha256": "38ef88079d260b67161e680ea77fa6ddecb3cc74a1452796cbe28c0e3601c052"
370
+ "sha256": "8fe97a3daefdceb9bf40a15a19dffb81fb6387c0acbe20041e58e63b24e80dd1"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/index.mjs",
374
374
  "mode": "0000644",
375
- "sha256": "d5f8ca20a0826b3258c909d870da54ebd4c3e757c8c35a306c1fa7a72b8292c4"
375
+ "sha256": "adb2a36a9598c543adbf7c8011f36585f7c394bac7f4961718359ee7a29cb1dd"
376
376
  },
377
377
  {
378
378
  "path": "clients/bongos-client/package.json",
@@ -1367,12 +1367,12 @@
1367
1367
  {
1368
1368
  "path": "docs/api-reference.md",
1369
1369
  "mode": "0000644",
1370
- "sha256": "32c6c5fe14cf8684d353f0c73cde4b09d84ba61eabcb13e75c11bd5b7f9be2b7"
1370
+ "sha256": "52554cf7c8e5355c59594c872f30975581eb6c1b9a5bcb63efa1a1a19f2d3877"
1371
1371
  },
1372
1372
  {
1373
1373
  "path": "docs/api/openapi.json",
1374
1374
  "mode": "0000644",
1375
- "sha256": "c11ec9dcb0726382e15bb7fc9e74086037ed158256ef16b5efcc81fe2db2d078"
1375
+ "sha256": "825af2c499836301a34cff79192e41556cc863fe9a5378d9e5134c862769c2fa"
1376
1376
  },
1377
1377
  {
1378
1378
  "path": "docs/architecture.md",
@@ -2682,7 +2682,7 @@
2682
2682
  {
2683
2683
  "path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
2684
2684
  "mode": "0000644",
2685
- "sha256": "9de16e178984c7c9ac9c20de3de8ca074bb904423b20a8459a93ce838c1507ea"
2685
+ "sha256": "a92355ef21073634500f6806f1e495c955a0b67e889cf07264ed8d1169b119be"
2686
2686
  },
2687
2687
  {
2688
2688
  "path": "modules/dev-box/app/test/unit.mjs",
@@ -3949,6 +3949,11 @@
3949
3949
  "mode": "0000644",
3950
3950
  "sha256": "8dc04a18ad77563a2bd73029bf13cab03fb5dadd1b62850fddbde475257e6a76"
3951
3951
  },
3952
+ {
3953
+ "path": "modules/provisioning/migrations/provisioning_009_project_settings.sql",
3954
+ "mode": "0000644",
3955
+ "sha256": "de17cfb74f8684044abfb03e56698f91fa5aa813608f3a19d2ddf81d113e897e"
3956
+ },
3952
3957
  {
3953
3958
  "path": "modules/provisioning/module.json",
3954
3959
  "mode": "0000644",
@@ -3957,7 +3962,7 @@
3957
3962
  {
3958
3963
  "path": "modules/provisioning/onboard-plan.js",
3959
3964
  "mode": "0000644",
3960
- "sha256": "de7927d2a3c1aac0d40ec5b1ac6c2e98e87cb593c4d3d2bd6ddfe3696371bff6"
3965
+ "sha256": "4aae27c3c56de480e9cc4f19405572a96c6bf0246fdd859adceae629c7a71842"
3961
3966
  },
3962
3967
  {
3963
3968
  "path": "modules/provisioning/pollers/liveness-sweep.js",
@@ -3967,7 +3972,7 @@
3967
3972
  {
3968
3973
  "path": "modules/provisioning/provisioning.js",
3969
3974
  "mode": "0000644",
3970
- "sha256": "e43977d0c5458de4fde91e6ccb784b112187545fdf03ceed2c352b605686a57e"
3975
+ "sha256": "b9d4ee116eb4b213b084408868f727a4587876faa5fae78f4d2f64cb2fe12231"
3971
3976
  },
3972
3977
  {
3973
3978
  "path": "modules/provisioning/rate-limit.js",
@@ -3977,7 +3982,7 @@
3977
3982
  {
3978
3983
  "path": "modules/provisioning/routes/provisioning.js",
3979
3984
  "mode": "0000644",
3980
- "sha256": "f7cf016e10587302437f5d8ab7b01d8b1be6694e05b9e8c47a6ccb2cdfda8ac4"
3985
+ "sha256": "78c89017e17dfba57ade2330fce293e6422aab316e9311f8215ff3eb9fdc3fe5"
3981
3986
  },
3982
3987
  {
3983
3988
  "path": "modules/provisioning/tests/liveness.mjs",
@@ -3987,7 +3992,7 @@
3987
3992
  {
3988
3993
  "path": "modules/provisioning/tests/provisioning.mjs",
3989
3994
  "mode": "0000644",
3990
- "sha256": "4c7bb37582485445e947e233c9fbb9c20c9ab55da9dd159c8062fffa4472a5d7"
3995
+ "sha256": "3db404b6ad50e01de0b1d73131cefc01ab8fe939eee18157ba6aa8f28a05fb7f"
3991
3996
  },
3992
3997
  {
3993
3998
  "path": "modules/provisioning/ui/.gitkeep",
@@ -4277,12 +4282,12 @@
4277
4282
  {
4278
4283
  "path": "package-lock.json",
4279
4284
  "mode": "0000644",
4280
- "sha256": "8cece7080d6a67c93467f86ee1c02cff85f8b2dbd5e8219519e9bc9df034f895"
4285
+ "sha256": "df481ba4f5057938d85fadf4e5551602cb50c68f78358dc110d03ebfb99ff278"
4281
4286
  },
4282
4287
  {
4283
4288
  "path": "package.json",
4284
4289
  "mode": "0000644",
4285
- "sha256": "05a1768a85ccd224b9caa4e388b83f5a1d933b8b46761ebe7ce6f5a06f3c6d6a"
4290
+ "sha256": "5b6943de459044d4545437bd4941abadbdefcedc0063e291f72205e46956beb3"
4286
4291
  },
4287
4292
  {
4288
4293
  "path": "public-docs/index.html",
@@ -4542,7 +4547,7 @@
4542
4547
  {
4543
4548
  "path": "public-landing/projects.html",
4544
4549
  "mode": "0000644",
4545
- "sha256": "494d1aa1a6ff006a8e8f239c29d90c052f735919937c9dc6fb6b8eeff4902e91"
4550
+ "sha256": "20dd4fcb471c8d5a4dced2788ca6fffecaba241207bc0087d918d15b60bcc1a1"
4546
4551
  },
4547
4552
  {
4548
4553
  "path": "public-landing/world/assets/clouds/cloud-island-large.png",
@@ -5442,7 +5447,7 @@
5442
5447
  {
5443
5448
  "path": "scripts/gds/setup.js",
5444
5449
  "mode": "0000644",
5445
- "sha256": "8e512a07ed885666722a216951dfad7f57fbfd92923bdf5079ce1c6f7b5c0abc"
5450
+ "sha256": "98671f5666ae6bdafa7691bd519367345772c3041680b59c24ec83c56b99f419"
5446
5451
  },
5447
5452
  {
5448
5453
  "path": "scripts/gds/shell.js",
@@ -5892,7 +5897,7 @@
5892
5897
  {
5893
5898
  "path": "src/module-api.js",
5894
5899
  "mode": "0000644",
5895
- "sha256": "84441072e12b08bf8c5dde09972dc91dd530b586f30f287016d830589476fb5d"
5900
+ "sha256": "d20ec520ccfe8d1ac72910455f97f728feaf179b265f79ebf6f9a2ca21f1e424"
5896
5901
  },
5897
5902
  {
5898
5903
  "path": "src/module-loader/catalog.js",
@@ -7377,7 +7382,7 @@
7377
7382
  {
7378
7383
  "path": "tests/onboard.mjs",
7379
7384
  "mode": "0000644",
7380
- "sha256": "c6823a6f0f81bcb4f01ccbd2364d6dcf76eb21e3ff10972738f792438939dee0"
7385
+ "sha256": "71eeb42b47ad2ba11b8379cce263ceac2da42b00b9fe55aab64546027b193364"
7381
7386
  },
7382
7387
  {
7383
7388
  "path": "tests/onboarding_gate.mjs",
@@ -7539,6 +7544,11 @@
7539
7544
  "mode": "0000644",
7540
7545
  "sha256": "7749df454ac3cca7c7e5ea1acc94ead15d1c9f87b38fe2028a1c93c8adf31bcf"
7541
7546
  },
7547
+ {
7548
+ "path": "tests/provisioning_settings.mjs",
7549
+ "mode": "0000644",
7550
+ "sha256": "bb800d2e15045efbac4fadbc62996054d33e163eb86e6a5e09087d409cc7fbfa"
7551
+ },
7542
7552
  {
7543
7553
  "path": "tests/provisioning_slug_available.mjs",
7544
7554
  "mode": "0000644",
@@ -7819,6 +7829,11 @@
7819
7829
  "mode": "0000644",
7820
7830
  "sha256": "a630ac72981f230e8aa6609152765c13e8928ac329cb0ff3fe615371f31208d2"
7821
7831
  },
7832
+ {
7833
+ "path": "tests/setup_device_flow_fallback.mjs",
7834
+ "mode": "0000644",
7835
+ "sha256": "9a9df92b732b4f13d222329877ab17f8f972ef01370c9a918b00635716c76b5e"
7836
+ },
7822
7837
  {
7823
7838
  "path": "tests/setup_smoke.mjs",
7824
7839
  "mode": "0000644",
@@ -9,7 +9,7 @@ You are guiding a new owner from **zero to a live, owned Cloud Bongos instance**
9
9
 
10
10
  A new instance is **standalone** (ADR 0108): it runs from its **own git repo** with `@cloudbongos/core` installed as a **pinned npm dependency**, not a fork of this monorepo. Central updates are a `bongos upgrade` version-pin bump, not a merge. Every step below assumes this shape (`hosting_shape=standalone`).
11
11
 
12
- Five steps are **irreducibly human** and must be rendered as **precise, UI-first, copy-paste-safe prompts** (a non-technical owner does them with browser clicks, no terminal guessing): (1) create the GitHub repo, (2) approve the pre-filled **GitHub App** for sign-in (ONE click — the App Manifest flow, task 2080; no secret to paste), (3) install that App on the repo (ONE click — the publish credential, task 1003049), (4) own a domain, (5) the first sign-in. Everything else is automated. Never ask the owner to do in a terminal what they can do with a click.
12
+ Six steps are **irreducibly human** and must be rendered as **precise, UI-first, copy-paste-safe prompts** (a non-technical owner does them with browser clicks, no terminal guessing): (1) create the GitHub repo, (2) approve the pre-filled **GitHub App** for sign-in (ONE click — the App Manifest flow, task 2080; no secret to paste), (3) tick **Enable Device Flow** in that App's settings (ONE checkbox — terminal sign-in, task 1003051; until then `bongos setup` falls back to a web token), (4) install that App on the repo (ONE click — the publish credential, task 1003049), (5) own a domain, (6) the first sign-in. Everything else is automated. Never ask the owner to do in a terminal what they can do with a click.
13
13
 
14
14
  ## The canonical sequence
15
15
 
@@ -5,7 +5,7 @@ A **generated**, zero-dependency typed client for the Bongos API — produced fr
5
5
  by hand; it regenerates when the spec changes, so it can never drift from the routes.
6
6
 
7
7
  - API version: **v1** (served at `/api/bongos/v1`)
8
- - 276 operations across 46 resource groups
8
+ - 278 operations across 46 resource groups
9
9
 
10
10
  ## Install
11
11
 
@@ -543,6 +543,10 @@ function createClient(opts = {}) {
543
543
  postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
544
544
  // POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
545
545
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
546
+ // GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
547
+ getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
548
+ // PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
549
+ patchProvisioningInstancesIdSettings: (args) => request("PATCH", "/provisioning/instances/{id}/settings", { hasBody: true }, args),
546
550
  // POST /provisioning/instances/{id}/teardown — rank: any-builder — POST /provisioning/instances/:id/teardown
547
551
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
548
552
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
@@ -542,6 +542,10 @@ function createClient(opts = {}) {
542
542
  postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
543
543
  // POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
544
544
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
545
+ // GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
546
+ getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
547
+ // PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
548
+ patchProvisioningInstancesIdSettings: (args) => request("PATCH", "/provisioning/instances/{id}/settings", { hasBody: true }, args),
545
549
  // POST /provisioning/instances/{id}/teardown — rank: any-builder — POST /provisioning/instances/:id/teardown
546
550
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
547
551
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
@@ -75,6 +75,7 @@ export interface GetProvisioningFleetResponse { instances: unknown }
75
75
  export interface GetProvisioningGithubAppStatusResponse { ok: boolean; status: unknown; ready: unknown; terminal: unknown; domain: unknown; instance_status: unknown; app_slug: unknown }
76
76
  export interface GetProvisioningHealthResponse { module: unknown; ok: boolean; coreVersion: unknown }
77
77
  export interface GetProvisioningInstancesIdResponse { instance: unknown; open_intent: unknown }
78
+ export interface GetProvisioningInstancesIdSettingsResponse { ok: boolean; settings: unknown; options: unknown }
78
79
  export interface GetProvisioningInstancesResponse { instances: unknown }
79
80
  export interface GetProvisioningOnboardPlanResponse { mode: unknown; steps: unknown }
80
81
  export interface GetProvisioningSlugAvailableResponse { slug: unknown; available: unknown; reason: unknown; address: unknown }
@@ -140,6 +141,8 @@ export interface PatchMeSkillPrefsResponse { prefs: unknown; effective: unknown;
140
141
  export interface PatchMeSoundPrefsResponse { prefs: unknown; effective: unknown; effective_map: unknown; volume: unknown; defaults: unknown; known_sounds: unknown }
141
142
  export interface PatchProjectsIdFeaturedRequest { featured: boolean }
142
143
  export interface PatchProjectsIdFeaturedResponse { project: unknown }
144
+ export interface PatchProvisioningInstancesIdSettingsRequest { platform_visibility?: string; joinability?: string }
145
+ export interface PatchProvisioningInstancesIdSettingsResponse { ok: boolean; settings: unknown }
143
146
  export interface PatchTasksIdRequest { kind?: string; discipline?: string; requires_rank?: string; module_key?: string; goal_id?: number; parent_task_id?: StringifiableId; parallel_safe?: unknown; newcomer_friendly?: boolean; xenos_claimable?: boolean; security_sensitive?: boolean; automation_tag?: string; needs_migration?: boolean; description?: string; status?: unknown }
144
147
  export interface PostAccessRequestsRequest { github_login: string; display_name?: string; note?: string }
145
148
  export interface PostAccessRequestsResponse { ok: boolean; request?: unknown; already_pending?: boolean }
@@ -787,6 +790,10 @@ export interface BongosClient {
787
790
  postProvisioningInstancesIdForceTeardown(args?: RequestArgs): Promise<PostProvisioningInstancesIdForceTeardownResponse>;
788
791
  /** POST /provisioning/instances/{id}/github-app — rank: any-builder */
789
792
  postProvisioningInstancesIdGithubApp(args?: RequestArgs & { body?: PostProvisioningInstancesIdGithubAppRequest }): Promise<PostProvisioningInstancesIdGithubAppResponse>;
793
+ /** GET /provisioning/instances/{id}/settings — rank: any-builder */
794
+ getProvisioningInstancesIdSettings(args?: RequestArgs): Promise<GetProvisioningInstancesIdSettingsResponse>;
795
+ /** PATCH /provisioning/instances/{id}/settings — rank: any-builder */
796
+ patchProvisioningInstancesIdSettings(args?: RequestArgs & { body?: PatchProvisioningInstancesIdSettingsRequest }): Promise<PatchProvisioningInstancesIdSettingsResponse>;
790
797
  /** POST /provisioning/instances/{id}/teardown — rank: any-builder */
791
798
  postProvisioningInstancesIdTeardown(args?: RequestArgs): Promise<PostProvisioningInstancesIdTeardownResponse>;
792
799
  /** GET /provisioning/onboard-plan — rank: public */
@@ -539,6 +539,10 @@ export function createClient(opts = {}) {
539
539
  postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
540
540
  // POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
541
541
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
542
+ // GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
543
+ getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
544
+ // PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
545
+ patchProvisioningInstancesIdSettings: (args) => request("PATCH", "/provisioning/instances/{id}/settings", { hasBody: true }, args),
542
546
  // POST /provisioning/instances/{id}/teardown — rank: any-builder — POST /provisioning/instances/:id/teardown
543
547
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
544
548
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
@@ -8951,6 +8951,119 @@
8951
8951
  ]
8952
8952
  }
8953
8953
  },
8954
+ "/provisioning/instances/{id}/settings": {
8955
+ "get": {
8956
+ "operationId": "get_provisioning_instances_id_settings",
8957
+ "tags": [
8958
+ "provisioning"
8959
+ ],
8960
+ "summary": "GET /provisioning/instances/:id/settings",
8961
+ "description": "GET /provisioning/instances/:id/settings — read a project's effective settings + the allowed values (so a form can render its choices). rank: any authenticated builder (own resource; archon may read any).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8962
+ "x-rank": "any-builder",
8963
+ "x-source": "modules/provisioning/routes/provisioning.js",
8964
+ "parameters": [
8965
+ {
8966
+ "name": "id",
8967
+ "in": "path",
8968
+ "required": true,
8969
+ "schema": {
8970
+ "type": "string"
8971
+ },
8972
+ "description": "Path parameter `id`."
8973
+ }
8974
+ ],
8975
+ "responses": {
8976
+ "200": {
8977
+ "description": "Success.",
8978
+ "content": {
8979
+ "application/json": {
8980
+ "schema": {
8981
+ "$ref": "#/components/schemas/GetProvisioningInstancesIdSettingsResponse"
8982
+ }
8983
+ }
8984
+ }
8985
+ },
8986
+ "400": {
8987
+ "$ref": "#/components/responses/BadRequest"
8988
+ },
8989
+ "401": {
8990
+ "$ref": "#/components/responses/Unauthorized"
8991
+ },
8992
+ "403": {
8993
+ "$ref": "#/components/responses/Forbidden"
8994
+ },
8995
+ "404": {
8996
+ "$ref": "#/components/responses/NotFound"
8997
+ }
8998
+ },
8999
+ "security": [
9000
+ {
9001
+ "builderSession": []
9002
+ }
9003
+ ]
9004
+ },
9005
+ "patch": {
9006
+ "operationId": "patch_provisioning_instances_id_settings",
9007
+ "tags": [
9008
+ "provisioning"
9009
+ ],
9010
+ "summary": "PATCH /provisioning/instances/:id/settings",
9011
+ "description": "PATCH /provisioning/instances/:id/settings — change a project's settings. Body: any subset of the known keys; strict validation refuses unknown keys and off-vocabulary values. rank: any authenticated builder (own resource; archon may change any — the override is audited via the event's actor).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
9012
+ "x-rank": "any-builder",
9013
+ "x-source": "modules/provisioning/routes/provisioning.js",
9014
+ "parameters": [
9015
+ {
9016
+ "name": "id",
9017
+ "in": "path",
9018
+ "required": true,
9019
+ "schema": {
9020
+ "type": "string"
9021
+ },
9022
+ "description": "Path parameter `id`."
9023
+ }
9024
+ ],
9025
+ "requestBody": {
9026
+ "required": false,
9027
+ "content": {
9028
+ "application/json": {
9029
+ "schema": {
9030
+ "$ref": "#/components/schemas/PatchProvisioningInstancesIdSettingsRequest"
9031
+ }
9032
+ }
9033
+ },
9034
+ "x-validated": true
9035
+ },
9036
+ "responses": {
9037
+ "200": {
9038
+ "description": "Success.",
9039
+ "content": {
9040
+ "application/json": {
9041
+ "schema": {
9042
+ "$ref": "#/components/schemas/PatchProvisioningInstancesIdSettingsResponse"
9043
+ }
9044
+ }
9045
+ }
9046
+ },
9047
+ "400": {
9048
+ "$ref": "#/components/responses/ValidationFailed"
9049
+ },
9050
+ "401": {
9051
+ "$ref": "#/components/responses/Unauthorized"
9052
+ },
9053
+ "403": {
9054
+ "$ref": "#/components/responses/Forbidden"
9055
+ },
9056
+ "404": {
9057
+ "$ref": "#/components/responses/NotFound"
9058
+ }
9059
+ },
9060
+ "security": [
9061
+ {
9062
+ "builderSession": []
9063
+ }
9064
+ ]
9065
+ }
9066
+ },
8954
9067
  "/provisioning/instances/{id}/teardown": {
8955
9068
  "post": {
8956
9069
  "operationId": "post_provisioning_instances_id_teardown",
@@ -13441,6 +13554,21 @@
13441
13554
  "open_intent"
13442
13555
  ]
13443
13556
  },
13557
+ "GetProvisioningInstancesIdSettingsResponse": {
13558
+ "type": "object",
13559
+ "properties": {
13560
+ "ok": {
13561
+ "type": "boolean"
13562
+ },
13563
+ "settings": {},
13564
+ "options": {}
13565
+ },
13566
+ "required": [
13567
+ "ok",
13568
+ "settings",
13569
+ "options"
13570
+ ]
13571
+ },
13444
13572
  "GetProvisioningInstancesResponse": {
13445
13573
  "type": "object",
13446
13574
  "properties": {
@@ -14253,6 +14381,31 @@
14253
14381
  "project"
14254
14382
  ]
14255
14383
  },
14384
+ "PatchProvisioningInstancesIdSettingsRequest": {
14385
+ "type": "object",
14386
+ "properties": {
14387
+ "platform_visibility": {
14388
+ "type": "string"
14389
+ },
14390
+ "joinability": {
14391
+ "type": "string"
14392
+ }
14393
+ },
14394
+ "additionalProperties": false
14395
+ },
14396
+ "PatchProvisioningInstancesIdSettingsResponse": {
14397
+ "type": "object",
14398
+ "properties": {
14399
+ "ok": {
14400
+ "type": "boolean"
14401
+ },
14402
+ "settings": {}
14403
+ },
14404
+ "required": [
14405
+ "ok",
14406
+ "settings"
14407
+ ]
14408
+ },
14256
14409
  "PatchTasksIdRequest": {
14257
14410
  "type": "object",
14258
14411
  "properties": {
@@ -17434,9 +17587,9 @@
17434
17587
  "description": "A required dependency/feature is not configured or is temporarily down."
17435
17588
  }
17436
17589
  },
17437
- "x-endpoint-count": 276,
17438
- "x-schema-count": 311,
17590
+ "x-endpoint-count": 278,
17591
+ "x-schema-count": 314,
17439
17592
  "x-undocumented-bodies": 8,
17440
- "x-response-schemas": 210,
17593
+ "x-response-schemas": 212,
17441
17594
  "x-generated-by": "scripts/gds/gen-api-docs.js"
17442
17595
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Bongos API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 276 endpoints across 46 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 278 endpoints across 46 route files.
6
6
  > Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
7
7
 
8
8
  Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -369,7 +369,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
369
369
  | GET | `/api/bongos/projects/featured` | `public` | — | a curated public showcase; no auth by design. |
370
370
  | POST | `/api/bongos/projects/invite` | `metic+archon` | `client_id`, `github_login` | invite a builder into a project (ADR 0141 §5, task #1002115). |
371
371
 
372
- ## `provisioning` (15)
372
+ ## `provisioning` (17)
373
373
 
374
374
  | Method | Path | Rank | Body | Description |
375
375
  |---|---|---|---|---|
@@ -384,6 +384,8 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
384
384
  | POST | `/api/bongos/provisioning/instances/:id/domain` | `any-builder` | `domain` | POST /provisioning/instances/:id/domain — give the caller's OWN instance its address (task 1002692, gap 5: no path existed to add a domai… |
385
385
  | POST | `/api/bongos/provisioning/instances/:id/force-teardown` | `metic+archon` | — | POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. |
386
386
  | POST | `/api/bongos/provisioning/instances/:id/github-app` | `any-builder` | `account` | POST /provisioning/instances/:id/github-app — mint a GitHub-App-Manifest onboarding link for the caller's OWN instance (task 2080, ADR 01… |
387
+ | GET | `/api/bongos/provisioning/instances/:id/settings` | `any-builder` | — | GET /provisioning/instances/:id/settings — read a project's effective settings + the allowed values (so a form can render its choices). |
388
+ | PATCH | `/api/bongos/provisioning/instances/:id/settings` | `any-builder` | `platform_visibility`, `joinability` | PATCH /provisioning/instances/:id/settings — change a project's settings. |
387
389
  | POST | `/api/bongos/provisioning/instances/:id/teardown` | `any-builder` | — | POST /provisioning/instances/:id/teardown — request teardown of the caller's OWN instance. |
388
390
  | GET | `/api/bongos/provisioning/onboard-plan` | `public` | — | GET /provisioning/onboard-plan?mode=greenfield\|adopt&domain=<host> — the CANONICAL onboarding step sequence (task 2085; goal 35 / criteri… |
389
391
  | GET | `/api/bongos/provisioning/slug-available` | `any-builder` | — | GET /provisioning/slug-available?slug=<handle> — is this handle free to create under? rank: any authenticated builder (same gate as the c… |
@@ -542,6 +542,10 @@ function createClient(opts = {}) {
542
542
  postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
543
543
  // POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
544
544
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
545
+ // GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
546
+ getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
547
+ // PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
548
+ patchProvisioningInstancesIdSettings: (args) => request("PATCH", "/provisioning/instances/{id}/settings", { hasBody: true }, args),
545
549
  // POST /provisioning/instances/{id}/teardown — rank: any-builder — POST /provisioning/instances/:id/teardown
546
550
  postProvisioningInstancesIdTeardown: (args) => request("POST", "/provisioning/instances/{id}/teardown", { hasBody: true }, args),
547
551
  // GET /provisioning/onboard-plan — rank: public — GET /provisioning/onboard-plan
@@ -0,0 +1,19 @@
1
+ -- provisioning_009_project_settings.sql — per-project settings storage (task
2
+ -- 1003040, goal 1000058: the project-management page wave's foundation).
3
+ --
4
+ -- WHY jsonb, not columns: the manage-page wave adds settings one task at a time
5
+ -- (platform visibility, joinability, repo visibility, …) and a new key must not
6
+ -- cost a migration each time. The column is a dumb store; the known keys + their
7
+ -- vocabularies are enforced at the API layer (provisioning.SETTINGS_VOCAB /
8
+ -- the settings routes' validator), and unknown stored values fall back to the
9
+ -- default at read time (effectiveSettings) rather than leaking out.
10
+ --
11
+ -- DEFAULTS = today's behavior: '{}'::jsonb READS as
12
+ -- { platform_visibility: 'public', joinability: 'apply' } — the default lives in
13
+ -- code, applied at read time, so ADD COLUMN backfills every existing row with an
14
+ -- empty object and no instance changes behavior.
15
+ ALTER TABLE provisioning_instances
16
+ ADD COLUMN IF NOT EXISTS settings jsonb NOT NULL DEFAULT '{}'::jsonb;
17
+
18
+ INSERT INTO schema_migrations (version) VALUES ('provisioning_009_project_settings')
19
+ ON CONFLICT (version) DO NOTHING;
@@ -44,6 +44,7 @@ function onboardPlan(mode = 'greenfield', opts = {}) {
44
44
  { key: 'seed-version', kind: 'auto', label: 'Seed the first version (V1) so the instance can take tasks immediately (task 2119)' },
45
45
  { key: 'oauth-app', kind: 'human', label: 'Wire GitHub sign-in — one-click GitHub App (task 2080), or a manual OAuth app' },
46
46
  { key: 'oauth-place', kind: 'auto', shapes: CONTROL_PLANE_SHAPES, label: 'Place the OAuth secret — auto via the Manifest flow, or verified manual (task 1979)' },
47
+ { key: 'device-flow', kind: 'human', label: 'Enable Device Flow in the GitHub App settings — one checkbox, so terminal sign-in (bongos login) works (task 1003051)' },
47
48
  { key: 'app-install', kind: 'human', label: 'Install the GitHub App on the repo — the publish credential that lets shipped work land itself (task 1003049, ADR 0055)' },
48
49
  { key: 'first-sign-in', kind: 'human', label: 'First sign-in (seats the founding Archon)' },
49
50
  { key: 'verify', kind: 'auto', label: 'Verify /healthz auth_configured' },
@@ -59,6 +59,17 @@ const PROVISION_ENQUEUE_FROM = new Set(['requested', 'provisioning', 'error', 't
59
59
  // itself. Mid-flight or torn-down states refuse truthfully.
60
60
  const DOMAIN_ATTACH_FROM = new Set(['requested', 'error', 'active']);
61
61
 
62
+ // Per-project settings (task 1003040, goal 1000058): the known keys + their
63
+ // vocabularies, enforced at the API layer — the jsonb `settings` column
64
+ // (migration provisioning_009) is a dumb store with room for future keys.
65
+ // DEFAULT_SETTINGS is TODAY's behavior (public surfaces, apply-to-join),
66
+ // applied at read time so pre-existing rows need no data backfill.
67
+ const SETTINGS_VOCAB = Object.freeze({
68
+ platform_visibility: ['public', 'gated'],
69
+ joinability: ['open', 'apply', 'invite_only'],
70
+ });
71
+ const DEFAULT_SETTINGS = Object.freeze({ platform_visibility: 'public', joinability: 'apply' });
72
+
62
73
  // Monthly cost estimate (USD) for a dedicated droplet tier — VISIBILITY only
63
74
  // (ADR 0111 §6), never a bill. A small local table so this module needs no
64
75
  // sibling-module import; P2 (shared control-plane client extraction) is where a
@@ -210,6 +221,19 @@ function publicInstance(row) {
210
221
  };
211
222
  }
212
223
 
224
+ // The instance's EFFECTIVE settings: the defaults overlaid with the stored,
225
+ // on-vocabulary keys. An off-vocabulary or unknown stored value falls back to
226
+ // its default rather than leaking into the read surface. PURE.
227
+ function effectiveSettings(row) {
228
+ const stored = row && row.settings && typeof row.settings === 'object' && !Array.isArray(row.settings)
229
+ ? row.settings : {};
230
+ const out = { ...DEFAULT_SETTINGS };
231
+ for (const [key, vocab] of Object.entries(SETTINGS_VOCAB)) {
232
+ if (vocab.includes(stored[key])) out[key] = stored[key];
233
+ }
234
+ return out;
235
+ }
236
+
213
237
  // ---------------------------------------------------------------------------
214
238
  // GitHub App Manifest flow — PURE builders (task 2080, ADR 0133).
215
239
  // GitHub has no create-an-OAuth-App API, but the App *Manifest* flow lets the owner
@@ -345,6 +369,20 @@ async function getInstanceByDomain(db, domain) {
345
369
  return rows[0] || null;
346
370
  }
347
371
 
372
+ // Merge a VALIDATED settings patch into the instance's settings column (task
373
+ // 1003040). Narrow like updateInstanceDomain: settings + updated_at only — a
374
+ // settings change is a deliberate owner action, so surfacing it in the
375
+ // updated_at-ordered card list is correct (unlike the liveness overlay).
376
+ async function updateInstanceSettings(db, id, patch) {
377
+ const { rows } = await db.query(
378
+ `UPDATE provisioning_instances
379
+ SET settings = settings || $2::jsonb, updated_at = now()
380
+ WHERE id = $1 RETURNING *`,
381
+ [id, JSON.stringify(patch)]
382
+ );
383
+ return rows[0] || null;
384
+ }
385
+
348
386
  // Record an instance's domain — the ONLY column this touches (task 1002692). Status
349
387
  // changes stay setInstanceStatus's job; keeping this narrow means the domain-attach
350
388
  // route can never drift an instance's lifecycle as a side effect.
@@ -735,9 +773,10 @@ module.exports = {
735
773
  // constants
736
774
  INSTANCE_STATES, HOSTING_SHAPES, ONBOARD_MODES, PROJECT_TYPES, INTENT_ACTIONS, TEARDOWN_FROM,
737
775
  PROVISION_ENQUEUE_FROM, DOMAIN_ATTACH_FROM, TIER_MONTHLY_USD, CERT_ELIGIBLE_STATES,
776
+ SETTINGS_VOCAB, DEFAULT_SETTINGS,
738
777
  // pure
739
778
  isValidSlug, costEstimateUsd, publicInstance, normalizeHostname,
740
- defaultDomainForSlug, isReservedHostname,
779
+ defaultDomainForSlug, isReservedHostname, effectiveSettings,
741
780
  // pure — GitHub App Manifest flow (task 2080)
742
781
  githubAppName, buildGithubAppManifest, manifestPostUrl,
743
782
  // data access
@@ -745,7 +784,7 @@ module.exports = {
745
784
  getInstanceById, getInstanceBySlug, getInstanceByDomain, listInstancesForOwner, listAllInstances,
746
785
  // data access — verification overlay (task 1002696)
747
786
  listActiveInstancesForLiveness, recordLivenessProbe, recordDnsNote, clearErrorNote,
748
- createInstance, setInstanceStatus, updateInstanceDomain,
787
+ createInstance, setInstanceStatus, updateInstanceDomain, updateInstanceSettings,
749
788
  enqueueIntent, enqueueTeardown, getOpenIntent, claimNextIntent, resolveIntent,
750
789
  recordEvent, instanceStateForSlug, costLedger,
751
790
  // data access — GitHub App Manifest attempts (task 2080)