@bongos/core 1.19.168 → 1.19.170

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.168",
6
- "core_contract": "1.19.168",
7
- "source_commit": "d1de1d92631455296b40254771a484510790afe2",
5
+ "core_version": "1.19.170",
6
+ "core_contract": "1.19.170",
7
+ "source_commit": "2fd8009b960bd910fe95b3169d504adc7fe309d1",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-16T17:40:10.703Z",
9
+ "built_at": "2026-08-16T18:45:10.150Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 305,
13
13
  "agent_docs_stubbed": 21,
14
- "functional_verbatim": 1265,
14
+ "functional_verbatim": 1268,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1591,
20
- "tree_sha256": "decba66e24c9eb800c760c258aeff0daefebef5fd777a6f7000df6a3c6e464c7",
19
+ "file_count": 1594,
20
+ "tree_sha256": "938326e2e51b3c2bf0a7ab516c8444005ec95028f247df10cc55bedae67b099f",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -347,12 +347,12 @@
347
347
  {
348
348
  "path": "clients/bongos-client/README.md",
349
349
  "mode": "0000644",
350
- "sha256": "c8143e170b5ac87e7cdd243eb83edb8b22ad252382c86544f96e7a38311e0380"
350
+ "sha256": "d6d6163164f98c96a8e25dfe84825669bf8324f1f1b98adb0674781ad235ad10"
351
351
  },
352
352
  {
353
353
  "path": "clients/bongos-client/bongos-client.global.js",
354
354
  "mode": "0000644",
355
- "sha256": "dd11d5decd14af95cc23c2bef8dfe8c477132fb07d671682b228107fe69d7ea4"
355
+ "sha256": "386706d0ef3d09c5e074bdc45bfc0de869d732eb1cb2a2280472f02f797f2b74"
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": "257ac54c66f7969090065a34c29e2874fa6f9d111b6e75f0510ab1a2fcb3ef17"
365
+ "sha256": "7d462b5b80c9db9159981406398fc62c5ba71043c6a3b9433852d06d612bf2b0"
366
366
  },
367
367
  {
368
368
  "path": "clients/bongos-client/index.d.ts",
369
369
  "mode": "0000644",
370
- "sha256": "4245c4fb82c1c4f5c87788030dc4640987fe22e0d588072d4549e9982cea7ecc"
370
+ "sha256": "4acb1dde6f894ba37cff7e27e0110f12ae30c7cb6e4d972d6e85d2877489b6d0"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/index.mjs",
374
374
  "mode": "0000644",
375
- "sha256": "4889c6c70c1f58d90006800cf2bd363b4c2cc546c69042a1faae5106c16aab03"
375
+ "sha256": "4c7679ef258644ab12db1b8fe412b388f96f4296c6aae45d6ab637a8f3b9a037"
376
376
  },
