@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.
@@ -10,6 +10,10 @@
10
10
  // 3. THE PUBLIC READ — 404 for an unlisted guild is byte-identical to an
11
11
  // unknown slug, needs no session, is no-store, and its roster statement
12
12
  // carries shown_publicly AND the shared existence predicate.
13
+ // 3b. THE GUILD MAP (task 1002306) — public guilds with a non-empty public
14
+ // roster, sized by the guild page's own predicate and cap, ranked only by
15
+ // published fields (size, or the STORED shipped band floor), paging
16
+ // clamped, and an unknown order refused before any SQL.
13
17
  // 4. SILENCE — a request written and one swallowed by a decline cooldown
14
18
  // answer identically; a decline is an empty 204.
15
19
  // 5. THE CARD — an invite accept must echo the visibility its card showed,
@@ -90,6 +94,7 @@ require.cache[moduleApiPath] = {
90
94
  },
91
95
  };
92
96
  const guilds = require('../modules/platform-identity/guilds.js');
97
+ const guildMap = require('../modules/platform-identity/guild-map.js');
93
98
  const buildGuildRoutes = require('../modules/platform-identity/routes/guilds.js');
94
99
  const buildPublicRoutes = require('../modules/platform-identity/routes/guilds-public.js');
95
100
  const { attachFail } = require('../src/bongos/middleware/error-envelope.js');
@@ -263,8 +268,13 @@ test('public read: the roster is shown_publicly AND the shared existence predica
263
268
  });
264
269
  const res = await call('GET', '/api/bongos/guilds/Guild-A');
265
270
  assert.equal(res.status, 200);
266
- assert.deepEqual(Object.keys(res.json).sort(), ['guild', 'members', 'size']);
271
+ assert.deepEqual(Object.keys(res.json).sort(), ['guild', 'members', 'size', 'totals']);
267
272
  assert.equal(res.json.size, 2);
273
+ assert.equal(res.json.totals, null, 'no stored record yet → no totals, never a computed stand-in');
274
+ assert.ok(calls.some((c) => /FROM platform_identity_guild_totals\s+WHERE guild_id = \$1/.test(c.text)),
275
+ 'the totals are READ from the weekly snapshot');
276
+ assert.ok(calls.every((c) => !/INSERT|UPDATE|platform_identity_builder_project_activity/.test(c.text)),
277
+ 'the public read never computes or writes the totals (ADR 0337 D4.4: never on a read)');
268
278
  assert.equal(res.json.members.length, 2);
269
279
  assert.ok(!('id' in res.json.guild), 'the row id stays internal');
270
280
  assert.ok(!/github_id|github_login/.test(res.text), 'no account id or login crosses');
@@ -276,6 +286,75 @@ test('public read: the roster is shown_publicly AND the shared existence predica
276
286
  assert.equal(calls[0].params[0], 'guild-a', 'the slug is looked up in canonical form');
277
287
  });
278
288
 
