35 files and 5,332 lines out — twelve public pages, seven admin views, two player views, eight components, the two `data/` leaves and the three `lib/` ones, plus the two tests that came with them. §2.7.1's estimate of 51 files / ~3,700 lines was measured differently and is corrected in the docs PR. The seams core keeps, each smaller than what it replaced: Nine rows leave the public header and six leave the admin sidebar, and both lists are now free of `feature` gates and of `IconShard`. `moduleTitle` already handled a module page's heading, so the six TITLES entries and the `/admin/characters` branch of `sectionTitle` simply go. `/player` had `PlayerCharacters` as its index — a UO page — and rather than name a replacement or invent a landing screen it now resolves to the first row of the portal nav this viewer can reach (`firstDestinationFor`, beside `allowedPathsFor` and reading the BASE nav for the same reason: an override is presentation and where everybody lands is behaviour). With the module installed that is still Characters, so a player's first screen after signing in does not change. Deliberately generic and deliberately not in the portal layout — the admin index is the same question with a hardcoded answer, and if the two logged-in areas ever become one this is what serves both. `game_account_signup` goes with the rest of core's UO prose: the mode list, the derived public flag, the validation and a Site Settings field whose help text named Bridge.cfg. The row itself is untouched and module-uo reads it through ctx.settings — the data stays, the semantics move. KNOWN BREAK, accepted by the org lead: the shipped Android app reads `gameAccountSignup` off `/public/settings` (PublicDto.kt:80). The field has a `= false` default so nothing crashes; the app silently stops offering game-account creation until it reads the module's `/public/shard/features` instead. Out of scope here, recorded in the Android plan, and it lands well before this workstream's cutover reaches `main`. 620 server + 161 client tests. Manifest 158 public + 2 internal, unchanged; routes.guards unchanged. The OpenAPI spec loses exactly one property, and only because it was hand-written in swagger.js — regeneration alone would have left the spec documenting a field core no longer returns. Co-Authored-By: Claude <noreply@anthropic.com>
76 lines
3.6 KiB
JavaScript
76 lines
3.6 KiB
JavaScript
// ── What core's settings no longer know about ──────────────────────────────
|
|
//
|
|
// Phase 3, slice 3. `game_account_signup` policy left core: the mode list, the
|
|
// derived public flag, the validation and the Site Settings field. The row in
|
|
// the `settings` table is untouched and module-uo reads it through
|
|
// `ctx.settings`, which is the whole point — the DATA stays, the SEMANTICS move.
|
|
//
|
|
// This file exists because the deletion passed 616 tests without one of them
|
|
// noticing. Nothing asserted the shape of `getPublic()`, so a field could leave
|
|
// the public settings payload — which the SPA, the Android app and the Discord
|
|
// bot all read — and no suite would say a word. That is worth a test in the
|
|
// direction of "and it is gone", but it is much more worth one in the direction
|
|
// of "and nothing else went with it".
|
|
|
|
process.env.DB_HOST = '127.0.0.1'
|
|
process.env.DB_PORT = '59999'
|
|
|
|
const { test, after, afterEach } = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
|
|
const settings = require('../src/model/settings/settings.model')
|
|
const settingsDb = require('../src/model/settings/settings.db')
|
|
const db = require('../src/utils/db')
|
|
|
|
after(() => db.close())
|
|
|
|
const originals = { getAll: settingsDb.getAll, get: settingsDb.get }
|
|
afterEach(() => Object.assign(settingsDb, originals))
|
|
|
|
// Both readers, because the two halves of this test read different ones:
|
|
// `getPublic` folds `getAll`, and a module's `ctx.settings.get` is `get`.
|
|
const withRows = (rows) => {
|
|
settingsDb.getAll = async () => Object.entries(rows).map(([key, value]) => ({ key, value }))
|
|
settingsDb.get = async (key) => (key in rows ? rows[key] : null)
|
|
}
|
|
|
|
test('the public settings payload no longer carries gameAccountSignup', async () => {
|
|
// Configured as it would be on a live instance that had the feature on. The
|
|
// row is still there and still readable — it is simply not core's to interpret.
|
|
withRows({ site_title: 'Test', game_account_signup: 'hybrid' })
|
|
const out = await settings.getPublic()
|
|
assert.equal('gameAccountSignup' in out, false)
|
|
})
|
|
|
|
test('and the raw row is still there for the module to read', async () => {
|
|
// The load-bearing half. Renaming or dropping the key would silently reset
|
|
// every configured instance to `disabled`, with players reporting that signup
|
|
// stopped working as the only clue.
|
|
withRows({ game_account_signup: 'hybrid' })
|
|
assert.equal(await settings.get('game_account_signup'), 'hybrid')
|
|
})
|
|
|
|
test('the rest of the public payload is unchanged', async () => {
|
|
// The assertion the deletion actually needed: three clients read this object
|
|
// and none of them are in this repo. Registration flags are the near
|
|
// neighbour — same shape, same file, same derived-from-a-mode pattern — and
|
|
// the one most likely to be taken along by an over-eager edit.
|
|
withRows({
|
|
site_title: 'Test',
|
|
player_registration: 'both',
|
|
game_account_signup: 'hybrid',
|
|
})
|
|
const out = await settings.getPublic()
|
|
assert.deepEqual(out.registration, { password: true, sso: true })
|
|
assert.equal(out.site_title, 'Test')
|
|
})
|
|
|
|
test('core no longer exports the game-signup policy', () => {
|
|
// A leftover export is a leftover consumer waiting to happen, and the module
|
|
// has its own copy now. `ctx.settings` is three functions and never included
|
|
// these, so nothing outside core could have been using them.
|
|
for (const name of ['GAME_SIGNUP_KEY', 'GAME_SIGNUP_MODES', 'getGameSignupMode', 'isGameAccountSignupEnabled']) {
|
|
assert.equal(name in settings, false, `settings still exports ${name}`)
|
|
}
|
|
})
|