377
377
  {
378
378
  "path": "clients/bongos-client/package.json",
@@ -1347,12 +1347,12 @@
1347
1347
  {
1348
1348
  "path": "docs/api-reference.md",
1349
1349
  "mode": "0000644",
1350
- "sha256": "879ef6fd06bde11c040c5ef67ccf495f0be6eb95e11be6f8979c9d560a33da64"
1350
+ "sha256": "ccf59372e0456f36d83154d6dff4dbf5382e8d69023bee82b318b8e9cfb2c50b"
1351
1351
  },
1352
1352
  {
1353
1353
  "path": "docs/api/openapi.json",
1354
1354
  "mode": "0000644",
1355
- "sha256": "9382373e7be837c0ce4e26f23c3cd32bf20ab09858650bdee318dd90a06dedbe"
1355
+ "sha256": "4deac83a1d7c12e1a24109e856d9a6fef6b539afafdca55a525ab6786fe4e235"
1356
1356
  },
1357
1357
  {
1358
1358
  "path": "docs/architecture.md",
@@ -2662,7 +2662,7 @@
2662
2662
  {
2663
2663
  "path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
2664
2664
  "mode": "0000644",
2665
- "sha256": "257ac54c66f7969090065a34c29e2874fa6f9d111b6e75f0510ab1a2fcb3ef17"
2665
+ "sha256": "7d462b5b80c9db9159981406398fc62c5ba71043c6a3b9433852d06d612bf2b0"
2666
2666
  },
2667
2667
  {
2668
2668
  "path": "modules/dev-box/app/test/unit.mjs",
@@ -3382,12 +3382,12 @@
3382
3382
  {
3383
3383
  "path": "modules/hall-ui/public/settings.html",
3384
3384
  "mode": "0000644",
3385
- "sha256": "eaea5b3ca78fa89fbff71bb0209f24afd010e064dec5e4b4803edc2bdd07e1c1"
3385
+ "sha256": "ae68a26d5d37ac75968ac11335b7062a448798cb3af0e0a4f81963f3382f204d"
3386
3386
  },
3387
3387
  {
3388
3388
  "path": "modules/hall-ui/public/settings.js",
3389
3389
  "mode": "0000644",
3390
- "sha256": "9b6c826e4c444ff68a7dcc0df1a76122ead297220685e701dc0d45edafa6ca4b"
3390
+ "sha256": "2b69d258218e92b9fe2922496632e43d4bdb81f641f09469f5f6df85494a9fca"
3391
3391
  },
3392
3392
  {
3393
3393
  "path": "modules/hall-ui/public/shell.js",
@@ -3784,15 +3784,20 @@
3784
3784
  "mode": "0000644",
3785
3785
  "sha256": "4885d452673c2d6170835c8d7f03c101847ddb313a69dfb66c8e640f875ecdc1"
3786
3786
  },
3787
+ {
3788
+ "path": "modules/platform-identity/migrations/platform_identity_007_profile_consent.sql",
3789
+ "mode": "0000644",
3790
+ "sha256": "cce2f971f030aa628f9d7855f2e421595ea71cb314e90965206dbe970b7beded"
3791
+ },
3787
3792
  {
3788
3793
  "path": "modules/platform-identity/module.json",
3789
3794
  "mode": "0000644",
3790
- "sha256": "71bd26b5e4ba6012e3119a99c1aa1046d61b12b17e1018f55c9ee11b6ec29895"
3795
+ "sha256": "e993fb26e61249bf89c0b0a5977c60e9d974810ffe1b67e94d909e8b52e00d5e"
3791
3796
  },
3792
3797
  {
3793
3798
  "path": "modules/platform-identity/platform-identity.js",
3794
3799
  "mode": "0000644",
3795
- "sha256": "3d20563833a9daf20d14745f2ce1c5fe530fc918eac03427185998ff9b67beed"
3800
+ "sha256": "96907af1af78c472118ecf5ed9f269d6d2ce940b09535aae3b3df4de4d2337c1"
3796
3801
  },
3797
3802
  {
3798
3803
  "path": "modules/platform-identity/pollers/code-sweep.js",
@@ -3809,6 +3814,11 @@
3809
3814
  "mode": "0000644",
3810
3815
  "sha256": "7fdb5a107e1ad84214c0d07507a7fd14b9234c9907224fddc0f6a70c850f460a"
3811
3816
  },
3817
+ {
3818
+ "path": "modules/platform-identity/routes/profile.js",
3819
+ "mode": "0000644",
3820
+ "sha256": "6ea29b4f07417fa925b7987dd7fbe8a0262b7fec83ceffade9fccbc220289bba"
3821
+ },
3812
3822
  {
3813
3823
  "path": "modules/platform-identity/routes/projects.js",
3814
3824
  "mode": "0000644",
@@ -3817,17 +3827,17 @@
3817
3827
  {
3818
3828
  "path": "modules/platform-identity/routes/scouting.js",
3819
3829
  "mode": "0000644",
3820
- "sha256": "c6db7fa003caaf55d2ecb68f1ff73d7d89d8b71b6d999ed3ebf71286e8726359"
3830
+ "sha256": "886c9d98c94e84d2e51e21d5e716caafe757edbb49073d7dc096221b339ffd27"
3821
3831
  },
3822
3832
  {
3823
3833
  "path": "modules/platform-identity/routes/sso.js",
3824
3834
  "mode": "0000644",
3825
- "sha256": "1a3b19e793387c8410062cb2d53f981eb108ff72c31e09741bcc7c8622ca2b80"
3835
+ "sha256": "45c8a071f8bf61bd97bce83518fe3bd1b32cff99f31281c2cba84ad500359d60"
3826
3836
  },
3827
3837
  {
3828
3838
  "path": "modules/platform-identity/tests/platform-identity.mjs",
3829
3839
  "mode": "0000644",
3830
- "sha256": "727fc8c7533eec1e4af477582bdd6428e9842b930b3cc898bb8a13ddead83ec3"
3840
+ "sha256": "18bf8d0cb42d76bc5413c760b13837fe439a6e719b88a84db96f143b829e67d5"
3831
3841
  },
3832
3842
  {
3833
3843
  "path": "modules/platform-identity/ui/.gitkeep",
@@ -4202,12 +4212,12 @@
4202
4212
  {
4203
4213
  "path": "package-lock.json",
4204
4214
  "mode": "0000644",
4205
- "sha256": "5dc4705ddce9ec0b3e3925e5f3babfe6c648e5d6039b949ff74b2afa571cd8d1"
4215
+ "sha256": "0b596f97bbd28b6ddfda4a9265effcb0ea8711a4bb57948c35b80d7cf79c23d9"
4206
4216
  },
4207
4217
  {
4208
4218
  "path": "package.json",
4209
4219
  "mode": "0000644",
4210
- "sha256": "d661d208ae737337262da1c9abd9a5d6cafe5ef36b53699c2913bfd96dd13ec8"
4220
+ "sha256": "ae9625129bd03cb29845f65e1be3abd91c48259d85a9c23095370e43a0a0e8aa"
4211
4221
  },
4212
4222
  {
4213
4223
  "path": "public-docs/index.html",
@@ -5192,7 +5202,7 @@
5192
5202
  {
5193
5203
  "path": "scripts/gds/run-unit-tests.js",
5194
5204
  "mode": "0000644",
5195
- "sha256": "5e7030e617e4db066136556a43cf030078b0d042ee480c9b7245eea05ab83776"
5205
+ "sha256": "21bcaeaa9d8b2048b9c3f9ff9b251a9203a9259c991a536636c0ec3c8745bbd5"
5196
5206
  },
5197
5207
  {
5198
5208
  "path": "scripts/gds/sandbox-stage.js",
@@ -5572,7 +5582,7 @@
5572
5582
  {
5573
5583
  "path": "src/bongos/auth.js",
5574
5584
  "mode": "0000644",
5575
- "sha256": "a8215fa2659638d5850acb787eb3b193b18b545bc7e86f801764cab328b0c837"
5585
+ "sha256": "04cddf3c307c2f3bf22b8b29140973b80b549a04f1ba90be38ed7f1a794352ad"
5576
5586
  },
5577
5587
  {
5578
5588
  "path": "src/bongos/cascade-dispatch.js",
@@ -5712,7 +5722,7 @@
5712
5722
  {
5713
5723
  "path": "src/bongos/routes/builders.js",
5714
5724
  "mode": "0000644",
5715
- "sha256": "43a409918ba54af69d0c7183af510ff9d73b26566a1a520ad97d84360abcc79b"
5725
+ "sha256": "9423af249991f4d40e03ffa8d73a3584279f9d1095115c420047a735103bb417"
5716
5726
  },
5717
5727
  {
5718
5728
  "path": "src/bongos/routes/github.js",
@@ -5812,7 +5822,7 @@
5812
5822
  {
5813
5823
  "path": "src/module-api.js",
5814
5824
  "mode": "0000644",
5815
- "sha256": "55951238fbbe742e078f5f6c3d8fbaaf2af2219be6775c38c4366d035554f6a0"
5825
+ "sha256": "28605499539ca63e000ac2fc52af1a3d75dbb2fd947846426619a189a2afd92b"
5816
5826
  },
5817
5827
  {
5818
5828
  "path": "src/module-loader/catalog.js",
@@ -7369,10 +7379,15 @@
7369
7379
  "mode": "0000644",
7370
7380
  "sha256": "3c85d28ecc55e375988f3e55aee993c8c84220889678262d8207146c2772f3f5"
7371
7381
  },
7382
+ {
7383
+ "path": "tests/profile_rollup_consent.mjs",
7384
+ "mode": "0000644",
7385
+ "sha256": "b926ffa5d4e96ef223e4057ecc3e64d678ca1e16ec4afe79cb90cbf3e35e65e0"
7386
+ },
7372
7387
  {
7373
7388
  "path": "tests/profile_route.mjs",
7374
7389
  "mode": "0000644",
7375
- "sha256": "dc354f082204073409aea90df9b91f149d474c6930b761ed5c9928bb76e1358f"
7390
+ "sha256": "3b3045a6143d67c963516ed5703b5dabb9b8945a392118721e6a0a56258f1732"
7376
7391
  },
7377
7392
  {
7378
7393
  "path": "tests/project_stats.mjs",
@@ -7567,7 +7582,7 @@
7567
7582
  {
7568
7583
  "path": "tests/scouting_rollup_fanout.mjs",
7569
7584
  "mode": "0000644",
7570
- "sha256": "1b58003a1fac89b05acfc3287e529a9e17e2b7a6ec48259b5700f6cc837cc554"
7585
+ "sha256": "3451cb25abd4eb819a7b951d1e06310d575faf6145808711fcdd2e2afb655ec3"
7571
7586
  },
7572
7587
  {
7573
7588
  "path": "tests/scrubber_corpus.mjs",
@@ -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
- - 271 operations across 45 resource groups
8
+ - 273 operations across 45 resource groups
9
9
 
10
10
  ## Install
11
11
 
@@ -409,6 +409,10 @@ function createClient(opts = {}) {
409
409
  getMeAchievements: (args) => request("GET", "/me/achievements", { hasBody: false }, args),
410
410
  // POST /me/anthropic-link — rank: any-builder — POST /me/anthropic-link
411
411
  postMeAnthropicLink: (args) => request("POST", "/me/anthropic-link", { hasBody: true }, args),
412
+ // GET /me/cross-project — rank: any-builder — GET /me/cross-project
413
+ getMeCrossProject: (args) => request("GET", "/me/cross-project", { hasBody: false }, args),
414
+ // PATCH /me/cross-project — rank: any-builder — PATCH /me/cross-project
415
+ patchMeCrossProject: (args) => request("PATCH", "/me/cross-project", { hasBody: true }, args),
412
416
  // PATCH /me/disciplines — rank: any-builder — PATCH /me/disciplines
413
417
  patchMeDisciplines: (args) => request("PATCH", "/me/disciplines", { hasBody: true }, args),
414
418
  // GET /me/display-name — rank: any-builder — GET /me/display-name
@@ -408,6 +408,10 @@ function createClient(opts = {}) {
408
408
  getMeAchievements: (args) => request("GET", "/me/achievements", { hasBody: false }, args),
409
409
  // POST /me/anthropic-link — rank: any-builder — POST /me/anthropic-link
410
410
  postMeAnthropicLink: (args) => request("POST", "/me/anthropic-link", { hasBody: true }, args),
411
+ // GET /me/cross-project — rank: any-builder — GET /me/cross-project
412
+ getMeCrossProject: (args) => request("GET", "/me/cross-project", { hasBody: false }, args),
413
+ // PATCH /me/cross-project — rank: any-builder — PATCH /me/cross-project
414
+ patchMeCrossProject: (args) => request("PATCH", "/me/cross-project", { hasBody: true }, args),
411
415
  // PATCH /me/disciplines — rank: any-builder — PATCH /me/disciplines
412
416
  patchMeDisciplines: (args) => request("PATCH", "/me/disciplines", { hasBody: true }, args),
413
417
  // GET /me/display-name — rank: any-builder — GET /me/display-name
@@ -30,7 +30,7 @@ export interface GetBoxesResponse { boxes: unknown }
30
30
  export interface GetBuildersDirectoryResponse { builders: unknown }
31
31
  export interface GetBuildersIdActiveClaimsResponse { builder_id: unknown; claims: unknown; stale_hours: unknown }
32
32
  export interface GetBuildersIdOnboardingResponse { builder_id: unknown; onboarding: unknown }
33
- export interface GetBuildersIdProfileResponse { builder: unknown; shipped_count: unknown; recent_ships: unknown; achievements: unknown }
33
+ export interface GetBuildersIdProfileResponse { builder: unknown; shipped_count: unknown; recent_ships: unknown; achievements: unknown; cross_project?: unknown }
34
34
  export interface GetBuildersMePendingRankChangeResponse { change: unknown; greeting?: unknown }
35
35
  export interface GetBuildersRosterResponse { builders: unknown; stale_hours: unknown }
36
36
  export interface GetDiscordChannelsPlanResponse { ok: boolean; guild_id: unknown; op_count: unknown; ops: unknown; warnings: unknown }
@@ -51,6 +51,7 @@ export interface GetInboxResponse { ideas: unknown; open_count: unknown }
51
51
  export interface GetLeaderboardResponse { leaderboard: unknown; page: unknown }
52
52
  export interface GetLearningsResponse { learnings: unknown }
53
53
  export interface GetMeAchievementsResponse { unlocked: unknown }
54
+ export interface GetMeCrossProjectResponse { hide_stats: boolean; profile_state: unknown; cross_project: unknown }
54
55
  export interface GetMeDisplayNameResponse { display_name: unknown; max_length: unknown }
55
56
  export interface GetMeEventSoundPrefsResponse { prefs: unknown; effective: unknown; effective_wav: unknown; events: unknown }
56
57
  export interface GetMeRecentShipsResponse { ships: unknown }
@@ -124,6 +125,8 @@ export interface PatchGoalsIdVisibilityRequest { visibility: string }
124
125
  export interface PatchGoalsIdVisibilityResponse { ok: boolean; goal: unknown }
125
126
  export interface PatchInboxIdRequest { status?: "open" | "promoted" | "discarded" | "merged"; kind?: string; promoted_to_task_id?: number; reviewed_at?: unknown; merged_into_idea_id?: number; triage_note?: string }
126
127
  export interface PatchInboxIdResponse { idea: unknown }
128
+ export interface PatchMeCrossProjectRequest { hide_stats: boolean }
129
+ export interface PatchMeCrossProjectResponse { hide_stats: boolean }
127
130
  export interface PatchMeDisciplinesRequest { preferred_disciplines: string[] }
128
131
  export interface PatchMeDisciplinesResponse { builder: unknown; onboarding: unknown }
129
132
  export interface PatchMeDisplayNameResponse { display_name: unknown; max_length: unknown }
@@ -645,6 +648,10 @@ export interface BongosClient {
645
648
  getMeAchievements(args?: RequestArgs): Promise<GetMeAchievementsResponse>;
646
649
  /** POST /me/anthropic-link — rank: any-builder */
647
650
  postMeAnthropicLink(args: RequestArgs & { body: PostMeAnthropicLinkRequest }): Promise<PostMeAnthropicLinkResponse>;
651
+ /** GET /me/cross-project — rank: any-builder */
652
+ getMeCrossProject(args?: RequestArgs): Promise<GetMeCrossProjectResponse>;
653
+ /** PATCH /me/cross-project — rank: any-builder */
654
+ patchMeCrossProject(args: RequestArgs & { body: PatchMeCrossProjectRequest }): Promise<PatchMeCrossProjectResponse>;
648
655
  /** PATCH /me/disciplines — rank: any-builder */
649
656
  patchMeDisciplines(args: RequestArgs & { body: PatchMeDisciplinesRequest }): Promise<PatchMeDisciplinesResponse>;
650
657
  /** GET /me/display-name — rank: any-builder */
@@ -405,6 +405,10 @@ export function createClient(opts = {}) {
405
405
  getMeAchievements: (args) => request("GET", "/me/achievements", { hasBody: false }, args),
406
406
  // POST /me/anthropic-link — rank: any-builder — POST /me/anthropic-link
407
407
  postMeAnthropicLink: (args) => request("POST", "/me/anthropic-link", { hasBody: true }, args),
408
+ // GET /me/cross-project — rank: any-builder — GET /me/cross-project
409
+ getMeCrossProject: (args) => request("GET", "/me/cross-project", { hasBody: false }, args),
410
+ // PATCH /me/cross-project — rank: any-builder — PATCH /me/cross-project
411
+ patchMeCrossProject: (args) => request("PATCH", "/me/cross-project", { hasBody: true }, args),
408
412
  // PATCH /me/disciplines — rank: any-builder — PATCH /me/disciplines
409
413
  patchMeDisciplines: (args) => request("PATCH", "/me/disciplines", { hasBody: true }, args),
410
414
  // GET /me/display-name — rank: any-builder — GET /me/display-name
@@ -6267,6 +6267,91 @@
6267
6267
  ]
6268
6268
  }
6269
6269
  },
6270
+ "/me/cross-project": {
6271
+ "get": {
6272
+ "operationId": "get_me_cross_project",
6273
+ "tags": [
6274
+ "me"
6275
+ ],
6276
+ "summary": "GET /me/cross-project",
6277
+ "description": "the caller's OWN cross-project record + hide flag (own data).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6278
+ "x-rank": "any-builder",
6279
+ "x-source": "modules/platform-identity/routes/profile.js",
6280
+ "responses": {
6281
+ "200": {
6282
+ "description": "Success.",
6283
+ "content": {
6284
+ "application/json": {
6285
+ "schema": {
6286
+ "$ref": "#/components/schemas/GetMeCrossProjectResponse"
6287
+ }
6288
+ }
6289
+ }
6290
+ },
6291
+ "400": {
6292
+ "$ref": "#/components/responses/BadRequest"
6293
+ },
6294
+ "401": {
6295
+ "$ref": "#/components/responses/Unauthorized"
6296
+ },
6297
+ "403": {
6298
+ "$ref": "#/components/responses/Forbidden"
6299
+ }
6300
+ },
6301
+ "security": [
6302
+ {
6303
+ "builderSession": []
6304
+ }
6305
+ ]
6306
+ },
6307
+ "patch": {
6308
+ "operationId": "patch_me_cross_project",
6309
+ "tags": [
6310
+ "me"
6311
+ ],
6312
+ "summary": "PATCH /me/cross-project",
6313
+ "description": "flip the caller's OWN hide flag (C2's self-serve opt-out; own data, keyed on the authenticated github_id).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6314
+ "x-rank": "any-builder",
6315
+ "x-source": "modules/platform-identity/routes/profile.js",
6316
+ "requestBody": {
6317
+ "required": true,
6318
+ "content": {
6319
+ "application/json": {
6320
+ "schema": {
6321
+ "$ref": "#/components/schemas/PatchMeCrossProjectRequest"
6322
+ }
6323
+ }
6324
+ },
6325
+ "x-validated": true
6326
+ },
6327
+ "responses": {
6328
+ "200": {
6329
+ "description": "Success.",
6330
+ "content": {
6331
+ "application/json": {
6332
+ "schema": {
6333
+ "$ref": "#/components/schemas/PatchMeCrossProjectResponse"
6334
+ }
6335
+ }
6336
+ }
6337
+ },
6338
+ "400": {
6339
+ "$ref": "#/components/responses/ValidationFailed"
6340
+ },
6341
+ "401": {
6342
+ "$ref": "#/components/responses/Unauthorized"
6343
+ },
6344
+ "403": {
6345
+ "$ref": "#/components/responses/Forbidden"
6346
+ }
6347
+ },
6348
+ "security": [
6349
+ {
6350
+ "builderSession": []
6351
+ }
6352
+ ]
6353
+ }
6354
+ },
6270
6355
  "/me/disciplines": {
6271
6356
  "patch": {
6272
6357
  "operationId": "patch_me_disciplines",
@@ -12617,7 +12702,8 @@
12617
12702
  "builder": {},
12618
12703
  "shipped_count": {},
12619
12704
  "recent_ships": {},
12620
- "achievements": {}
12705
+ "achievements": {},
12706
+ "cross_project": {}
12621
12707
  },
12622
12708
  "required": [
12623
12709
  "builder",
@@ -12849,6 +12935,21 @@
12849
12935
  "unlocked"
12850
12936
  ]
12851
12937
  },
12938
+ "GetMeCrossProjectResponse": {
12939
+ "type": "object",
12940
+ "properties": {
12941
+ "hide_stats": {
12942
+ "type": "boolean"
12943
+ },
12944
+ "profile_state": {},
12945
+ "cross_project": {}
12946
+ },
12947
+ "required": [
12948
+ "hide_stats",
12949
+ "profile_state",
12950
+ "cross_project"
12951
+ ]
12952
+ },
12852
12953
  "GetMeDisplayNameResponse": {
12853
12954
  "type": "object",
12854
12955
  "properties": {
@@ -13807,6 +13908,29 @@
13807
13908
  "idea"
13808
13909
  ]
13809
13910
  },
13911
+ "PatchMeCrossProjectRequest": {
13912
+ "type": "object",
13913
+ "properties": {
13914
+ "hide_stats": {
13915
+ "type": "boolean"
13916
+ }
13917
+ },
13918
+ "required": [
13919
+ "hide_stats"
13920
+ ],
13921
+ "additionalProperties": false
13922
+ },
13923
+ "PatchMeCrossProjectResponse": {
13924
+ "type": "object",
13925
+ "properties": {
13926
+ "hide_stats": {
13927
+ "type": "boolean"
13928
+ }
13929
+ },
13930
+ "required": [
13931
+ "hide_stats"
13932
+ ]
13933
+ },
13810
13934
  "PatchMeDisciplinesRequest": {
13811
13935
  "type": "object",
13812
13936
  "properties": {
@@ -17098,9 +17222,9 @@
17098
17222
  "description": "A required dependency/feature is not configured or is temporarily down."
17099
17223
  }
17100
17224
  },
17101
- "x-endpoint-count": 271,
17102
- "x-schema-count": 303,
17225
+ "x-endpoint-count": 273,
17226
+ "x-schema-count": 306,
17103
17227
  "x-undocumented-bodies": 8,
17104
- "x-response-schemas": 205,
17228
+ "x-response-schemas": 207,
17105
17229
  "x-generated-by": "scripts/gds/gen-api-docs.js"
17106
17230
  }
@@ -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. 271 endpoints across 44 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 273 endpoints across 45 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`.
@@ -282,13 +282,15 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
282
282
  | POST | `/api/bongos/llm-cache/lookup` | `metic+archon` | `cache_key`, `tokens_saved_est` | POST /llm-cache/lookup — hit/miss + atomic hit_count bump. |
283
283
  | POST | `/api/bongos/llm-cache/store` | `metic+archon` | `spec`, `result_stdout`, `result_cost_usd` | POST /llm-cache/store — upsert a freshly-produced result. |
284
284
 
285
- ## `me` (21)
285
+ ## `me` (23)
286
286
 
287
287
  | Method | Path | Rank | Body | Description |
288
288
  |---|---|---|---|---|
289
289
  | GET | `/api/bongos/me` | `any-builder` | — | PMS-V2 task 188: response now also carries `unlocked` (server-joined achievement metadata) + `locked_with_progress` (server-computed huma… |
290
290
  | GET | `/api/bongos/me/achievements` | `any-builder` | — | The builder's unlocked achievements (joined to achievement metadata). |
291
291
  | POST | `/api/bongos/me/anthropic-link` | `any-builder` | `anthropic_email`, `anthropic_user_id` | V3.R10 (task 235), criterion C3 — link the authed builder's Anthropic account. |
292
+ | GET | `/api/bongos/me/cross-project` | `any-builder` | — | the caller's OWN cross-project record + hide flag (own data). |
293
+ | PATCH | `/api/bongos/me/cross-project` | `any-builder` | `hide_stats` | flip the caller's OWN hide flag (C2's self-serve opt-out; own data, keyed on the authenticated github_id). |
292
294
  | PATCH | `/api/bongos/me/disciplines` | `any-builder` | `preferred_disciplines` | Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). |
293
295
  | GET | `/api/bongos/me/display-name` | `any-builder` | — | Per-builder DISPLAY NAME (task 1669). |
294
296
  | PATCH | `/api/bongos/me/display-name` | `any-builder` | _undocumented_ | PATCH the display name. |
@@ -408,6 +408,10 @@ function createClient(opts = {}) {
408
408
  getMeAchievements: (args) => request("GET", "/me/achievements", { hasBody: false }, args),
409
409
  // POST /me/anthropic-link — rank: any-builder — POST /me/anthropic-link
410
410
  postMeAnthropicLink: (args) => request("POST", "/me/anthropic-link", { hasBody: true }, args),
411
+ // GET /me/cross-project — rank: any-builder — GET /me/cross-project
412
+ getMeCrossProject: (args) => request("GET", "/me/cross-project", { hasBody: false }, args),
413
+ // PATCH /me/cross-project — rank: any-builder — PATCH /me/cross-project
414
+ patchMeCrossProject: (args) => request("PATCH", "/me/cross-project", { hasBody: true }, args),
411
415
  // PATCH /me/disciplines — rank: any-builder — PATCH /me/disciplines
412
416
  patchMeDisciplines: (args) => request("PATCH", "/me/disciplines", { hasBody: true }, args),
413
417
  // GET /me/display-name — rank: any-builder — GET /me/display-name
@@ -79,6 +79,20 @@
79
79
  <p class="section-note">Saves when you press Save; shows everywhere at once.</p>
80
80
  </section>
81
81
 
82
+ <!-- Cross-project record (platform-identity module, ADR 0171 / task 1002279).
83
+ Revealed only when the module's own endpoint answers; hidden on a
84
+ vanilla instance. P04 later moves this into the Profile rail group. -->
85
+ <section class="scroll" id="cross-project-scroll" aria-labelledby="cross-project-h" data-group="account" hidden>
86
+ <h2 id="cross-project-h" class="scroll__h">Cross-project record</h2>
87
+ <p class="scroll__lede">
88
+ Your track record across every project you build on, shown on your
89
+ public profile. Hiding it takes effect immediately everywhere —
90
+ your profile, the People directory, and recruiting views.
91
+ </p>
92
+ <div id="cross-project-rows"></div>
93
+ <p class="settings-status" id="cross-project-status" role="status" aria-live="polite"></p>
94
+ </section>
95
+
82
96
  <!-- CRAFT — discipline preferences (GET /me, PATCH /me/disciplines). -->
83
97
  <section class="scroll" id="craft-scroll" aria-labelledby="craft-h" data-group="account" hidden>
84
98
  <h2 id="craft-h" class="scroll__h">Preferred disciplines</h2>
@@ -550,6 +550,86 @@
550
550
  }
551
551
  }
552
552
 
553
+ // ---- section: CROSS-PROJECT RECORD (hide flag — ADR 0171 D4, task 1002279)
554
+ //
555
+ // GET/PATCH /api/bongos/me/cross-project (platform-identity module — hub only).
556
+ // One on/off toggle: "show my cross-project record on my public profile".
557
+ // Enforcement is server-side in the module's read functions, so flipping it
558
+ // takes effect immediately on the profile, /people, and /scouting. The section
559
+ // reveals ONLY when the module's endpoint answers (404 on a vanilla instance →
560
+ // stays hidden, no error state). P04 later re-homes this in the Profile rail
561
+ // group; storage is account-global on the hub (not behavior_prefs).
562
+ function renderCrossProject(data) {
563
+ const wrap = $('#cross-project-rows');
564
+ if (!wrap) return;
565
+ const hidden = !!(data && data.hide_stats);
566
+ const on = !hidden; // the toggle reads as "shown"
567
+ const cp = data && data.cross_project;
568
+ const totals = cp && cp.totals ? cp.totals : null;
569
+ const totalsLine = totals
570
+ ? `Your record: ${totals.projects} project${totals.projects === 1 ? '' : 's'} · ` +
571
+ `${totals.credits} credits · ${totals.works_shipped} works shipped · ${totals.karma} karma.`
572
+ : 'No cross-project activity reported yet.';
573
+ const consentNote = data && data.profile_state !== 'active'
574
+ ? ' Your profile publishes after your next sign-in at the hub.'
575
+ : '';
576
+ wrap.innerHTML =
577
+ '<div class="sound-row" data-cross-project="hide">' +
578
+ '<div class="sound-row__text">' +
579
+ '<div class="sound-row__label">Show my cross-project record</div>' +
580
+ `<div class="sound-row__desc">${escapeHtml(totalsLine + consentNote)} You always see your own numbers here.</div>` +
581
+ '</div>' +
582
+ `<button type="button" class="sound-toggle" data-on="${on ? '1' : '0'}" aria-pressed="${on ? 'true' : 'false'}">${on ? 'Shown' : 'Hidden'}</button>` +
583
+ '</div>';
584
+ }
585
+
586
+ // PATCH the hide flag. Body: { hide_stats: <bool> } (routes/profile.js).
587
+ async function saveCrossProject(hide, btn) {
588
+ const status = $('#cross-project-status');
589
+ if (status) status.textContent = 'Saving…';
590
+ if (btn) btn.disabled = true;
591
+ try {
592
+ const res = await api.request('PATCH', `${API}/me/cross-project`, { body: { hide_stats: hide } });
593
+ if (res.status === 401) { toAuth(); return; }
594
+ if (!res.ok) throw new Error(`cross-project PATCH → ${res.status}`);
595
+ await loadCrossProject(); // re-render from the server's truth (flag + record)
596
+ const msg = hide
597
+ ? 'Cross-project record hidden — removed from your profile and directories immediately.'
598
+ : 'Cross-project record shown on your public profile.';
599
+ if (status) status.textContent = msg;
600
+ toast(msg);
601
+ } catch (err) {
602
+ console.error('[settings] save cross-project failed', err);
603
+ if (status) status.textContent = 'Could not save. Try again.';
604
+ toast('Could not save your cross-project preference. Try again.');
605
+ if (btn) btn.disabled = false;
606
+ }
607
+ }
608
+
609
+ let crossProjectWired = false;
610
+ async function loadCrossProject() {
611
+ const section = $('#cross-project-scroll');
612
+ if (!section) return;
613
+ try {
614
+ const res = await api.request('GET', `${API}/me/cross-project`);
615
+ if (res.status === 401) { toAuth(); return; }
616
+ if (!res.ok) return; // module off / route absent → the section stays hidden
617
+ renderCrossProject(res.data);
618
+ section.hidden = false;
619
+ if (!crossProjectWired) {
620
+ crossProjectWired = true;
621
+ $('#cross-project-rows').addEventListener('click', (e) => {
622
+ const b = e.target.closest('.sound-toggle');
623
+ if (!b || b.disabled) return;
624
+ saveCrossProject(b.dataset.on === '1', b); // shown → hide; hidden → show
625
+ });
626
+ }
627
+ } catch (err) {
628
+ // Network/parse failure on an optional module section — stay hidden, log only.
629
+ console.error('[settings] failed to load cross-project', err);
630
+ }
631
+ }
632
+
553
633
  // ---- section 2: CRAFT (discipline preferences) ---------------------------
554
634
 
555
635
  // Valid disciplines are limited (see me.js + db.updateBuilderDisciplines):
@@ -1098,6 +1178,7 @@
1098
1178
  const PANEL_ANCHORS = {
1099
1179
  'connections': 'connections-scroll',
1100
1180
  'display-name': 'display-name-scroll',
1181
+ 'cross-project': 'cross-project-scroll',
1101
1182
  'disciplines': 'craft-scroll',
1102
1183
  'cli': 'cli-scroll',
1103
1184
  'art-key': 'art-key',
@@ -1250,6 +1331,9 @@
1250
1331
  await loadWandering();
1251
1332
  // Rendering loads independently too (rich in-feed cards on/off, task 1279).
1252
1333
  await loadRender();
1334
+ // Cross-project record (hide flag) — reveals only where the platform-identity
1335
+ // module answers (the hub); silent no-op elsewhere (task 1002279).
1336
+ await loadCrossProject();
1253
1337
  // Image key (per-builder Gemini key, task 1013) — own try/catch; `me` carries
1254
1338
  // the `needs` art_key item that drives the covered/action-needed banner.
1255
1339
  await loadArtKey(me);