@bongos/core 1.20.19 → 1.20.21
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 +59 -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 +4 -1
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +49 -6
- package/docs/api-reference.md +3 -2
- package/docs/module-api-changelog.md +4 -0
- package/modules/platform-identity/guild-map.js +105 -0
- package/modules/platform-identity/guild-totals.js +217 -0
- package/modules/platform-identity/guilds.js +6 -2
- package/modules/platform-identity/migrations/platform_identity_027_guild_totals.sql +45 -0
- package/modules/platform-identity/module.json +1 -1
- package/modules/platform-identity/pollers/guild-totals.js +76 -0
- package/modules/platform-identity/routes/guilds-public.js +47 -9
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/scripts/gds/run-unit-tests.js +9 -0
- package/src/module-api.js +1 -1
- package/tests/guild_map_db.mjs +157 -0
- package/tests/guild_totals.mjs +183 -0
- package/tests/guild_totals_db.mjs +292 -0
- package/tests/guilds_api.mjs +80 -1
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.20.
|
|
6
|
-
"core_contract": "1.20.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.20.21",
|
|
6
|
+
"core_contract": "1.20.21",
|
|
7
|
+
"source_commit": "21843bf1398d569536fc45f748fae3c195be4ba2",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-30T15:20:08.598Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 557,
|
|
13
13
|
"agent_docs_stubbed": 25,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2638,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 3221,
|
|
20
|
+
"tree_sha256": "07ce496b1770bfc67bcd98bdf44e2bc6a47d1f869682f5fba2db1ded196d0b07",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -327,12 +327,12 @@
|
|
|
327
327
|
{
|
|
328
328
|
"path": "clients/bongos-client/README.md",
|
|
329
329
|
"mode": "0000644",
|
|
330
|
-
"sha256": "
|
|
330
|
+
"sha256": "680d37464fa929b11cd7a02af6aa4fb144bedcde5134c3d81edac167d7b95980"
|
|
331
331
|
},
|
|
332
332
|
{
|
|
333
333
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
334
334
|
"mode": "0000644",
|
|
335
|
-
"sha256": "
|
|
335
|
+
"sha256": "c6dac0dab2b2d5fb996568cff8ead84e7f6ac9e036c3fab6a47893c79a99f8f4"
|
|
336
336
|
},
|
|
337
337
|
{
|
|
338
338
|
"path": "clients/bongos-client/examples/hello-world.mjs",
|
|
@@ -342,17 +342,17 @@
|
|
|
342
342
|
{
|
|
343
343
|
"path": "clients/bongos-client/index.cjs",
|
|
344
344
|
"mode": "0000644",
|
|
345
|
-
"sha256": "
|
|
345
|
+
"sha256": "baa7c833c3d18bf8250590fd94c499b3032ba05c6b9aa0af36b4660da295c799"
|
|
346
346
|
},
|
|
347
347
|
{
|
|
348
348
|
"path": "clients/bongos-client/index.d.ts",
|
|
349
349
|
"mode": "0000644",
|
|
350
|
-
"sha256": "
|
|
350
|
+
"sha256": "e9b2837873e241f20472ebde570b550718365a663282d4a85c255d98a8c8e21c"
|
|
351
351
|
},
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/index.mjs",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "79240ff449f616e50aca58fc310a3b0670af84dc30d7a93991d84c0d0f4b87d2"
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
"path": "clients/bongos-client/package.json",
|
|
@@ -2242,12 +2242,12 @@
|
|
|
2242
2242
|
{
|
|
2243
2243
|
"path": "docs/api-reference.md",
|
|
2244
2244
|
"mode": "0000644",
|
|
2245
|
-
"sha256": "
|
|
2245
|
+
"sha256": "36a01165649c2ca2f1e29c592332efe08f3cffcd926a547e8de4121ca05c0469"
|
|
2246
2246
|
},
|
|
2247
2247
|
{
|
|
2248
2248
|
"path": "docs/api/openapi.json",
|
|
2249
2249
|
"mode": "0000644",
|
|
2250
|
-
"sha256": "
|
|
2250
|
+
"sha256": "37b9cfbb4cce621c7ba60d358a66b618d60f6706b4b1c2dec7215c88451cff1c"
|
|
2251
2251
|
},
|
|
2252
2252
|
{
|
|
2253
2253
|
"path": "docs/architecture.md",
|
|
@@ -2777,7 +2777,7 @@
|
|
|
2777
2777
|
{
|
|
2778
2778
|
"path": "docs/module-api-changelog.md",
|
|
2779
2779
|
"mode": "0000644",
|
|
2780
|
-
"sha256": "
|
|
2780
|
+
"sha256": "5be7dcf0c4dbcd61706bbaf8fec0edc509d32b721b7be1abae250dcff896f95e"
|
|
2781
2781
|
},
|
|
2782
2782
|
{
|
|
2783
2783
|
"path": "docs/modules-contract.md",
|
|
@@ -6864,10 +6864,20 @@
|
|
|
6864
6864
|
"mode": "0000644",
|
|
6865
6865
|
"sha256": "793e96feacef39ec52166dd7372c894a25679c7137c9c3c5e9df38ec323f1c4a"
|
|
6866
6866
|
},
|
|
6867
|
+
{
|
|
6868
|
+
"path": "modules/platform-identity/guild-map.js",
|
|
6869
|
+
"mode": "0000644",
|
|
6870
|
+
"sha256": "f550b6f42ef3e37c4390a1629d4c5f109285a130d2b5efd4ccbefa57acfe2cf1"
|
|
6871
|
+
},
|
|
6872
|
+
{
|
|
6873
|
+
"path": "modules/platform-identity/guild-totals.js",
|
|
6874
|
+
"mode": "0000644",
|
|
6875
|
+
"sha256": "8e07aed97641d68d826ffea3055d209b8fd9eb172e1d000f17e335f7296cc6d6"
|
|
6876
|
+
},
|
|
6867
6877
|
{
|
|
6868
6878
|
"path": "modules/platform-identity/guilds.js",
|
|
6869
6879
|
"mode": "0000644",
|
|
6870
|
-
"sha256": "
|
|
6880
|
+
"sha256": "e048e674b087eae9035da5b3449d8f4029ec329a42333980eb21ac3e6c13a297"
|
|
6871
6881
|
},
|
|
6872
6882
|
{
|
|
6873
6883
|
"path": "modules/platform-identity/hub-device.js",
|
|
@@ -7019,10 +7029,15 @@
|
|
|
7019
7029
|
"mode": "0000644",
|
|
7020
7030
|
"sha256": "9f8d582d626dec82b55b96272f9d6d7f6c1488ac28bd9a98ab673404afde0c8e"
|
|
7021
7031
|
},
|
|
7032
|
+
{
|
|
7033
|
+
"path": "modules/platform-identity/migrations/platform_identity_027_guild_totals.sql",
|
|
7034
|
+
"mode": "0000644",
|
|
7035
|
+
"sha256": "9b263f91ce6df19640ef8ae413f3eb40cc17589924fdf21256da7647b55631c1"
|
|
7036
|
+
},
|
|
7022
7037
|
{
|
|
7023
7038
|
"path": "modules/platform-identity/module.json",
|
|
7024
7039
|
"mode": "0000644",
|
|
7025
|
-
"sha256": "
|
|
7040
|
+
"sha256": "48c9d82d9ec647430a97ba19f403b22e7eba13e16ff553b6bbd08691a8918a7b"
|
|
7026
7041
|
},
|
|
7027
7042
|
{
|
|
7028
7043
|
"path": "modules/platform-identity/origin-containment.js",
|
|
@@ -7039,6 +7054,11 @@
|
|
|
7039
7054
|
"mode": "0000644",
|
|
7040
7055
|
"sha256": "b6eea95dbe66a3126fc2c73d93237cf38dd648a803e910eb88fbd5c780ccef62"
|
|
7041
7056
|
},
|
|
7057
|
+
{
|
|
7058
|
+
"path": "modules/platform-identity/pollers/guild-totals.js",
|
|
7059
|
+
"mode": "0000644",
|
|
7060
|
+
"sha256": "cfd421477fdcee4a8a92ed30fa1bb987e9f8a055862c8564de9a9bfe8eb5e089"
|
|
7061
|
+
},
|
|
7042
7062
|
{
|
|
7043
7063
|
"path": "modules/platform-identity/pollers/visibility-pull.js",
|
|
7044
7064
|
"mode": "0000644",
|
|
@@ -7092,7 +7112,7 @@
|
|
|
7092
7112
|
{
|
|
7093
7113
|
"path": "modules/platform-identity/routes/guilds-public.js",
|
|
7094
7114
|
"mode": "0000644",
|
|
7095
|
-
"sha256": "
|
|
7115
|
+
"sha256": "3217ae9aa5d952b72711a4e723bec3c93b4b5d12975f056bb74e8e9f4ff5e7e3"
|
|
7096
7116
|
},
|
|
7097
7117
|
{
|
|
7098
7118
|
"path": "modules/platform-identity/routes/guilds.js",
|
|
@@ -8872,12 +8892,12 @@
|
|
|
8872
8892
|
{
|
|
8873
8893
|
"path": "package-lock.json",
|
|
8874
8894
|
"mode": "0000644",
|
|
8875
|
-
"sha256": "
|
|
8895
|
+
"sha256": "7ca4dcc58b8138d0f20002590f565c03952db6a97c8a740c09307c91b24872bf"
|
|
8876
8896
|
},
|
|
8877
8897
|
{
|
|
8878
8898
|
"path": "package.json",
|
|
8879
8899
|
"mode": "0000644",
|
|
8880
|
-
"sha256": "
|
|
8900
|
+
"sha256": "fc858fcc7b0fef1d6850cca8b5d5825250568cb16754f3452dc5a5d8f42545d5"
|
|
8881
8901
|
},
|
|
8882
8902
|
{
|
|
8883
8903
|
"path": "public-docs/index.html",
|
|
@@ -8897,7 +8917,7 @@
|
|
|
8897
8917
|
{
|
|
8898
8918
|
"path": "release-notes.json",
|
|
8899
8919
|
"mode": "0000644",
|
|
8900
|
-
"sha256": "
|
|
8920
|
+
"sha256": "1739d308859639e1ff64b6716cd4e04f117c094868c1ad8ad1f1fa1272232221"
|
|
8901
8921
|
},
|
|
8902
8922
|
{
|
|
8903
8923
|
"path": "scripts/bongos-mcp.js",
|
|
@@ -10057,7 +10077,7 @@
|
|
|
10057
10077
|
{
|
|
10058
10078
|
"path": "scripts/gds/run-unit-tests.js",
|
|
10059
10079
|
"mode": "0000644",
|
|
10060
|
-
"sha256": "
|
|
10080
|
+
"sha256": "8a7b0e6b5d899bc2706d952d2383ee5b45758810b7f7d5bd5b7ebc2fc547e43e"
|
|
10061
10081
|
},
|
|
10062
10082
|
{
|
|
10063
10083
|
"path": "scripts/gds/runner-drift.js",
|
|
@@ -11012,7 +11032,7 @@
|
|
|
11012
11032
|
{
|
|
11013
11033
|
"path": "src/module-api.js",
|
|
11014
11034
|
"mode": "0000644",
|
|
11015
|
-
"sha256": "
|
|
11035
|
+
"sha256": "7e01ad4572ca48ef4dba7c5776246f2e7ba1a251a1bc079f1ae0566b9dc67593"
|
|
11016
11036
|
},
|
|
11017
11037
|
{
|
|
11018
11038
|
"path": "src/module-loader/catalog.js",
|
|
@@ -13059,15 +13079,30 @@
|
|
|
13059
13079
|
"mode": "0000644",
|
|
13060
13080
|
"sha256": "6e834f3cf75dd34ba30795c46bc401098053a56c967da8661128f34db71ff8c3"
|
|
13061
13081
|
},
|
|
13082
|
+
{
|
|
13083
|
+
"path": "tests/guild_map_db.mjs",
|
|
13084
|
+
"mode": "0000644",
|
|
13085
|
+
"sha256": "cc230b6df32f9f7ab7c81d0cca88af6d0ace233c800a4d29d43cd474d0deefa1"
|
|
13086
|
+
},
|
|
13062
13087
|
{
|
|
13063
13088
|
"path": "tests/guild_namespace_reserved.mjs",
|
|
13064
13089
|
"mode": "0000644",
|
|
13065
13090
|
"sha256": "8298006ae35010d726bcac8a2d351a5aa932d2ee6d5b53ed7b8a5c095ca5e54f"
|
|
13066
13091
|
},
|
|
13092
|
+
{
|
|
13093
|
+
"path": "tests/guild_totals.mjs",
|
|
13094
|
+
"mode": "0000644",
|
|
13095
|
+
"sha256": "c488d1231e2d7b9233e7b857cf584c4c6df9c596b34c7e4a74c8d976f38d1ada"
|
|
13096
|
+
},
|
|
13097
|
+
{
|
|
13098
|
+
"path": "tests/guild_totals_db.mjs",
|
|
13099
|
+
"mode": "0000644",
|
|
13100
|
+
"sha256": "095f66255fa4755ff57db9aef07a5334f12a2f1720a71e9523eeb5d28356029a"
|
|
13101
|
+
},
|
|
13067
13102
|
{
|
|
13068
13103
|
"path": "tests/guilds_api.mjs",
|
|
13069
13104
|
"mode": "0000644",
|
|
13070
|
-
"sha256": "
|
|
13105
|
+
"sha256": "ae92262fb5fa1a79b1540538e7b9191ae47d19c3b4ae3572d07d470159f4ef91"
|
|
13071
13106
|
},
|
|
13072
13107
|
{
|
|
13073
13108
|
"path": "tests/guilds_db.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
|
-
-
|
|
8
|
+
- 462 operations across 70 resource groups
|
|
9
9
|
|
|
10
10
|
## Use it from your project
|
|
11
11
|
|
|
@@ -499,6 +499,8 @@ function createClient(opts = {}) {
|
|
|
499
499
|
postGuildRequestsIdDecline: (args) => request("POST", "/guild-requests/{id}/decline", { hasBody: true }, args),
|
|
500
500
|
},
|
|
501
501
|
"guilds": {
|
|
502
|
+
// GET /guilds — rank: public — GET /guilds
|
|
503
|
+
getGuilds: (args) => request("GET", "/guilds", { hasBody: false }, args),
|
|
502
504
|
// POST /guilds — rank: any-builder — POST /guilds
|
|
503
505
|
postGuilds: (args) => request("POST", "/guilds", { hasBody: true }, args),
|
|
504
506
|
// DELETE /guilds/{slug} — rank: any-builder — DELETE /guilds/:slug
|
|
@@ -498,6 +498,8 @@ function createClient(opts = {}) {
|
|
|
498
498
|
postGuildRequestsIdDecline: (args) => request("POST", "/guild-requests/{id}/decline", { hasBody: true }, args),
|
|
499
499
|
},
|
|
500
500
|
"guilds": {
|
|
501
|
+
// GET /guilds — rank: public — GET /guilds
|
|
502
|
+
getGuilds: (args) => request("GET", "/guilds", { hasBody: false }, args),
|
|
501
503
|
// POST /guilds — rank: any-builder — POST /guilds
|
|
502
504
|
postGuilds: (args) => request("POST", "/guilds", { hasBody: true }, args),
|
|
503
505
|
// DELETE /guilds/{slug} — rank: any-builder — DELETE /guilds/:slug
|
|
@@ -72,9 +72,10 @@ export interface GetGovernmentAssignmentsResponse { assignments: unknown }
|
|
|
72
72
|
export interface GetGovernmentPermissionsResponse { permissions: unknown; principals: unknown }
|
|
73
73
|
export interface GetGovernmentRanksResponse { ranks: unknown }
|
|
74
74
|
export interface GetGradesByBuilderResponse { window_days: unknown; builders: unknown }
|
|
75
|
+
export interface GetGuildsResponse { order: unknown; count: unknown; results: unknown; page: unknown }
|
|
75
76
|
export interface GetGuildsSlugMembersResponse { guild: unknown; you: unknown; members: unknown; count: unknown }
|
|
76
77
|
export interface GetGuildsSlugRequestsResponse { incoming: unknown; outgoing: unknown; incoming_count: unknown; outgoing_count: unknown }
|
|
77
|
-
export interface GetGuildsSlugResponse { guild: unknown; members: unknown; size: unknown }
|
|
78
|
+
export interface GetGuildsSlugResponse { guild: unknown; members: unknown; size: unknown; totals: unknown }
|
|
78
79
|
export interface GetHealthzResponse { ok: boolean; auth_configured: unknown }
|
|
79
80
|
export interface GetHelpRequestsArchiveResponse { asked_of_you: unknown; asked_of_others: unknown; count: unknown; crafts: unknown }
|
|
80
81
|
export interface GetHelpRequestsForMeResponse { help_requests: unknown; count: unknown; crafts: unknown }
|
|
@@ -925,6 +926,8 @@ export interface BongosClient {
|
|
|
925
926
|
postGuildRequestsIdDecline(args?: RequestArgs): Promise<ApiResponse>;
|
|
926
927
|
};
|
|
927
928
|
"guilds": {
|
|
929
|
+
/** GET /guilds — rank: public */
|
|
930
|
+
getGuilds(args?: RequestArgs): Promise<GetGuildsResponse>;
|
|
928
931
|
/** POST /guilds — rank: any-builder */
|
|
929
932
|
postGuilds(args: RequestArgs & { body: PostGuildsRequest }): Promise<PostGuildsResponse>;
|
|
930
933
|
/** DELETE /guilds/{slug} — rank: any-builder */
|
|
@@ -495,6 +495,8 @@ export function createClient(opts = {}) {
|
|
|
495
495
|
postGuildRequestsIdDecline: (args) => request("POST", "/guild-requests/{id}/decline", { hasBody: true }, args),
|
|
496
496
|
},
|
|
497
497
|
"guilds": {
|
|
498
|
+
// GET /guilds — rank: public — GET /guilds
|
|
499
|
+
getGuilds: (args) => request("GET", "/guilds", { hasBody: false }, args),
|
|
498
500
|
// POST /guilds — rank: any-builder — POST /guilds
|
|
499
501
|
postGuilds: (args) => request("POST", "/guilds", { hasBody: true }, args),
|
|
500
502
|
// DELETE /guilds/{slug} — rank: any-builder — DELETE /guilds/:slug
|
package/docs/api/openapi.json
CHANGED
|
@@ -8590,6 +8590,32 @@
|
|
|
8590
8590
|
}
|
|
8591
8591
|
},
|
|
8592
8592
|
"/guilds": {
|
|
8593
|
+
"get": {
|
|
8594
|
+
"operationId": "get_guilds",
|
|
8595
|
+
"tags": [
|
|
8596
|
+
"guilds"
|
|
8597
|
+
],
|
|
8598
|
+
"summary": "GET /guilds",
|
|
8599
|
+
"description": "the guild map (?order=size|shipped, default size; ?limit=&offset=). Viewer-independent: it reads no session. size is the public roster's length; shipped is R26's stored band floor (ADR 0337 D4.4), never an exact sum, null before a guild's first refresh. no-store: a hide or a visibility flip moves size on the very next read (ADR 0171 D5).\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8600
|
+
"x-rank": "public",
|
|
8601
|
+
"x-source": "modules/platform-identity/routes/guilds-public.js",
|
|
8602
|
+
"responses": {
|
|
8603
|
+
"200": {
|
|
8604
|
+
"description": "Success.",
|
|
8605
|
+
"content": {
|
|
8606
|
+
"application/json": {
|
|
8607
|
+
"schema": {
|
|
8608
|
+
"$ref": "#/components/schemas/GetGuildsResponse"
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
}
|
|
8612
|
+
},
|
|
8613
|
+
"400": {
|
|
8614
|
+
"$ref": "#/components/responses/BadRequest"
|
|
8615
|
+
}
|
|
8616
|
+
},
|
|
8617
|
+
"security": []
|
|
8618
|
+
},
|
|
8593
8619
|
"post": {
|
|
8594
8620
|
"operationId": "post_guilds",
|
|
8595
8621
|
"tags": [
|
|
@@ -8645,7 +8671,7 @@
|
|
|
8645
8671
|
"guilds"
|
|
8646
8672
|
],
|
|
8647
8673
|
"summary": "GET /guilds/:slug",
|
|
8648
|
-
"description": "a public guild's page data. The roster is the members who agreed to be shown AND whose own accounts are publicly visible (ADR 0336 D4); size is that roster's length. no-store: a hide or a visibility flip must beat every cache (ADR 0171 D5).\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8674
|
+
"description": "a public guild's page data. The roster is the members who agreed to be shown AND whose own accounts are publicly visible (ADR 0336 D4); size is that roster's length; totals are the weekly band floors (ADR 0337 D4.4), null before the first refresh. no-store: a hide or a visibility flip must beat every cache (ADR 0171 D5).\n\n**Rank:** `public` — No authentication — any caller.",
|
|
8649
8675
|
"x-rank": "public",
|
|
8650
8676
|
"x-source": "modules/platform-identity/routes/guilds-public.js",
|
|
8651
8677
|
"parameters": [
|
|
@@ -22551,6 +22577,21 @@
|
|
|
22551
22577
|
"builders"
|
|
22552
22578
|
]
|
|
22553
22579
|
},
|
|
22580
|
+
"GetGuildsResponse": {
|
|
22581
|
+
"type": "object",
|
|
22582
|
+
"properties": {
|
|
22583
|
+
"order": {},
|
|
22584
|
+
"count": {},
|
|
22585
|
+
"results": {},
|
|
22586
|
+
"page": {}
|
|
22587
|
+
},
|
|
22588
|
+
"required": [
|
|
22589
|
+
"order",
|
|
22590
|
+
"count",
|
|
22591
|
+
"results",
|
|
22592
|
+
"page"
|
|
22593
|
+
]
|
|
22594
|
+
},
|
|
22554
22595
|
"GetGuildsSlugMembersResponse": {
|
|
22555
22596
|
"type": "object",
|
|
22556
22597
|
"properties": {
|
|
@@ -22586,12 +22627,14 @@
|
|
|
22586
22627
|
"properties": {
|
|
22587
22628
|
"guild": {},
|
|
22588
22629
|
"members": {},
|
|
22589
|
-
"size": {}
|
|
22630
|
+
"size": {},
|
|
22631
|
+
"totals": {}
|
|
22590
22632
|
},
|
|
22591
22633
|
"required": [
|
|
22592
22634
|
"guild",
|
|
22593
22635
|
"members",
|
|
22594
|
-
"size"
|
|
22636
|
+
"size",
|
|
22637
|
+
"totals"
|
|
22595
22638
|
]
|
|
22596
22639
|
},
|
|
22597
22640
|
"GetHealthzResponse": {
|
|
@@ -29521,9 +29564,9 @@
|
|
|
29521
29564
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
29522
29565
|
}
|
|
29523
29566
|
},
|
|
29524
|
-
"x-endpoint-count":
|
|
29525
|
-
"x-schema-count":
|
|
29567
|
+
"x-endpoint-count": 462,
|
|
29568
|
+
"x-schema-count": 494,
|
|
29526
29569
|
"x-undocumented-bodies": 12,
|
|
29527
|
-
"x-response-schemas":
|
|
29570
|
+
"x-response-schemas": 336,
|
|
29528
29571
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
29529
29572
|
}
|
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. 462 endpoints across 82 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/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
|
|
@@ -342,10 +342,11 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
|
|
|
342
342
|
| POST | `/api/bongos/guild-requests/:id/accept` | `any-builder` | `visibility`, `counted_in_totals` | accept an invite addressed to ME, or (as the guild's owner) a request to join it. |
|
|
343
343
|
| POST | `/api/bongos/guild-requests/:id/decline` | `any-builder` | — | decline an invite to ME, or (as owner) a request to my guild. |
|
|
344
344
|
|
|
345
|
-
## `guilds` (
|
|
345
|
+
## `guilds` (13)
|
|
346
346
|
|
|
347
347
|
| Method | Path | Rank | Body | Description |
|
|
348
348
|
|---|---|---|---|---|
|
|
349
|
+
| GET | `/api/bongos/guilds` | `public` | — | the guild map (?order=size\|shipped, default size; ?limit=&offset=). |
|
|
349
350
|
| POST | `/api/bongos/guilds` | `any-builder` | `slug`, `name`, `description`, `visibility` | create a guild. |
|
|
350
351
|
| GET | `/api/bongos/guilds/:slug` | `public` | — | a public guild's page data. |
|
|
351
352
|
| PATCH | `/api/bongos/guilds/:slug` | `any-builder` | `name`, `description`, `visibility` | owner: edit name, description or visibility. |
|
|
@@ -2695,5 +2695,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2695
2695
|
landed since 1.20.17 with no explicit bump. run 36724081934. (task 1002620)
|
|
2696
2696
|
1.20.19 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2697
2697
|
landed since 1.20.18 with no explicit bump. run 36727774141. (task 1002620)
|
|
2698
|
+
1.20.20 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2699
|
+
landed since 1.20.19 with no explicit bump. run 36732445320. (task 1002620)
|
|
2700
|
+
1.20.21 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2701
|
+
landed since 1.20.20 with no explicit bump. run 36735857856. (task 1002620)
|
|
2698
2702
|
---------------------------------------------------------------------------
|
|
2699
2703
|
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// modules/platform-identity/guild-map.js — the guild map's data: public guilds,
|
|
2
|
+
// ranked (R30, task 1002306; ADR 0336 D8, amended by ADR 0337 D4.4).
|
|
3
|
+
//
|
|
4
|
+
// WHO. `visibility = 'public'` AND a non-empty public roster. An unlisted guild
|
|
5
|
+
// has no public existence (ADR 0336 D4), so it is never listed. Neither is a
|
|
6
|
+
// public guild whose every member is private or unshown: it would be a name on
|
|
7
|
+
// the map with nobody behind it.
|
|
8
|
+
//
|
|
9
|
+
// TWO ORDERINGS, NO STORED SCORE (D8):
|
|
10
|
+
// * size — the public roster's length, computed exactly as getPublicGuild
|
|
11
|
+
// computes it (shown_publicly AND accountVisibleSql, capped at
|
|
12
|
+
// guilds.LIST_MAX), so the map and the guild page never disagree.
|
|
13
|
+
// hide_stats hides numbers, never membership (ADR 0336 D4 §2), so a
|
|
14
|
+
// member who hides their numbers is still in it; a private one never.
|
|
15
|
+
// * shipped — the guild's STORED works_shipped band floor (guild-totals.js),
|
|
16
|
+
// never an exact sum (D4.4). A guild not yet refreshed publishes
|
|
17
|
+
// null and sorts last.
|
|
18
|
+
// Ties break on slug. Every sort key is a field the row publishes (ADR 0255: a
|
|
19
|
+
// public list's order is a covert column otherwise).
|
|
20
|
+
//
|
|
21
|
+
// COST, AND WHY THERE IS NO CACHE. One aggregate per read, over PUBLIC guilds'
|
|
22
|
+
// memberships only (the roster CTE filters on visibility before it groups, so an
|
|
23
|
+
// unlisted guild's members are never counted, let alone scanned for the map) —
|
|
24
|
+
// at the hub's scale a few index scans, bounded per caller by guild-map-read.
|
|
25
|
+
// D8 decides "computed at read time" and names the revisit trigger: a measured
|
|
26
|
+
// p95. It also rules out the cheap cache: any cache must be INVALIDATED by a hide,
|
|
27
|
+
// a privacy flip, a shown_publicly change, a membership change and a visibility
|
|
28
|
+
// change, because a TTL alone keeps publishing a withdrawn member in a guild's
|
|
29
|
+
// size (the ADR 0202 D3 reason). community-leaderboard.js's 30s memo does not
|
|
30
|
+
// transfer: it caches only NUMBERS and re-reads WHO on every request, and here
|
|
31
|
+
// the expensive half IS who — the roster under the privacy predicates. A cache
|
|
32
|
+
// is therefore a write-path change across guilds.js, the privacy setters and
|
|
33
|
+
// consent, taken when the p95 says so, not a TTL bolted on here.
|
|
34
|
+
//
|
|
35
|
+
// NOTHING HERE IS AUTHORITY (ADR 0016 / ADR 0141). Descriptive only.
|
|
36
|
+
//
|
|
37
|
+
// Reaches core only through the doorway (ADR 0083).
|
|
38
|
+
'use strict';
|
|
39
|
+
|
|
40
|
+
const api = require('../../src/module-api');
|
|
41
|
+
const { accountVisibleSql } = require('./account-visibility');
|
|
42
|
+
const { LIST_MAX } = require('./guilds');
|
|
43
|
+
const { clampOffset, MAX_OFFSET } = require('./builder-search');
|
|
44
|
+
|
|
45
|
+
const { pool: defaultPool } = api;
|
|
46
|
+
|
|
47
|
+
const DEFAULT_LIMIT = 25;
|
|
48
|
+
const MAX_LIMIT = 100;
|
|
49
|
+
|
|
50
|
+
// The orderings, as fixed SQL. A request names a key; it never supplies SQL.
|
|
51
|
+
const ORDERS = {
|
|
52
|
+
size: 'size DESC, g.slug',
|
|
53
|
+
shipped: 'shipped DESC NULLS LAST, g.slug',
|
|
54
|
+
};
|
|
55
|
+
const ORDER_KEYS = Object.keys(ORDERS);
|
|
56
|
+
const DEFAULT_ORDER = 'size';
|
|
57
|
+
|
|
58
|
+
function isOrder(order) {
|
|
59
|
+
return typeof order === 'string' && Object.prototype.hasOwnProperty.call(ORDERS, order);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function clampLimit(limit) {
|
|
63
|
+
const n = parseInt(limit, 10);
|
|
64
|
+
if (!Number.isFinite(n) || n <= 0) return DEFAULT_LIMIT;
|
|
65
|
+
return Math.min(n, MAX_LIMIT);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// One page of the map. `order` must already be valid (the route 400s first; an
|
|
69
|
+
// invalid one here falls back to the default rather than reaching SQL). Returns
|
|
70
|
+
// { order, results: [{ slug, name, size, shipped }], limit, offset } with the
|
|
71
|
+
// CLAMPED paging, so the route echoes what was actually applied.
|
|
72
|
+
async function listGuildMap({ order = DEFAULT_ORDER, limit, offset } = {}, { pool = defaultPool } = {}) {
|
|
73
|
+
const key = isOrder(order) ? order : DEFAULT_ORDER;
|
|
74
|
+
const lim = clampLimit(limit);
|
|
75
|
+
const off = clampOffset(offset);
|
|
76
|
+
const { rows } = await pool.query(
|
|
77
|
+
`WITH roster AS (
|
|
78
|
+
SELECT m.guild_id, LEAST(count(*), $3)::int AS size
|
|
79
|
+
FROM platform_identity_guilds pg
|
|
80
|
+
JOIN platform_identity_guild_members m ON m.guild_id = pg.id
|
|
81
|
+
JOIN platform_identity_accounts pa ON pa.github_id = m.github_id
|
|
82
|
+
WHERE pg.visibility = 'public' AND m.shown_publicly AND ${accountVisibleSql('pa')}
|
|
83
|
+
GROUP BY m.guild_id
|
|
84
|
+
)
|
|
85
|
+
SELECT g.slug, g.name, r.size, t.works_shipped AS shipped
|
|
86
|
+
FROM platform_identity_guilds g
|
|
87
|
+
JOIN roster r ON r.guild_id = g.id
|
|
88
|
+
LEFT JOIN platform_identity_guild_totals t ON t.guild_id = g.id
|
|
89
|
+
WHERE g.visibility = 'public'
|
|
90
|
+
ORDER BY ${ORDERS[key]}
|
|
91
|
+
LIMIT $1 OFFSET $2`,
|
|
92
|
+
[lim, off, LIST_MAX],
|
|
93
|
+
);
|
|
94
|
+
return { order: key, results: rows, limit: lim, offset: off };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = {
|
|
98
|
+
ORDER_KEYS,
|
|
99
|
+
DEFAULT_ORDER,
|
|
100
|
+
DEFAULT_LIMIT,
|
|
101
|
+
MAX_LIMIT,
|
|
102
|
+
MAX_OFFSET,
|
|
103
|
+
isOrder,
|
|
104
|
+
listGuildMap,
|
|
105
|
+
};
|