@bongos/core 1.19.180 → 1.19.182
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 +42 -27
- 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 +81 -4
- package/docs/api-reference.md +3 -2
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/economy/credits.js +73 -0
- package/modules/economy/reward.js +2 -0
- package/modules/hall-ui/public/profile.js +1 -1
- package/modules/lifecycle/db.js +13 -3
- package/modules/platform-identity/migrations/platform_identity_009_profile_fields.sql +38 -0
- package/modules/platform-identity/platform-identity.js +201 -3
- package/modules/platform-identity/routes/profile.js +63 -1
- package/modules/platform-identity/routes/public-profile.js +41 -2
- package/modules/platform-identity/tests/platform-identity.mjs +90 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +5 -1
- package/tests/hub_profile_leak.mjs +11 -6
- package/tests/idea_task_ship_credit.mjs +117 -0
- package/tests/profile_fields.mjs +133 -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.182",
|
|
6
|
+
"core_contract": "1.19.182",
|
|
7
|
+
"source_commit": "e5417ea88504c51b0cc9af06d143ec9b3d37c0ed",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-16T21:
|
|
9
|
+
"built_at": "2026-08-16T21:13:59.751Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 308,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1279,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1608,
|
|
20
|
+
"tree_sha256": "101a4745dd8d3b2a32eb0658b962706986782e31b92eb968862d929b7e5e05b7",
|
|
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": "4801db32c6f4ba6220bce8e664be063f8d8483bc22a57df08205b0fc36788b8b"
|
|
351
351
|
},
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "0d3fc054ed48e1e9398366c75e526e52c3b9ecf96b70888d98607e8aa0e68949"
|
|
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": "53dc2ac9322bdc1827fae124789e0cd8b09751c5359e1ae0266b65951a90126a"
|
|
366
366
|
},
|
|
367
367
|
{
|
|
368
368
|
"path": "clients/bongos-client/index.d.ts",
|
|
369
369
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
370
|
+
"sha256": "a775432136dc7ba0093a989991adf3f639793a287919dccc002eeaf026dacf6b"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.mjs",
|
|
374
374
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
375
|
+
"sha256": "3588010536522ef306ab7e822bdb68dcc40ef42754d5b298384dac443f9ae0c6"
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
378
|
"path": "clients/bongos-client/package.json",
|
|
@@ -1362,12 +1362,12 @@
|
|
|
1362
1362
|
{
|
|
1363
1363
|
"path": "docs/api-reference.md",
|
|
1364
1364
|
"mode": "0000644",
|
|
1365
|
-
"sha256": "
|
|
1365
|
+
"sha256": "b311208b348d4e94ca20536ae095098007f855ef1861169a15e534dbb2cf6ab4"
|
|
1366
1366
|
},
|
|
1367
1367
|
{
|
|
1368
1368
|
"path": "docs/api/openapi.json",
|
|
1369
1369
|
"mode": "0000644",
|
|
1370
|
-
"sha256": "
|
|
1370
|
+
"sha256": "c414eadf025db00d4e87b2cadd5a7c6b18a55780ac2af6bfe0cafc9897ae4512"
|
|
1371
1371
|
},
|
|
1372
1372
|
{
|
|
1373
1373
|
"path": "docs/architecture.md",
|
|
@@ -2677,7 +2677,7 @@
|
|
|
2677
2677
|
{
|
|
2678
2678
|
"path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
|
|
2679
2679
|
"mode": "0000644",
|
|
2680
|
-
"sha256": "
|
|
2680
|
+
"sha256": "53dc2ac9322bdc1827fae124789e0cd8b09751c5359e1ae0266b65951a90126a"
|
|
2681
2681
|
},
|
|
2682
2682
|
{
|
|
2683
2683
|
"path": "modules/dev-box/app/test/unit.mjs",
|
|
@@ -2842,7 +2842,7 @@
|
|
|
2842
2842
|
{
|
|
2843
2843
|
"path": "modules/economy/credits.js",
|
|
2844
2844
|
"mode": "0000644",
|
|
2845
|
-
"sha256": "
|
|
2845
|
+
"sha256": "71248889315a29d2a1714ad55ffc685987d862b74e877a29ac2de010bea140f3"
|
|
2846
2846
|
},
|
|
2847
2847
|
{
|
|
2848
2848
|
"path": "modules/economy/migrations/economy_001_fix_gds_shipper_description.sql",
|
|
@@ -2857,7 +2857,7 @@
|
|
|
2857
2857
|
{
|
|
2858
2858
|
"path": "modules/economy/reward.js",
|
|
2859
2859
|
"mode": "0000644",
|
|
2860
|
-
"sha256": "
|
|
2860
|
+
"sha256": "59952daf3cb8cadc33f5249fb07552949d390ba37c71299117a2d503f83e422a"
|
|
2861
2861
|
},
|
|
2862
2862
|
{
|
|
2863
2863
|
"path": "modules/economy/routes/cost.js",
|
|
@@ -3337,7 +3337,7 @@
|
|
|
3337
3337
|
{
|
|
3338
3338
|
"path": "modules/hall-ui/public/profile.js",
|
|
3339
3339
|
"mode": "0000644",
|
|
3340
|
-
"sha256": "
|
|
3340
|
+
"sha256": "ddd95350fa5c3696452996d4c79bb7e9c5d4d2b1034ed31a082dd568195b6543"
|
|
3341
3341
|
},
|
|
3342
3342
|
{
|
|
3343
3343
|
"path": "modules/hall-ui/public/ranks.html",
|
|
@@ -3532,7 +3532,7 @@
|
|
|
3532
3532
|
{
|
|
3533
3533
|
"path": "modules/lifecycle/db.js",
|
|
3534
3534
|
"mode": "0000644",
|
|
3535
|
-
"sha256": "
|
|
3535
|
+
"sha256": "3b7e1979609fa7ba55253e193596d8d0db169925574934083232057dcd1b3e6a"
|
|
3536
3536
|
},
|
|
3537
3537
|
{
|
|
3538
3538
|
"path": "modules/lifecycle/done-when.js",
|
|
@@ -3814,6 +3814,11 @@
|
|
|
3814
3814
|
"mode": "0000644",
|
|
3815
3815
|
"sha256": "f78eb8f7b6ee1ea3ddd789d6019b9715ae193ff0cb7890aeb24d8473033a911a"
|
|
3816
3816
|
},
|
|
3817
|
+
{
|
|
3818
|
+
"path": "modules/platform-identity/migrations/platform_identity_009_profile_fields.sql",
|
|
3819
|
+
"mode": "0000644",
|
|
3820
|
+
"sha256": "00e2e9feccc56bdb30a5e4f0c6abbe610382fe425222419963a04ae022d3c58a"
|
|
3821
|
+
},
|
|
3817
3822
|
{
|
|
3818
3823
|
"path": "modules/platform-identity/module.json",
|
|
3819
3824
|
"mode": "0000644",
|
|
@@ -3822,7 +3827,7 @@
|
|
|
3822
3827
|
{
|
|
3823
3828
|
"path": "modules/platform-identity/platform-identity.js",
|
|
3824
3829
|
"mode": "0000644",
|
|
3825
|
-
"sha256": "
|
|
3830
|
+
"sha256": "423afc175f0e1024d39fc20b561e24b423e2d9b6e5c16ddcd8e4a3329bcfa97b"
|
|
3826
3831
|
},
|
|
3827
3832
|
{
|
|
3828
3833
|
"path": "modules/platform-identity/pollers/code-sweep.js",
|
|
@@ -3842,7 +3847,7 @@
|
|
|
3842
3847
|
{
|
|
3843
3848
|
"path": "modules/platform-identity/routes/profile.js",
|
|
3844
3849
|
"mode": "0000644",
|
|
3845
|
-
"sha256": "
|
|
3850
|
+
"sha256": "2e158331e7cae0535ae81d63b6b7e8d471330c0f3d732f7e3092e45ad8255916"
|
|
3846
3851
|
},
|
|
3847
3852
|
{
|
|
3848
3853
|
"path": "modules/platform-identity/routes/projects.js",
|
|
@@ -3852,7 +3857,7 @@
|
|
|
3852
3857
|
{
|
|
3853
3858
|
"path": "modules/platform-identity/routes/public-profile.js",
|
|
3854
3859
|
"mode": "0000644",
|
|
3855
|
-
"sha256": "
|
|
3860
|
+
"sha256": "e59f99d6f323e70611a08fa2c8299af815e350dbb81bd7cc79e9d96bd93cdbba"
|
|
3856
3861
|
},
|
|
3857
3862
|
{
|
|
3858
3863
|
"path": "modules/platform-identity/routes/scouting.js",
|
|
@@ -3867,7 +3872,7 @@
|
|
|
3867
3872
|
{
|
|
3868
3873
|
"path": "modules/platform-identity/tests/platform-identity.mjs",
|
|
3869
3874
|
"mode": "0000644",
|
|
3870
|
-
"sha256": "
|
|
3875
|
+
"sha256": "514adcaae952190d418888ffb778d541a632e3040664ce53f7a55ba9a297292b"
|
|
3871
3876
|
},
|
|
3872
3877
|
{
|
|
3873
3878
|
"path": "modules/platform-identity/ui/.gitkeep",
|
|
@@ -4242,12 +4247,12 @@
|
|
|
4242
4247
|
{
|
|
4243
4248
|
"path": "package-lock.json",
|
|
4244
4249
|
"mode": "0000644",
|
|
4245
|
-
"sha256": "
|
|
4250
|
+
"sha256": "1817517e0566226b12320fb61a3a216cbb08c4536cd0e5b959567438b81f9993"
|
|
4246
4251
|
},
|
|
4247
4252
|
{
|
|
4248
4253
|
"path": "package.json",
|
|
4249
4254
|
"mode": "0000644",
|
|
4250
|
-
"sha256": "
|
|
4255
|
+
"sha256": "090d46542c940a8327bb953057f47a8e51e56c9ecc86755af99a7e941eea4247"
|
|
4251
4256
|
},
|
|
4252
4257
|
{
|
|
4253
4258
|
"path": "public-docs/index.html",
|
|
@@ -5852,7 +5857,7 @@
|
|
|
5852
5857
|
{
|
|
5853
5858
|
"path": "src/module-api.js",
|
|
5854
5859
|
"mode": "0000644",
|
|
5855
|
-
"sha256": "
|
|
5860
|
+
"sha256": "bcbce9e29c6f05fc39ad8e52b4aa13b170962a06dbd3b6b5befba810a48e29d8"
|
|
5856
5861
|
},
|
|
5857
5862
|
{
|
|
5858
5863
|
"path": "src/module-loader/catalog.js",
|
|
@@ -6967,7 +6972,7 @@
|
|
|
6967
6972
|
{
|
|
6968
6973
|
"path": "tests/hub_profile_leak.mjs",
|
|
6969
6974
|
"mode": "0000644",
|
|
6970
|
-
"sha256": "
|
|
6975
|
+
"sha256": "ea992d1ab2ddedc27aaa5348a397356bef91a4c1ad9b295eb1a0ed1c4fc707e9"
|
|
6971
6976
|
},
|
|
6972
6977
|
{
|
|
6973
6978
|
"path": "tests/idea_completeness.mjs",
|
|
@@ -6999,6 +7004,11 @@
|
|
|
6999
7004
|
"mode": "0000644",
|
|
7000
7005
|
"sha256": "cd782459f1e4e6ca6df8a0349521aedcc6a867128240a78d2f00e15f0fd5f259"
|
|
7001
7006
|
},
|
|
7007
|
+
{
|
|
7008
|
+
"path": "tests/idea_task_ship_credit.mjs",
|
|
7009
|
+
"mode": "0000644",
|
|
7010
|
+
"sha256": "e7f0807491c094fddedd518380af73a98c7ac17ac9d42736d9ed9a7cd6d4bf51"
|
|
7011
|
+
},
|
|
7002
7012
|
{
|
|
7003
7013
|
"path": "tests/idea_templates.mjs",
|
|
7004
7014
|
"mode": "0000644",
|
|
@@ -7429,6 +7439,11 @@
|
|
|
7429
7439
|
"mode": "0000644",
|
|
7430
7440
|
"sha256": "3c85d28ecc55e375988f3e55aee993c8c84220889678262d8207146c2772f3f5"
|
|
7431
7441
|
},
|
|
7442
|
+
{
|
|
7443
|
+
"path": "tests/profile_fields.mjs",
|
|
7444
|
+
"mode": "0000644",
|
|
7445
|
+
"sha256": "ff73579dd2416a81648d85dcd5d1a77cb776c32047bd0cc7897dff132cbae5b7"
|
|
7446
|
+
},
|
|
7432
7447
|
{
|
|
7433
7448
|
"path": "tests/profile_rollup_consent.mjs",
|
|
7434
7449
|
"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
|
+
- 276 operations across 46 resource groups
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -433,6 +433,8 @@ function createClient(opts = {}) {
|
|
|
433
433
|
getMeModelAllocation: (args) => request("GET", "/me/model-allocation", { hasBody: false }, args),
|
|
434
434
|
// PATCH /me/model-allocation — rank: any-builder — PATCH /me/model-allocation
|
|
435
435
|
patchMeModelAllocation: (args) => request("PATCH", "/me/model-allocation", { hasBody: true }, args),
|
|
436
|
+
// PATCH /me/profile — rank: any-builder — PATCH /me/profile
|
|
437
|
+
patchMeProfile: (args) => request("PATCH", "/me/profile", { hasBody: true }, args),
|
|
436
438
|
// GET /me/recent-ships — rank: any-builder — GET /me/recent-ships
|
|
437
439
|
getMeRecentShips: (args) => request("GET", "/me/recent-ships", { hasBody: false }, args),
|
|
438
440
|
// GET /me/render — rank: any-builder — GET /me/render
|
|
@@ -432,6 +432,8 @@ function createClient(opts = {}) {
|
|
|
432
432
|
getMeModelAllocation: (args) => request("GET", "/me/model-allocation", { hasBody: false }, args),
|
|
433
433
|
// PATCH /me/model-allocation — rank: any-builder — PATCH /me/model-allocation
|
|
434
434
|
patchMeModelAllocation: (args) => request("PATCH", "/me/model-allocation", { hasBody: true }, args),
|
|
435
|
+
// PATCH /me/profile — rank: any-builder — PATCH /me/profile
|
|
436
|
+
patchMeProfile: (args) => request("PATCH", "/me/profile", { hasBody: true }, args),
|
|
435
437
|
// GET /me/recent-ships — rank: any-builder — GET /me/recent-ships
|
|
436
438
|
getMeRecentShips: (args) => request("GET", "/me/recent-ships", { hasBody: false }, args),
|
|
437
439
|
// GET /me/render — rank: any-builder — GET /me/render
|
|
@@ -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; handle: unknown; cross_project: unknown }
|
|
54
|
+
export interface GetMeCrossProjectResponse { hide_stats: boolean; profile_state: unknown; handle: unknown; display_name: unknown; bio: unknown; links: 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 }
|
|
@@ -134,6 +134,8 @@ export interface PatchMeDisplayNameResponse { display_name: unknown; max_length:
|
|
|
134
134
|
export interface PatchMeEventSoundPrefsResponse { prefs: unknown; effective: unknown; effective_wav: unknown; events: unknown }
|
|
135
135
|
export interface PatchMeHandleRequest { handle: string }
|
|
136
136
|
export interface PatchMeHandleResponse { handle: unknown; previous_handle: unknown }
|
|
137
|
+
export interface PatchMeProfileRequest { display_name?: unknown; bio?: unknown; links?: unknown }
|
|
138
|
+
export interface PatchMeProfileResponse { display_name: unknown; bio: unknown; links: unknown }
|
|
137
139
|
export interface PatchMeSkillPrefsResponse { prefs: unknown; effective: unknown; defaults: unknown; known_skills: unknown; allowed_models: unknown }
|
|
138
140
|
export interface PatchMeSoundPrefsResponse { prefs: unknown; effective: unknown; effective_map: unknown; volume: unknown; defaults: unknown; known_sounds: unknown }
|
|
139
141
|
export interface PatchProjectsIdFeaturedRequest { featured: boolean }
|
|
@@ -675,6 +677,8 @@ export interface BongosClient {
|
|
|
675
677
|
getMeModelAllocation(args?: RequestArgs): Promise<ApiResponse>;
|
|
676
678
|
/** PATCH /me/model-allocation — rank: any-builder */
|
|
677
679
|
patchMeModelAllocation(args?: RequestArgs): Promise<ApiResponse>;
|
|
680
|
+
/** PATCH /me/profile — rank: any-builder */
|
|
681
|
+
patchMeProfile(args?: RequestArgs & { body?: PatchMeProfileRequest }): Promise<PatchMeProfileResponse>;
|
|
678
682
|
/** GET /me/recent-ships — rank: any-builder */
|
|
679
683
|
getMeRecentShips(args?: RequestArgs): Promise<GetMeRecentShipsResponse>;
|
|
680
684
|
/** GET /me/render — rank: any-builder */
|
|
@@ -429,6 +429,8 @@ export function createClient(opts = {}) {
|
|
|
429
429
|
getMeModelAllocation: (args) => request("GET", "/me/model-allocation", { hasBody: false }, args),
|
|
430
430
|
// PATCH /me/model-allocation — rank: any-builder — PATCH /me/model-allocation
|
|
431
431
|
patchMeModelAllocation: (args) => request("PATCH", "/me/model-allocation", { hasBody: true }, args),
|
|
432
|
+
// PATCH /me/profile — rank: any-builder — PATCH /me/profile
|
|
433
|
+
patchMeProfile: (args) => request("PATCH", "/me/profile", { hasBody: true }, args),
|
|
432
434
|
// GET /me/recent-ships — rank: any-builder — GET /me/recent-ships
|
|
433
435
|
getMeRecentShips: (args) => request("GET", "/me/recent-ships", { hasBody: false }, args),
|
|
434
436
|
// GET /me/render — rank: any-builder — GET /me/render
|
package/docs/api/openapi.json
CHANGED
|
@@ -6774,6 +6774,55 @@
|
|
|
6774
6774
|
]
|
|
6775
6775
|
}
|
|
6776
6776
|
},
|
|
6777
|
+
"/me/profile": {
|
|
6778
|
+
"patch": {
|
|
6779
|
+
"operationId": "patch_me_profile",
|
|
6780
|
+
"tags": [
|
|
6781
|
+
"me"
|
|
6782
|
+
],
|
|
6783
|
+
"summary": "PATCH /me/profile",
|
|
6784
|
+
"description": "the caller's OWN profile fields (P02, task 1002798; spec Decision 4): bio, typed links, account display name. Own data, keyed on the authenticated github_id. The schema declares the keys for strict mode; the REAL validation (bio length/charset, https-only + host-pinned links, name length) lives in the domain, next to the data, and each field is nullable (null clears), which validateOrRespond's typed rules can't express.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
6785
|
+
"x-rank": "any-builder",
|
|
6786
|
+
"x-source": "modules/platform-identity/routes/profile.js",
|
|
6787
|
+
"requestBody": {
|
|
6788
|
+
"required": false,
|
|
6789
|
+
"content": {
|
|
6790
|
+
"application/json": {
|
|
6791
|
+
"schema": {
|
|
6792
|
+
"$ref": "#/components/schemas/PatchMeProfileRequest"
|
|
6793
|
+
}
|
|
6794
|
+
}
|
|
6795
|
+
},
|
|
6796
|
+
"x-validated": true
|
|
6797
|
+
},
|
|
6798
|
+
"responses": {
|
|
6799
|
+
"200": {
|
|
6800
|
+
"description": "Success.",
|
|
6801
|
+
"content": {
|
|
6802
|
+
"application/json": {
|
|
6803
|
+
"schema": {
|
|
6804
|
+
"$ref": "#/components/schemas/PatchMeProfileResponse"
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
},
|
|
6809
|
+
"400": {
|
|
6810
|
+
"$ref": "#/components/responses/ValidationFailed"
|
|
6811
|
+
},
|
|
6812
|
+
"401": {
|
|
6813
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
6814
|
+
},
|
|
6815
|
+
"403": {
|
|
6816
|
+
"$ref": "#/components/responses/Forbidden"
|
|
6817
|
+
}
|
|
6818
|
+
},
|
|
6819
|
+
"security": [
|
|
6820
|
+
{
|
|
6821
|
+
"builderSession": []
|
|
6822
|
+
}
|
|
6823
|
+
]
|
|
6824
|
+
}
|
|
6825
|
+
},
|
|
6777
6826
|
"/me/recent-ships": {
|
|
6778
6827
|
"get": {
|
|
6779
6828
|
"operationId": "get_me_recent_ships",
|
|
@@ -8174,7 +8223,7 @@
|
|
|
8174
8223
|
"profiles"
|
|
8175
8224
|
],
|
|
8176
8225
|
"summary": "GET /profiles/:handle",
|
|
8177
|
-
"description": "a handle-addressed public profile. Every field is already world-readable on the numeric profile route + the leaderboard; the handle is just the rename-proof address (spec Decision 3). Whitelisting happens inside the module (getPublicProfileByHandle); no-store because the payload embeds cross_project and hide must beat the cache (ADR 0171 D5).\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8226
|
+
"description": "a handle-addressed public profile. Every field is already world-readable on the numeric profile route + the leaderboard; the handle is just the rename-proof address (spec Decision 3). Whitelisting happens inside the module (getPublicProfileByHandle); no-store because the payload embeds cross_project and hide must beat the cache (ADR 0171 D5). Rate-limited like /public/* (per-IP read limiter) so the handle→identity mapping can't be scripted-enumerated at line rate (R05 grade advisory, task 1002798).\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8178
8227
|
"x-rank": "public",
|
|
8179
8228
|
"x-source": "modules/platform-identity/routes/public-profile.js",
|
|
8180
8229
|
"parameters": [
|
|
@@ -13038,12 +13087,18 @@
|
|
|
13038
13087
|
},
|
|
13039
13088
|
"profile_state": {},
|
|
13040
13089
|
"handle": {},
|
|
13090
|
+
"display_name": {},
|
|
13091
|
+
"bio": {},
|
|
13092
|
+
"links": {},
|
|
13041
13093
|
"cross_project": {}
|
|
13042
13094
|
},
|
|
13043
13095
|
"required": [
|
|
13044
13096
|
"hide_stats",
|
|
13045
13097
|
"profile_state",
|
|
13046
13098
|
"handle",
|
|
13099
|
+
"display_name",
|
|
13100
|
+
"bio",
|
|
13101
|
+
"links",
|
|
13047
13102
|
"cross_project"
|
|
13048
13103
|
]
|
|
13049
13104
|
},
|
|
@@ -14117,6 +14172,28 @@
|
|
|
14117
14172
|
"previous_handle"
|
|
14118
14173
|
]
|
|
14119
14174
|
},
|
|
14175
|
+
"PatchMeProfileRequest": {
|
|
14176
|
+
"type": "object",
|
|
14177
|
+
"properties": {
|
|
14178
|
+
"display_name": {},
|
|
14179
|
+
"bio": {},
|
|
14180
|
+
"links": {}
|
|
14181
|
+
},
|
|
14182
|
+
"additionalProperties": false
|
|
14183
|
+
},
|
|
14184
|
+
"PatchMeProfileResponse": {
|
|
14185
|
+
"type": "object",
|
|
14186
|
+
"properties": {
|
|
14187
|
+
"display_name": {},
|
|
14188
|
+
"bio": {},
|
|
14189
|
+
"links": {}
|
|
14190
|
+
},
|
|
14191
|
+
"required": [
|
|
14192
|
+
"display_name",
|
|
14193
|
+
"bio",
|
|
14194
|
+
"links"
|
|
14195
|
+
]
|
|
14196
|
+
},
|
|
14120
14197
|
"PatchMeSkillPrefsResponse": {
|
|
14121
14198
|
"type": "object",
|
|
14122
14199
|
"properties": {
|
|
@@ -17355,9 +17432,9 @@
|
|
|
17355
17432
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
17356
17433
|
}
|
|
17357
17434
|
},
|
|
17358
|
-
"x-endpoint-count":
|
|
17359
|
-
"x-schema-count":
|
|
17435
|
+
"x-endpoint-count": 276,
|
|
17436
|
+
"x-schema-count": 311,
|
|
17360
17437
|
"x-undocumented-bodies": 8,
|
|
17361
|
-
"x-response-schemas":
|
|
17438
|
+
"x-response-schemas": 210,
|
|
17362
17439
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
17363
17440
|
}
|
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. 276 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`.
|
|
@@ -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` (25)
|
|
286
286
|
|
|
287
287
|
| Method | Path | Rank | Body | Description |
|
|
288
288
|
|---|---|---|---|---|
|
|
@@ -301,6 +301,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
301
301
|
| PATCH | `/api/bongos/me/interaction` | `any-builder` | _undocumented_ | PATCH the interaction profile. |
|
|
302
302
|
| GET | `/api/bongos/me/model-allocation` | `any-builder` | — | |
|
|
303
303
|
| PATCH | `/api/bongos/me/model-allocation` | `any-builder` | _undocumented_ | PATCH the model allocation. |
|
|
304
|
+
| PATCH | `/api/bongos/me/profile` | `any-builder` | `display_name`, `bio`, `links` | the caller's OWN profile fields (P02, task 1002798; spec Decision 4): bio, typed links, account display name. |
|
|
304
305
|
| GET | `/api/bongos/me/recent-ships` | `any-builder` | — | Tasks this builder has shipped, most recent first. |
|
|
305
306
|
| GET | `/api/bongos/me/render` | `any-builder` | — | Per-builder "render widgets" knob (task 1279, shares the behavior_prefs jsonb / migration 119). |
|
|
306
307
|
| PATCH | `/api/bongos/me/render` | `any-builder` | _undocumented_ | PATCH the render knob. |
|
|
@@ -432,6 +432,8 @@ function createClient(opts = {}) {
|
|
|
432
432
|
getMeModelAllocation: (args) => request("GET", "/me/model-allocation", { hasBody: false }, args),
|
|
433
433
|
// PATCH /me/model-allocation — rank: any-builder — PATCH /me/model-allocation
|
|
434
434
|
patchMeModelAllocation: (args) => request("PATCH", "/me/model-allocation", { hasBody: true }, args),
|
|
435
|
+
// PATCH /me/profile — rank: any-builder — PATCH /me/profile
|
|
436
|
+
patchMeProfile: (args) => request("PATCH", "/me/profile", { hasBody: true }, args),
|
|
435
437
|
// GET /me/recent-ships — rank: any-builder — GET /me/recent-ships
|
|
436
438
|
getMeRecentShips: (args) => request("GET", "/me/recent-ships", { hasBody: false }, args),
|
|
437
439
|
// GET /me/render — rank: any-builder — GET /me/render
|
|
@@ -117,6 +117,8 @@ const IDEA_BONUS_FRACTION = 0.25; // 25% slice to the idea's original capturer
|
|
|
117
117
|
// (per-task-ship IC4, governance-pass IC5) will be siblings of this function.
|
|
118
118
|
const IDEA_FULL_PASS_CREDIT = 5; // owner: "gives 5 credits"
|
|
119
119
|
const IDEA_FULL_PASS_BAR = 60; // completeness 0-100; ADR 0172 proposed default
|
|
120
|
+
const IDEA_TASK_SHIP_BASE = 5; // stream 1: base credit per shipped task under an idea
|
|
121
|
+
const QUICK_IDEA_FACTOR = 0.6; // a quick/spark idea's grade factor (ADR 0172 default)
|
|
120
122
|
|
|
121
123
|
// =========================================================================
|
|
122
124
|
// Session token reward (flat cost-plus) — task 1005 (ADR 0054).
|
|
@@ -385,6 +387,74 @@ async function awardIdeaFullPassCredit(client, { ideaId, authorId, completenessS
|
|
|
385
387
|
: { credited: 0, reason: 'already_paid' };
|
|
386
388
|
}
|
|
387
389
|
|
|
390
|
+
// Stream 1 (ADR 0172 / goal 1000067 IC4): as each task descended from an idea
|
|
391
|
+
// SHIPS, pay the idea's author IDEA_TASK_SHIP_BASE credits, SCALED by the idea's
|
|
392
|
+
// grade — a Full Idea by its completeness, a Quick/Spark idea by a flat factor.
|
|
393
|
+
// The ideator lane, so it gates on config.ideatorCredit, never perTaskCredit.
|
|
394
|
+
//
|
|
395
|
+
// THIS REPLACES the ADR 0023 25% idea-promotion slice (maybeAwardIdeaPromotionBonus).
|
|
396
|
+
// The lifecycle ship hook (awardLandingCredit) now calls THIS instead of the
|
|
397
|
+
// slice, so there is one idea-credit-on-ship path, not two (ADR 0172 §4). The
|
|
398
|
+
// old function stays for its unit tests + any compat caller, but is no longer
|
|
399
|
+
// wired at ship.
|
|
400
|
+
//
|
|
401
|
+
// LINEAGE READ, NOT A CODE IMPORT. It reads the ideas-owned lineage + grade
|
|
402
|
+
// tables directly (ideas_task_lineage → idea_inbox → ideas_grades), exactly as
|
|
403
|
+
// maybeAwardIdeaPromotionBonus reads idea_inbox — a cross-table SQL read is
|
|
404
|
+
// allowed across the module boundary; a cross-module require is not.
|
|
405
|
+
//
|
|
406
|
+
// client — pg client / pool (transaction participant)
|
|
407
|
+
// taskId — the task that just shipped
|
|
408
|
+
// config — resolved reward policy; gates on config.ideatorCredit
|
|
409
|
+
//
|
|
410
|
+
// Returns { credited, reason, ideaId, authorId } — credited 0 with a reason for
|
|
411
|
+
// every no-pay path (no source idea, lane off, already paid). Idempotent per
|
|
412
|
+
// (idea, task) via reason='idea.credit.task_ship:<idea>:<task>', builder-scoped
|
|
413
|
+
// so the NOT EXISTS hits idx_credit_log_builder (the IC2 index lesson).
|
|
414
|
+
async function awardIdeaTaskShipCredit(client, { taskId, config = rewardConfig() } = {}) {
|
|
415
|
+
if (config && config.ideatorCredit === false) {
|
|
416
|
+
return { credited: 0, reason: 'ideator_lane_off' };
|
|
417
|
+
}
|
|
418
|
+
// Which idea does this task descend from, who authored it, and at what grade?
|
|
419
|
+
const { rows } = await client.query(
|
|
420
|
+
`SELECT l.idea_id,
|
|
421
|
+
i.captured_by,
|
|
422
|
+
COALESCE(g.grade, 'quick') AS grade,
|
|
423
|
+
g.completeness_score AS completeness
|
|
424
|
+
FROM ideas_task_lineage l
|
|
425
|
+
JOIN idea_inbox i ON i.id = l.idea_id
|
|
426
|
+
LEFT JOIN ideas_grades g ON g.idea_id = l.idea_id
|
|
427
|
+
WHERE l.task_id = $1`,
|
|
428
|
+
[taskId]
|
|
429
|
+
);
|
|
430
|
+
if (rows.length === 0 || rows[0].captured_by == null) {
|
|
431
|
+
return { credited: 0, reason: 'no_source_idea', ideaId: null, authorId: null };
|
|
432
|
+
}
|
|
433
|
+
const { idea_id: ideaId, captured_by: authorId, grade, completeness } = rows[0];
|
|
434
|
+
// Grade factor: a Full Idea earns in proportion to its completeness; a Quick
|
|
435
|
+
// or Spark idea (no completeness score) earns the flat quick factor. A full
|
|
436
|
+
// idea with no score yet also falls back to the quick factor rather than 0 —
|
|
437
|
+
// the work shipped, the idea is at least quick-grade.
|
|
438
|
+
const factor = (grade === 'full' && completeness != null && Number.isFinite(Number(completeness)))
|
|
439
|
+
? Math.max(0, Math.min(1, Number(completeness) / 100))
|
|
440
|
+
: QUICK_IDEA_FACTOR;
|
|
441
|
+
const delta = Math.round(IDEA_TASK_SHIP_BASE * factor);
|
|
442
|
+
if (delta <= 0) {
|
|
443
|
+
return { credited: 0, reason: 'zero_after_scaling', ideaId: Number(ideaId), authorId: Number(authorId) };
|
|
444
|
+
}
|
|
445
|
+
const reason = `idea.credit.task_ship:${ideaId}:${taskId}`;
|
|
446
|
+
const description = `Task #${taskId} shipped under idea #${ideaId} (${grade}${completeness != null ? ` ${Math.round(Number(completeness))}%` : ''}) → ${delta}c to its author (ideator lane stream 1, ADR 0172)`;
|
|
447
|
+
const { rowCount } = await client.query(
|
|
448
|
+
`INSERT INTO credit_log (builder_id, task_id, delta, reason, description)
|
|
449
|
+
SELECT $1, $2, $3, $4, $5
|
|
450
|
+
WHERE NOT EXISTS (SELECT 1 FROM credit_log WHERE builder_id = $1 AND reason = $4)`,
|
|
451
|
+
[authorId, taskId, delta, reason, description]
|
|
452
|
+
);
|
|
453
|
+
return rowCount > 0
|
|
454
|
+
? { credited: delta, reason: 'paid', ideaId: Number(ideaId), authorId: Number(authorId) }
|
|
455
|
+
: { credited: 0, reason: 'already_paid', ideaId: Number(ideaId), authorId: Number(authorId) };
|
|
456
|
+
}
|
|
457
|
+
|
|
388
458
|
// Award the flat cost-plus session token reward, idempotent per session_id
|
|
389
459
|
// (task 1005, ADR 0054). Called inside the same transaction as the session
|
|
390
460
|
// upsert (see upsertSessionRecordWithReward).
|
|
@@ -596,8 +666,11 @@ module.exports = {
|
|
|
596
666
|
insertMultipliedConfirmCredit,
|
|
597
667
|
maybeAwardIdeaPromotionBonus,
|
|
598
668
|
awardIdeaFullPassCredit,
|
|
669
|
+
awardIdeaTaskShipCredit,
|
|
599
670
|
IDEA_FULL_PASS_CREDIT,
|
|
600
671
|
IDEA_FULL_PASS_BAR,
|
|
672
|
+
IDEA_TASK_SHIP_BASE,
|
|
673
|
+
QUICK_IDEA_FACTOR,
|
|
601
674
|
awardSessionTokenReward,
|
|
602
675
|
NET_NEGATIVE_BONUS,
|
|
603
676
|
SUBTRACTOR_THRESHOLD,
|
|
@@ -26,6 +26,8 @@ module.exports = {
|
|
|
26
26
|
maybeAwardIdeaPromotionBonus: (...a) => credits.maybeAwardIdeaPromotionBonus(...a),
|
|
27
27
|
// ADR 0172 IC2 — the ideator credit lane (stream 2): a passing Full Idea pays its author, once.
|
|
28
28
|
awardIdeaFullPassCredit: (...a) => credits.awardIdeaFullPassCredit(...a),
|
|
29
|
+
// ADR 0172 IC4 — stream 1: pay the idea's author per shipped task, grade-scaled (replaces the 25% slice at ship).
|
|
30
|
+
awardIdeaTaskShipCredit: (...a) => credits.awardIdeaTaskShipCredit(...a),
|
|
29
31
|
awardNetNegativeBonus: (...a) => credits.awardNetNegativeBonus(...a),
|
|
30
32
|
awardSessionTokenReward: (...a) => credits.awardSessionTokenReward(...a),
|
|
31
33
|
// gamification hooks the lifecycle fires at claim/ship
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
const name = escapeHtml(p.name || 'Project');
|
|
178
178
|
// origin is third-party-reported; link only a well-formed https URL.
|
|
179
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;
|
|
180
|
+
const nameCell = origin ? `<a href="${escapeHtml(origin)}" rel="noopener noreferrer">${name}</a>` : name;
|
|
181
181
|
// rank_held is THAT project's standing as it reported it — plain text, never
|
|
182
182
|
// the local rank badge or the instance's own rank labels (spec Decision 1).
|
|
183
183
|
const held = typeof p.rank_held === 'string' && p.rank_held
|
package/modules/lifecycle/db.js
CHANGED
|
@@ -3597,9 +3597,19 @@ async function awardLandingCredit(client, { taskId, creditedBuilderId, creditsRe
|
|
|
3597
3597
|
const credit = await reward.insertMultipliedConfirmCredit(
|
|
3598
3598
|
client, creditedBuilderId, taskId, creditsReward, kind, 'task.shipped'
|
|
3599
3599
|
);
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
)
|
|
3600
|
+
// Stream 1 of the ideator credit lane (ADR 0172 / IC4) REPLACES the ADR 0023
|
|
3601
|
+
// 25% idea-promotion slice here — one idea-credit-on-ship path, not two
|
|
3602
|
+
// (ADR 0172 §4). Unlike the slice (25% of the builder estimate, so zero under
|
|
3603
|
+
// cost-plus-only), this pays 5×grade-factor on the IDEATOR lane, so an idea
|
|
3604
|
+
// earns as its work ships even when per-task builder credit is withheld. It
|
|
3605
|
+
// reads the one-idea-many-tasks lineage (ideas_task_lineage, IC3), so a Full
|
|
3606
|
+
// Idea that became a whole goal pays on every one of its shipped tasks — the
|
|
3607
|
+
// old slice only saw the single promoted_to_task_id. `maybeAwardIdeaPromotionBonus`
|
|
3608
|
+
// stays on the port for its unit tests / any compat caller, but is no longer
|
|
3609
|
+
// wired at ship. Guarded so a null return (lane off, no source idea) is fine.
|
|
3610
|
+
const ideaBonus = reward.awardIdeaTaskShipCredit
|
|
3611
|
+
? await reward.awardIdeaTaskShipCredit(client, { taskId })
|
|
3612
|
+
: null;
|
|
3603
3613
|
return {
|
|
3604
3614
|
creditsAwarded: credit.creditsAwarded,
|
|
3605
3615
|
creditsRaw: credit.raw,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- platform_identity_009_profile_fields.sql — bio + typed links + the
|
|
2
|
+
-- display-name source bit (P02, task 1002798 / goal 1000045; profile-page spec
|
|
3
|
+
-- Decision 4, ADR 0171 amendments R01).
|
|
4
|
+
--
|
|
5
|
+
-- bio — plain text, ~280 chars, NO markdown and no auto-linking. The length
|
|
6
|
+
-- cap + charset live in the domain validator (validateProfileBio in
|
|
7
|
+
-- platform-identity.js — the only writer); nullable = never set.
|
|
8
|
+
-- links — a TYPED, capped set as a jsonb object whose only keys are
|
|
9
|
+
-- website | x | linkedin | discord, each an https URL (max 4 by
|
|
10
|
+
-- construction — one per type). Typed-and-capped rather than a
|
|
11
|
+
-- free-form list because a public, indexable page with
|
|
12
|
+
-- user-controlled links is an SEO-spam magnet (spec Decision 4).
|
|
13
|
+
-- Validation (https-only, no userinfo, per-type host pinning) lives
|
|
14
|
+
-- in validateProfileLinks — the single write path; nullable = never set.
|
|
15
|
+
-- display_name_source — the ADR 0156 mirror for the HUB account: 'github'
|
|
16
|
+
-- (default; upsertAccount keeps re-syncing the name on every
|
|
17
|
+
-- check-in/authorize) or 'user' (set by setAccountProfileFields; the
|
|
18
|
+
-- upsertAccount conflict branch then never overwrites the name).
|
|
19
|
+
-- Module-owned here — unlike core_197 the guard reads it inside this
|
|
20
|
+
-- module's own upsertAccount, so it belongs on the module's table
|
|
21
|
+
-- (ADR 0083 §5).
|
|
22
|
+
--
|
|
23
|
+
-- Additive + platform_identity_-namespaced (ADR 0083 §5). Idempotent: the
|
|
24
|
+
-- inline CHECK rides the ADD COLUMN IF NOT EXISTS, so a re-run is a no-op.
|
|
25
|
+
|
|
26
|
+
BEGIN;
|
|
27
|
+
|
|
28
|
+
ALTER TABLE platform_identity_accounts
|
|
29
|
+
ADD COLUMN IF NOT EXISTS bio text,
|
|
30
|
+
ADD COLUMN IF NOT EXISTS links jsonb,
|
|
31
|
+
ADD COLUMN IF NOT EXISTS display_name_source text NOT NULL DEFAULT 'github'
|
|
32
|
+
CHECK (display_name_source IN ('github', 'user'));
|
|
33
|
+
|
|
34
|
+
-- 'github' is correct for every pre-existing row: before this change there was
|
|
35
|
+
-- no user-set account display name, so whatever is stored IS GitHub-derived
|
|
36
|
+
-- (the ADR 0156 backfill argument, unchanged).
|
|
37
|
+
|
|
38
|
+
COMMIT;
|