@bongos/core 1.19.170 → 1.19.172
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 +39 -24
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +5 -1
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +79 -3
- package/docs/api-reference.md +3 -2
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/hall-ui/public/profile.html +13 -1
- package/modules/hall-ui/public/profile.js +98 -5
- package/modules/platform-identity/migrations/platform_identity_008_handle.sql +70 -0
- package/modules/platform-identity/platform-identity.js +140 -5
- package/modules/platform-identity/routes/profile.js +47 -1
- package/modules/platform-identity/tests/platform-identity.mjs +139 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/hall-preview/server.js +1 -0
- package/src/module-api.js +5 -1
- package/tests/handle_machinery.mjs +115 -0
- package/tests/profile_ui_cross_project.mjs +182 -0
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.172",
|
|
6
|
+
"core_contract": "1.19.172",
|
|
7
|
+
"source_commit": "d488f4a69b30ec2fe81f95cc1ec652c25af8fc68",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-16T19:39:18.102Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 305,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1271,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1597,
|
|
20
|
+
"tree_sha256": "c7aad1a023cefa6bce6c0403ed5d0bf9c1e5a28b4e38e14a85f1cfc697d5edb3",
|
|
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": "
|
|
350
|
+
"sha256": "a13c27a7d671408579dedf417b7f28486bebc52b7a685ba3900cd4eca843957c"
|
|
351
351
|
},
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "7b6abb75150b8fdc9fba1e0d765c049979da7cdd1d6a20eeeb6f3d5e3886ebc7"
|
|
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": "
|
|
365
|
+
"sha256": "a4a864366450b849bafc096807f37cd16c8ed624470473aaf4907b24ab104778"
|
|
366
366
|
},
|
|
367
367
|
{
|
|
368
368
|
"path": "clients/bongos-client/index.d.ts",
|
|
369
369
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
370
|
+
"sha256": "c032e9796a9feeee86929323992511d5ed1cb448975481f98f86cee1b3790d50"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.mjs",
|
|
374
374
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
375
|
+
"sha256": "cc177720f5f3b0971edac3f03464e3dd5930b48d12811cd9ab39a7b6ceaaeb9c"
|
|
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": "
|
|
1350
|
+
"sha256": "d1595faad24aafba420199b3115b11ee5387de7c97c7f4fe7fe4f138f43dd79a"
|
|
1351
1351
|
},
|
|
1352
1352
|
{
|
|
1353
1353
|
"path": "docs/api/openapi.json",
|
|
1354
1354
|
"mode": "0000644",
|
|
1355
|
-
"sha256": "
|
|
1355
|
+
"sha256": "1435287ef26983d7088555abc9f18df97ceb4a8676be091ff49076e54a4366ab"
|
|
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": "
|
|
2665
|
+
"sha256": "a4a864366450b849bafc096807f37cd16c8ed624470473aaf4907b24ab104778"
|
|
2666
2666
|
},
|
|
2667
2667
|
{
|
|
2668
2668
|
"path": "modules/dev-box/app/test/unit.mjs",
|
|
@@ -3317,12 +3317,12 @@
|
|
|
3317
3317
|
{
|
|
3318
3318
|
"path": "modules/hall-ui/public/profile.html",
|
|
3319
3319
|
"mode": "0000644",
|
|
3320
|
-
"sha256": "
|
|
3320
|
+
"sha256": "b8d5fb31d92f6d65e8f257d10c77f4ee0aa0ebec50d977d4c7d918ff2253da1e"
|
|
3321
3321
|
},
|
|
3322
3322
|
{
|
|
3323
3323
|
"path": "modules/hall-ui/public/profile.js",
|
|
3324
3324
|
"mode": "0000644",
|
|
3325
|
-
"sha256": "
|
|
3325
|
+
"sha256": "a4cf0c4c2d088fd1fb84c41c93cc28e2acd2b656b0bc995cd46043881b3611fa"
|
|
3326
3326
|
},
|
|
3327
3327
|
{
|
|
3328
3328
|
"path": "modules/hall-ui/public/ranks.html",
|
|
@@ -3789,6 +3789,11 @@
|
|
|
3789
3789
|
"mode": "0000644",
|
|
3790
3790
|
"sha256": "cce2f971f030aa628f9d7855f2e421595ea71cb314e90965206dbe970b7beded"
|
|
3791
3791
|
},
|
|
3792
|
+
{
|
|
3793
|
+
"path": "modules/platform-identity/migrations/platform_identity_008_handle.sql",
|
|
3794
|
+
"mode": "0000644",
|
|
3795
|
+
"sha256": "f78eb8f7b6ee1ea3ddd789d6019b9715ae193ff0cb7890aeb24d8473033a911a"
|
|
3796
|
+
},
|
|
3792
3797
|
{
|
|
3793
3798
|
"path": "modules/platform-identity/module.json",
|
|
3794
3799
|
"mode": "0000644",
|
|
@@ -3797,7 +3802,7 @@
|
|
|
3797
3802
|
{
|
|
3798
3803
|
"path": "modules/platform-identity/platform-identity.js",
|
|
3799
3804
|
"mode": "0000644",
|
|
3800
|
-
"sha256": "
|
|
3805
|
+
"sha256": "115be49e667716d760610f8a9b167eeea4e0e6b61c40c7b9a439703847b61dcd"
|
|
3801
3806
|
},
|
|
3802
3807
|
{
|
|
3803
3808
|
"path": "modules/platform-identity/pollers/code-sweep.js",
|
|
@@ -3817,7 +3822,7 @@
|
|
|
3817
3822
|
{
|
|
3818
3823
|
"path": "modules/platform-identity/routes/profile.js",
|
|
3819
3824
|
"mode": "0000644",
|
|
3820
|
-
"sha256": "
|
|
3825
|
+
"sha256": "29e7f6304b4215fd79c35662c48370a04a5a9ffa2c3c4ae3d1fabf277d407eb2"
|
|
3821
3826
|
},
|
|
3822
3827
|
{
|
|
3823
3828
|
"path": "modules/platform-identity/routes/projects.js",
|
|
@@ -3837,7 +3842,7 @@
|
|
|
3837
3842
|
{
|
|
3838
3843
|
"path": "modules/platform-identity/tests/platform-identity.mjs",
|
|
3839
3844
|
"mode": "0000644",
|
|
3840
|
-
"sha256": "
|
|
3845
|
+
"sha256": "4b7f13effc33d5d16a5f87d0915ed31e107f138ef135822745774f90192ad327"
|
|
3841
3846
|
},
|
|
3842
3847
|
{
|
|
3843
3848
|
"path": "modules/platform-identity/ui/.gitkeep",
|
|
@@ -4212,12 +4217,12 @@
|
|
|
4212
4217
|
{
|
|
4213
4218
|
"path": "package-lock.json",
|
|
4214
4219
|
"mode": "0000644",
|
|
4215
|
-
"sha256": "
|
|
4220
|
+
"sha256": "3da96cec73d1af6c4f1470d29cc26187cc949eba5b6fb7291b89da3da4c7eae7"
|
|
4216
4221
|
},
|
|
4217
4222
|
{
|
|
4218
4223
|
"path": "package.json",
|
|
4219
4224
|
"mode": "0000644",
|
|
4220
|
-
"sha256": "
|
|
4225
|
+
"sha256": "dbf95e145339c9e8d52b1e532e452eb2d344c0c0f06a28f58c6e19366e256dd6"
|
|
4221
4226
|
},
|
|
4222
4227
|
{
|
|
4223
4228
|
"path": "public-docs/index.html",
|
|
@@ -5477,7 +5482,7 @@
|
|
|
5477
5482
|
{
|
|
5478
5483
|
"path": "scripts/hall-preview/server.js",
|
|
5479
5484
|
"mode": "0000644",
|
|
5480
|
-
"sha256": "
|
|
5485
|
+
"sha256": "1cd66475d610b107b0f3b7f19688133e7c482b41b034e2cef6009d552df31cb2"
|
|
5481
5486
|
},
|
|
5482
5487
|
{
|
|
5483
5488
|
"path": "scripts/migrate.sh",
|
|
@@ -5822,7 +5827,7 @@
|
|
|
5822
5827
|
{
|
|
5823
5828
|
"path": "src/module-api.js",
|
|
5824
5829
|
"mode": "0000644",
|
|
5825
|
-
"sha256": "
|
|
5830
|
+
"sha256": "bc1f9966a0040b5239664c1a5d993c302b1fa9c56d2080c97b168115a4da847a"
|
|
5826
5831
|
},
|
|
5827
5832
|
{
|
|
5828
5833
|
"path": "src/module-loader/catalog.js",
|
|
@@ -6904,6 +6909,11 @@
|
|
|
6904
6909
|
"mode": "0000644",
|
|
6905
6910
|
"sha256": "82bf1cc68150c247c108308d360d6408511f31a7af11d5e7a4721e7ea282f2bb"
|
|
6906
6911
|
},
|
|
6912
|
+
{
|
|
6913
|
+
"path": "tests/handle_machinery.mjs",
|
|
6914
|
+
"mode": "0000644",
|
|
6915
|
+
"sha256": "755f49404e97c60c8c264f5f4c9d563a7c4ee4f51b43afe96fd10acce52ebe7b"
|
|
6916
|
+
},
|
|
6907
6917
|
{
|
|
6908
6918
|
"path": "tests/helpers.mjs",
|
|
6909
6919
|
"mode": "0000644",
|
|
@@ -7389,6 +7399,11 @@
|
|
|
7389
7399
|
"mode": "0000644",
|
|
7390
7400
|
"sha256": "3b3045a6143d67c963516ed5703b5dabb9b8945a392118721e6a0a56258f1732"
|
|
7391
7401
|
},
|
|
7402
|
+
{
|
|
7403
|
+
"path": "tests/profile_ui_cross_project.mjs",
|
|
7404
|
+
"mode": "0000644",
|
|
7405
|
+
"sha256": "6a7a223a678b56333befaed017429e5b9d8a81e4405efae72a23355902517d9d"
|
|
7406
|
+
},
|
|
7392
7407
|
{
|
|
7393
7408
|
"path": "tests/project_stats.mjs",
|
|
7394
7409
|
"mode": "0000644",
|
|
@@ -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
|
-
-
|
|
8
|
+
- 274 operations across 45 resource groups
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -423,6 +423,8 @@ function createClient(opts = {}) {
|
|
|
423
423
|
getMeEventSoundPrefs: (args) => request("GET", "/me/event-sound-prefs", { hasBody: false }, args),
|
|
424
424
|
// PATCH /me/event-sound-prefs — rank: any-builder — PATCH /me/event-sound-prefs
|
|
425
425
|
patchMeEventSoundPrefs: (args) => request("PATCH", "/me/event-sound-prefs", { hasBody: true }, args),
|
|
426
|
+
// PATCH /me/handle — rank: any-builder — PATCH /me/handle
|
|
427
|
+
patchMeHandle: (args) => request("PATCH", "/me/handle", { hasBody: true }, args),
|
|
426
428
|
// GET /me/interaction — rank: any-builder — GET /me/interaction
|
|
427
429
|
getMeInteraction: (args) => request("GET", "/me/interaction", { hasBody: false }, args),
|
|
428
430
|
// PATCH /me/interaction — rank: any-builder — PATCH /me/interaction
|
|
@@ -422,6 +422,8 @@ function createClient(opts = {}) {
|
|
|
422
422
|
getMeEventSoundPrefs: (args) => request("GET", "/me/event-sound-prefs", { hasBody: false }, args),
|
|
423
423
|
// PATCH /me/event-sound-prefs — rank: any-builder — PATCH /me/event-sound-prefs
|
|
424
424
|
patchMeEventSoundPrefs: (args) => request("PATCH", "/me/event-sound-prefs", { hasBody: true }, args),
|
|
425
|
+
// PATCH /me/handle — rank: any-builder — PATCH /me/handle
|
|
426
|
+
patchMeHandle: (args) => request("PATCH", "/me/handle", { hasBody: true }, args),
|
|
425
427
|
// GET /me/interaction — rank: any-builder — GET /me/interaction
|
|
426
428
|
getMeInteraction: (args) => request("GET", "/me/interaction", { hasBody: false }, args),
|
|
427
429
|
// PATCH /me/interaction — rank: any-builder — PATCH /me/interaction
|
|
@@ -51,7 +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
|
+
export interface GetMeCrossProjectResponse { hide_stats: boolean; profile_state: unknown; handle: unknown; cross_project: unknown }
|
|
55
55
|
export interface GetMeDisplayNameResponse { display_name: unknown; max_length: unknown }
|
|
56
56
|
export interface GetMeEventSoundPrefsResponse { prefs: unknown; effective: unknown; effective_wav: unknown; events: unknown }
|
|
57
57
|
export interface GetMeRecentShipsResponse { ships: unknown }
|
|
@@ -131,6 +131,8 @@ export interface PatchMeDisciplinesRequest { preferred_disciplines: string[] }
|
|
|
131
131
|
export interface PatchMeDisciplinesResponse { builder: unknown; onboarding: unknown }
|
|
132
132
|
export interface PatchMeDisplayNameResponse { display_name: unknown; max_length: unknown }
|
|
133
133
|
export interface PatchMeEventSoundPrefsResponse { prefs: unknown; effective: unknown; effective_wav: unknown; events: unknown }
|
|
134
|
+
export interface PatchMeHandleRequest { handle: string }
|
|
135
|
+
export interface PatchMeHandleResponse { handle: unknown; previous_handle: unknown }
|
|
134
136
|
export interface PatchMeSkillPrefsResponse { prefs: unknown; effective: unknown; defaults: unknown; known_skills: unknown; allowed_models: unknown }
|
|
135
137
|
export interface PatchMeSoundPrefsResponse { prefs: unknown; effective: unknown; effective_map: unknown; volume: unknown; defaults: unknown; known_sounds: unknown }
|
|
136
138
|
export interface PatchProjectsIdFeaturedRequest { featured: boolean }
|
|
@@ -662,6 +664,8 @@ export interface BongosClient {
|
|
|
662
664
|
getMeEventSoundPrefs(args?: RequestArgs): Promise<GetMeEventSoundPrefsResponse>;
|
|
663
665
|
/** PATCH /me/event-sound-prefs — rank: any-builder */
|
|
664
666
|
patchMeEventSoundPrefs(args?: RequestArgs): Promise<PatchMeEventSoundPrefsResponse>;
|
|
667
|
+
/** PATCH /me/handle — rank: any-builder */
|
|
668
|
+
patchMeHandle(args: RequestArgs & { body: PatchMeHandleRequest }): Promise<PatchMeHandleResponse>;
|
|
665
669
|
/** GET /me/interaction — rank: any-builder */
|
|
666
670
|
getMeInteraction(args?: RequestArgs): Promise<ApiResponse>;
|
|
667
671
|
/** PATCH /me/interaction — rank: any-builder */
|
|
@@ -419,6 +419,8 @@ export function createClient(opts = {}) {
|
|
|
419
419
|
getMeEventSoundPrefs: (args) => request("GET", "/me/event-sound-prefs", { hasBody: false }, args),
|
|
420
420
|
// PATCH /me/event-sound-prefs — rank: any-builder — PATCH /me/event-sound-prefs
|
|
421
421
|
patchMeEventSoundPrefs: (args) => request("PATCH", "/me/event-sound-prefs", { hasBody: true }, args),
|
|
422
|
+
// PATCH /me/handle — rank: any-builder — PATCH /me/handle
|
|
423
|
+
patchMeHandle: (args) => request("PATCH", "/me/handle", { hasBody: true }, args),
|
|
422
424
|
// GET /me/interaction — rank: any-builder — GET /me/interaction
|
|
423
425
|
getMeInteraction: (args) => request("GET", "/me/interaction", { hasBody: false }, args),
|
|
424
426
|
// PATCH /me/interaction — rank: any-builder — PATCH /me/interaction
|
package/docs/api/openapi.json
CHANGED
|
@@ -6575,6 +6575,55 @@
|
|
|
6575
6575
|
]
|
|
6576
6576
|
}
|
|
6577
6577
|
},
|
|
6578
|
+
"/me/handle": {
|
|
6579
|
+
"patch": {
|
|
6580
|
+
"operationId": "patch_me_handle",
|
|
6581
|
+
"tags": [
|
|
6582
|
+
"me"
|
|
6583
|
+
],
|
|
6584
|
+
"summary": "PATCH /me/handle",
|
|
6585
|
+
"description": "rename the caller's OWN handle (own data, keyed on the authenticated github_id). Rules live in setAccountHandle: canonical form, reserved words refused, one rename per window, previous handle kept for the 301 window. Upsert-first (the setAccountHideStats precedent) so a hub builder who never federated can still claim a handle — never demotes consent.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
6586
|
+
"x-rank": "any-builder",
|
|
6587
|
+
"x-source": "modules/platform-identity/routes/profile.js",
|
|
6588
|
+
"requestBody": {
|
|
6589
|
+
"required": true,
|
|
6590
|
+
"content": {
|
|
6591
|
+
"application/json": {
|
|
6592
|
+
"schema": {
|
|
6593
|
+
"$ref": "#/components/schemas/PatchMeHandleRequest"
|
|
6594
|
+
}
|
|
6595
|
+
}
|
|
6596
|
+
},
|
|
6597
|
+
"x-validated": true
|
|
6598
|
+
},
|
|
6599
|
+
"responses": {
|
|
6600
|
+
"200": {
|
|
6601
|
+
"description": "Success.",
|
|
6602
|
+
"content": {
|
|
6603
|
+
"application/json": {
|
|
6604
|
+
"schema": {
|
|
6605
|
+
"$ref": "#/components/schemas/PatchMeHandleResponse"
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6608
|
+
}
|
|
6609
|
+
},
|
|
6610
|
+
"400": {
|
|
6611
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
6612
|
+
},
|
|
6613
|
+
"401": {
|
|
6614
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
6615
|
+
},
|
|
6616
|
+
"403": {
|
|
6617
|
+
"$ref": "#/components/responses/Forbidden"
|
|
6618
|
+
}
|
|
6619
|
+
},
|
|
6620
|
+
"security": [
|
|
6621
|
+
{
|
|
6622
|
+
"builderSession": []
|
|
6623
|
+
}
|
|
6624
|
+
]
|
|
6625
|
+
}
|
|
6626
|
+
},
|
|
6578
6627
|
"/me/interaction": {
|
|
6579
6628
|
"get": {
|
|
6580
6629
|
"operationId": "get_me_interaction",
|
|
@@ -12942,11 +12991,13 @@
|
|
|
12942
12991
|
"type": "boolean"
|
|
12943
12992
|
},
|
|
12944
12993
|
"profile_state": {},
|
|
12994
|
+
"handle": {},
|
|
12945
12995
|
"cross_project": {}
|
|
12946
12996
|
},
|
|
12947
12997
|
"required": [
|
|
12948
12998
|
"hide_stats",
|
|
12949
12999
|
"profile_state",
|
|
13000
|
+
"handle",
|
|
12950
13001
|
"cross_project"
|
|
12951
13002
|
]
|
|
12952
13003
|
},
|
|
@@ -13984,6 +14035,31 @@
|
|
|
13984
14035
|
"events"
|
|
13985
14036
|
]
|
|
13986
14037
|
},
|
|
14038
|
+
"PatchMeHandleRequest": {
|
|
14039
|
+
"type": "object",
|
|
14040
|
+
"properties": {
|
|
14041
|
+
"handle": {
|
|
14042
|
+
"type": "string",
|
|
14043
|
+
"minLength": 1,
|
|
14044
|
+
"maxLength": 39
|
|
14045
|
+
}
|
|
14046
|
+
},
|
|
14047
|
+
"required": [
|
|
14048
|
+
"handle"
|
|
14049
|
+
],
|
|
14050
|
+
"additionalProperties": false
|
|
14051
|
+
},
|
|
14052
|
+
"PatchMeHandleResponse": {
|
|
14053
|
+
"type": "object",
|
|
14054
|
+
"properties": {
|
|
14055
|
+
"handle": {},
|
|
14056
|
+
"previous_handle": {}
|
|
14057
|
+
},
|
|
14058
|
+
"required": [
|
|
14059
|
+
"handle",
|
|
14060
|
+
"previous_handle"
|
|
14061
|
+
]
|
|
14062
|
+
},
|
|
13987
14063
|
"PatchMeSkillPrefsResponse": {
|
|
13988
14064
|
"type": "object",
|
|
13989
14065
|
"properties": {
|
|
@@ -17222,9 +17298,9 @@
|
|
|
17222
17298
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
17223
17299
|
}
|
|
17224
17300
|
},
|
|
17225
|
-
"x-endpoint-count":
|
|
17226
|
-
"x-schema-count":
|
|
17301
|
+
"x-endpoint-count": 274,
|
|
17302
|
+
"x-schema-count": 308,
|
|
17227
17303
|
"x-undocumented-bodies": 8,
|
|
17228
|
-
"x-response-schemas":
|
|
17304
|
+
"x-response-schemas": 208,
|
|
17229
17305
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
17230
17306
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -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.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 274 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,7 +282,7 @@ 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` (
|
|
285
|
+
## `me` (24)
|
|
286
286
|
|
|
287
287
|
| Method | Path | Rank | Body | Description |
|
|
288
288
|
|---|---|---|---|---|
|
|
@@ -296,6 +296,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
296
296
|
| PATCH | `/api/bongos/me/display-name` | `any-builder` | _undocumented_ | PATCH the display name. |
|
|
297
297
|
| GET | `/api/bongos/me/event-sound-prefs` | `any-builder` | — | Per-builder per-event sound variant selection (task 582, migration 164). |
|
|
298
298
|
| PATCH | `/api/bongos/me/event-sound-prefs` | `any-builder` | _undocumented_ | PATCH a partial set of event sound overrides. |
|
|
299
|
+
| PATCH | `/api/bongos/me/handle` | `any-builder` | `handle` | rename the caller's OWN handle (own data, keyed on the authenticated github_id). |
|
|
299
300
|
| GET | `/api/bongos/me/interaction` | `any-builder` | — | Per-builder INTERACTION PROFILE (task 2010, shares the behavior_prefs jsonb / migration 119). |
|
|
300
301
|
| PATCH | `/api/bongos/me/interaction` | `any-builder` | _undocumented_ | PATCH the interaction profile. |
|
|
301
302
|
| GET | `/api/bongos/me/model-allocation` | `any-builder` | — | |
|
|
@@ -422,6 +422,8 @@ function createClient(opts = {}) {
|
|
|
422
422
|
getMeEventSoundPrefs: (args) => request("GET", "/me/event-sound-prefs", { hasBody: false }, args),
|
|
423
423
|
// PATCH /me/event-sound-prefs — rank: any-builder — PATCH /me/event-sound-prefs
|
|
424
424
|
patchMeEventSoundPrefs: (args) => request("PATCH", "/me/event-sound-prefs", { hasBody: true }, args),
|
|
425
|
+
// PATCH /me/handle — rank: any-builder — PATCH /me/handle
|
|
426
|
+
patchMeHandle: (args) => request("PATCH", "/me/handle", { hasBody: true }, args),
|
|
425
427
|
// GET /me/interaction — rank: any-builder — GET /me/interaction
|
|
426
428
|
getMeInteraction: (args) => request("GET", "/me/interaction", { hasBody: false }, args),
|
|
427
429
|
// PATCH /me/interaction — rank: any-builder — PATCH /me/interaction
|
|
@@ -40,6 +40,14 @@
|
|
|
40
40
|
</div>
|
|
41
41
|
</section>
|
|
42
42
|
|
|
43
|
+
<!-- Cross-project record — hub-only (ADR 0171). profile.js reveals this
|
|
44
|
+
only when the profile response carries a cross_project key; on a
|
|
45
|
+
vanilla instance the key is absent and the section never renders. -->
|
|
46
|
+
<section class="scroll" id="xp-scroll" aria-labelledby="xp-h" hidden>
|
|
47
|
+
<h2 id="xp-h" class="scroll__h">Cross-project record</h2>
|
|
48
|
+
<div id="xp-body"></div>
|
|
49
|
+
</section>
|
|
50
|
+
|
|
43
51
|
<!-- Achievements — the builder's earned shelf. -->
|
|
44
52
|
<section class="scroll scroll--bare" id="ach-scroll" aria-labelledby="ach-h">
|
|
45
53
|
<h2 id="ach-h" class="scroll__h">Achievements</h2>
|
|
@@ -66,6 +74,10 @@
|
|
|
66
74
|
</tbody>
|
|
67
75
|
</table>
|
|
68
76
|
</section>
|
|
77
|
+
|
|
78
|
+
<!-- Reserved slots — connections, guilds, and actions (profile-page
|
|
79
|
+
spec sections 6–8) mount here in later phases; keeping the order
|
|
80
|
+
fixed now means the page is not re-laid-out twice (Decision 5). -->
|
|
69
81
|
</main>
|
|
70
82
|
|
|
71
83
|
<footer class="app-foot" id="app-foot"></footer>
|
|
@@ -83,6 +95,6 @@
|
|
|
83
95
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
84
96
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
85
97
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75"></script>
|
|
86
|
-
<script src="/builders/profile.js?v=2026-08-
|
|
98
|
+
<script src="/builders/profile.js?v=2026-08-16-r04"></script>
|
|
87
99
|
</body>
|
|
88
100
|
</html>
|
|
@@ -160,6 +160,82 @@
|
|
|
160
160
|
}).join('');
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
// ---- render: cross-project record (hub-only, ADR 0171 / task 1002280) ----
|
|
164
|
+
//
|
|
165
|
+
// The section reveals only when the response carries a cross_project KEY —
|
|
166
|
+
// present iff the hub port resolved; on a vanilla instance the key is absent
|
|
167
|
+
// and the section stays hidden (degrade, don't 500). A null value means "no
|
|
168
|
+
// public cross-project record" — hidden, provisional, or none, deliberately
|
|
169
|
+
// indistinguishable — so all three render the same private line and NOTHING
|
|
170
|
+
// derived from the rollup (no partial numbers; a count plus a hidden total is
|
|
171
|
+
// a leak by subtraction). The response is viewer-independent (ADR 0171 D4):
|
|
172
|
+
// self is detected client-side by comparing the /me id, and the self "toggle"
|
|
173
|
+
// is a link to the real control in Settings (R03). No caching assumptions —
|
|
174
|
+
// hub profile responses are no-store (ADR 0171 D5).
|
|
175
|
+
|
|
176
|
+
function xpProjectRow(p) {
|
|
177
|
+
const name = escapeHtml(p.name || 'Project');
|
|
178
|
+
// origin is third-party-reported; link only a well-formed https URL.
|
|
179
|
+
const origin = typeof p.origin === 'string' && /^https:\/\//.test(p.origin) ? p.origin : null;
|
|
180
|
+
const nameCell = origin ? `<a href="${escapeHtml(origin)}" rel="noopener">${name}</a>` : name;
|
|
181
|
+
// rank_held is THAT project's standing as it reported it — plain text, never
|
|
182
|
+
// the local rank badge or the instance's own rank labels (spec Decision 1).
|
|
183
|
+
const held = typeof p.rank_held === 'string' && p.rank_held
|
|
184
|
+
? escapeHtml(p.rank_held.charAt(0).toUpperCase() + p.rank_held.slice(1))
|
|
185
|
+
: '—';
|
|
186
|
+
return `<tr><td>${nameCell}</td><td>${held}</td></tr>`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function renderCrossProject(data, selfId) {
|
|
190
|
+
const section = $('#xp-scroll');
|
|
191
|
+
const body = $('#xp-body');
|
|
192
|
+
if (!section || !body) return;
|
|
193
|
+
if (!data || !('cross_project' in data)) {
|
|
194
|
+
section.hidden = true;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// ids may serialize as strings (pg bigint) — compare canonicalized.
|
|
198
|
+
const isSelf = selfId != null && data.builder && String(data.builder.id) === String(selfId);
|
|
199
|
+
const manage = isSelf
|
|
200
|
+
? `<p class="scroll__lede">This is you — <a href="/settings#cross-project">manage its visibility in Settings → Cross-project record</a>.</p>`
|
|
201
|
+
: '';
|
|
202
|
+
const cp = data.cross_project;
|
|
203
|
+
if (!cp) {
|
|
204
|
+
body.innerHTML = `<p class="scroll__lede">This builder keeps their track record private.</p>${manage}`;
|
|
205
|
+
section.hidden = false;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const t = cp.totals || {};
|
|
209
|
+
const tiles =
|
|
210
|
+
`<div class="stat-row">` +
|
|
211
|
+
tile('Projects', fmtNum(t.projects)) +
|
|
212
|
+
tile('Works shipped', fmtNum(t.works_shipped)) +
|
|
213
|
+
tile('Credits', fmtNum(t.credits)) +
|
|
214
|
+
tile('Karma', fmtNum(t.karma)) +
|
|
215
|
+
`</div>`;
|
|
216
|
+
const discs = Array.isArray(cp.disciplines) ? cp.disciplines.filter((d) => typeof d === 'string') : [];
|
|
217
|
+
const metaBits = [];
|
|
218
|
+
if (discs.length) metaBits.push(`Disciplines: ${discs.join(', ')}`);
|
|
219
|
+
if (cp.last_active) metaBits.push(`Last active ${fmtDate(cp.last_active)}`);
|
|
220
|
+
const meta = metaBits.length ? `<p class="scroll__lede">${escapeHtml(metaBits.join(' · '))}</p>` : '';
|
|
221
|
+
const named = Array.isArray(cp.projects) ? cp.projects : [];
|
|
222
|
+
const moreCount = Number(cp.more_projects) || 0;
|
|
223
|
+
const projectsTable = named.length
|
|
224
|
+
? `<table class="ledger">
|
|
225
|
+
<thead><tr><th>Project</th><th title="That project's own standing, as reported by that project.">Standing there</th></tr></thead>
|
|
226
|
+
<tbody>${named.map(xpProjectRow).join('')}</tbody>
|
|
227
|
+
</table>`
|
|
228
|
+
: '';
|
|
229
|
+
const more = moreCount > 0
|
|
230
|
+
? `<p class="scroll__lede">+ ${fmtNum(moreCount)} more project${moreCount === 1 ? '' : 's'} not publicly listed.</p>`
|
|
231
|
+
: '';
|
|
232
|
+
const none = !named.length && !moreCount
|
|
233
|
+
? `<p class="scroll__lede">No cross-project activity reported yet.</p>`
|
|
234
|
+
: '';
|
|
235
|
+
body.innerHTML = tiles + meta + projectsTable + more + none + manage;
|
|
236
|
+
section.hidden = false;
|
|
237
|
+
}
|
|
238
|
+
|
|
163
239
|
// ---- states -------------------------------------------------------------
|
|
164
240
|
|
|
165
241
|
function showMessage(text) {
|
|
@@ -167,13 +243,14 @@
|
|
|
167
243
|
if (sub) sub.textContent = text;
|
|
168
244
|
}
|
|
169
245
|
|
|
170
|
-
function renderProfile(data) {
|
|
246
|
+
function renderProfile(data, selfId) {
|
|
171
247
|
const builder = data.builder || {};
|
|
172
248
|
const name = builder.display_name || builder.github_login || 'Builder';
|
|
173
249
|
const shipped = Number(data.shipped_count) || 0;
|
|
174
250
|
showMessage(`${name} — ${rankLabel(normalizeRank(builder.rank))} · ${fmtNum(shipped)} work${shipped === 1 ? '' : 's'} shipped`);
|
|
175
251
|
renderHead(builder);
|
|
176
252
|
renderNumbers(data.shipped_count, data.achievements);
|
|
253
|
+
renderCrossProject(data, selfId);
|
|
177
254
|
renderAchievements(data.achievements);
|
|
178
255
|
renderWorks(data.recent_ships);
|
|
179
256
|
}
|
|
@@ -197,23 +274,39 @@
|
|
|
197
274
|
const ach = $('#ach-grid'); if (ach) ach.innerHTML = '';
|
|
198
275
|
const works = $('#works-table tbody'); if (works) works.innerHTML = '';
|
|
199
276
|
const worksLede = $('#works-lede'); if (worksLede) worksLede.hidden = true;
|
|
277
|
+
const xp = $('#xp-scroll'); if (xp) xp.hidden = true;
|
|
200
278
|
}
|
|
201
279
|
|
|
202
|
-
async function fetchProfile(id) {
|
|
280
|
+
async function fetchProfile(id, selfId) {
|
|
203
281
|
const res = await api.request('GET', `${API}/builders/${encodeURIComponent(id)}/profile`);
|
|
204
282
|
if (res.status === 404) {
|
|
205
283
|
showMessage('No builder found with that id.');
|
|
206
284
|
return;
|
|
207
285
|
}
|
|
208
286
|
if (!res.ok) throw new Error(`profile → ${res.status}`);
|
|
209
|
-
renderProfile(res.data || {});
|
|
287
|
+
renderProfile(res.data || {}, selfId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// The viewer's own builder id, or null when signed out / unresolvable. Used
|
|
291
|
+
// ONLY for client-side self-detection (ADR 0171 D4 — the profile response is
|
|
292
|
+
// viewer-independent); a failure here just means no self link renders.
|
|
293
|
+
async function resolveSelfId() {
|
|
294
|
+
try {
|
|
295
|
+
const me = await api.request('GET', `${API}/me`);
|
|
296
|
+
if (!me.ok) return null;
|
|
297
|
+
const builder = (me.data && me.data.builder) ? me.data.builder : me.data;
|
|
298
|
+
return (builder && builder.id) || null;
|
|
299
|
+
} catch (err) {
|
|
300
|
+
console.error('[profile] /me self-detect failed', err);
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
210
303
|
}
|
|
211
304
|
|
|
212
305
|
async function load() {
|
|
213
306
|
const idParam = new URLSearchParams(location.search).get('id');
|
|
214
307
|
try {
|
|
215
308
|
if (idParam) {
|
|
216
|
-
await fetchProfile(idParam);
|
|
309
|
+
await fetchProfile(idParam, await resolveSelfId());
|
|
217
310
|
return;
|
|
218
311
|
}
|
|
219
312
|
// No id — soft-resolve the viewer's OWN id from /me (no hard redirect; a
|
|
@@ -230,7 +323,7 @@
|
|
|
230
323
|
renderEmpty();
|
|
231
324
|
return;
|
|
232
325
|
}
|
|
233
|
-
await fetchProfile(selfId);
|
|
326
|
+
await fetchProfile(selfId, selfId);
|
|
234
327
|
} catch (err) {
|
|
235
328
|
console.error('[profile] failed to load', err);
|
|
236
329
|
showMessage('Could not load this profile. Return to the hall and try again.');
|