289
+ // ===========================================================================
290
+ // 3b. The guild map (R30, task 1002306; ADR 0336 D8 + ADR 0337 D4.4)
291
+ // ===========================================================================
292
+
293
+ const IS_MAP = (t) => /WITH roster AS/.test(t) && /FROM platform_identity_guilds g/.test(t);
294
+
295
+ test('guild map: public guilds with a public roster, sized like the guild page, ranked by size then slug', async () => {
296
+ on((t) => (IS_MAP(t) ? result([
297
+ { slug: 'big', name: 'Big', size: 9, shipped: 50 },
298
+ { slug: 'new', name: 'New', size: 2, shipped: null },
299
+ ]) : result()));
300
+ session = null; // the map must not need one
301
+ try {
302
+ const res = await call('GET', '/api/bongos/guilds');
303
+ assert.equal(res.status, 200);
304
+ assert.equal(res.headers['cache-control'], 'no-store');
305
+ assert.deepEqual(Object.keys(res.json).sort(), ['count', 'order', 'page', 'results']);
306
+ assert.equal(res.json.order, 'size', 'size is the default ordering');
307
+ assert.equal(res.json.count, res.json.results.length);
308
+ assert.deepEqual(res.json.page, { limit: guildMap.DEFAULT_LIMIT, offset: 0 });
309
+ assert.equal(calls.length, 1, 'one statement, and no read of the viewer');
310
+ const { text, params } = calls[0];
311
+ assert.match(text, /AND m\.shown_publicly AND \(\(pa\.profile_state = 'active' AND pa\.terms_accepted_at IS NOT NULL\) AND pa\.account_visibility = 'public'\)/,
312
+ 'size is the public roster: shown_publicly AND accountVisibleSql — the getPublicGuild predicate');
313
+ assert.match(text, /JOIN roster r ON r\.guild_id = g\.id/, 'an INNER join: a guild with an empty public roster is not on the map');
314
+ assert.match(text, /WHERE g\.visibility = 'public'/, 'an unlisted guild is never listed');
315
+ assert.match(text, /LEAST\(count\(\*\), \$3\)/, 'size is capped like the guild page\'s roster');
316
+ assert.match(text.split('SELECT g.slug')[0], /WHERE pg\.visibility = 'public' AND m\.shown_publicly/,
317
+ 'the aggregate groups PUBLIC guilds\' memberships only — an unlisted guild is never scanned for the map');
318
+ assert.deepEqual(params, [guildMap.DEFAULT_LIMIT, 0, guilds.LIST_MAX]);
319
+ assert.match(text, /ORDER BY size DESC, g\.slug\s+LIMIT/, 'ties break on slug');
320
+ } finally { session = { github_id: ME, github_login: 'octo' }; }
321
+ });
322
+
323
+ test('guild map: shipped ranks by the STORED band floor, never an exact sum; a guild not yet refreshed sorts last', async () => {
324
+ on((t) => (IS_MAP(t) ? result([]) : result()));
325
+ const res = await call('GET', '/api/bongos/guilds?order=shipped');
326
+ assert.equal(res.status, 200);
327
+ assert.equal(res.json.order, 'shipped');
328
+ const { text } = calls[0];
329
+ assert.match(text, /LEFT JOIN platform_identity_guild_totals t ON t\.guild_id = g\.id/);
330
+ assert.match(text, /t\.works_shipped AS shipped/, 'the published key IS the sort key (ADR 0255)');
331
+ assert.match(text, /ORDER BY shipped DESC NULLS LAST, g\.slug/);
332
+ assert.doesNotMatch(text, /platform_identity_builder_project_activity/, 'no exact sum is ever read here (ADR 0337 D4.4)');
333
+ });
334
+
335
+ test('guild map: a row carries slug, name, size and shipped — nothing that names an account', async () => {
336
+ on((t) => (IS_MAP(t) ? result([]) : result()));
337
+ await call('GET', '/api/bongos/guilds');
338
+ const select = calls[0].text.split(/SELECT g\.slug/)[1].split('FROM')[0];
339
+ assert.equal(`g.slug${select}`.replace(/\s+/g, ' ').trim(), 'g.slug, g.name, r.size, t.works_shipped AS shipped');
340
+ });
341
+
342
+ test('guild map: an unknown order is a 400 that reaches no SQL; paging is clamped and echoed', async () => {
343
+ on(() => result());
344
+ const bad = await call('GET', '/api/bongos/guilds?order=credits');
345
+ assert.equal(bad.status, 400);
346
+ assert.equal(bad.json.error.code, 'guild_map_bad_order');
347
+ assert.equal(calls.length, 0);
348
+
349
+ on((t) => (IS_MAP(t) ? result([]) : result()));
350
+ const big = await call('GET', '/api/bongos/guilds?limit=1000&offset=99999');
351
+ assert.deepEqual(big.json.page, { limit: guildMap.MAX_LIMIT, offset: guildMap.MAX_OFFSET });
352
+ assert.deepEqual(calls[0].params.slice(0, 2), [guildMap.MAX_LIMIT, guildMap.MAX_OFFSET]);
353
+ on((t) => (IS_MAP(t) ? result([]) : result()));
354
+ const junk = await call('GET', '/api/bongos/guilds?limit=-3&offset=abc');
355
+ assert.deepEqual(junk.json.page, { limit: guildMap.DEFAULT_LIMIT, offset: 0 });
356
+ });
357
+
279
358
  // ===========================================================================
280
359
  // 4. Join requests and silence (D3)
281
360
  // ===========================================================================