spike(modules): carry /public/atlas/* behind the proposed module surface

THROWAWAY BRANCH — evidence for the Phase 1 contract, never merged. See
modules/uo/SPIKE.md and docs/website/MODULE_API.md Part 7.

The six public spawn-atlas routes now live in modules/uo/, reached only through
the ctx/register surface, with the client half loading as a prebuilt ESM chunk.
All three exit criteria met:

  • zero internal-file imports from the module into core; the built chunk has
    zero bare import specifiers and bundles no React
  • routes.manifest.json AND routes.guards.json are byte-identical
  • /uo/atlas renders from /modules/uo/entry.js under script-src 'self' with
    zero CSP violation reports

729 core tests and 81 module tests pass. Verified end to end against the real
database: the schema fragment replays after core's, onBoot runs the atlas
refresh, and the six API URLs answer unchanged.

Two things the spike changed in the contract:

  • ctx.express / ctx.validator. A module lives outside server/, so Node never
    reaches server/node_modules and require('express') fails outright — the
    server-side twin of the one-React rule, which §2.6 had only for the client.
  • window.__rg.jsxRuntime, so a module can build with the automatic JSX
    runtime its tooling already assumes rather than being forced to classic.

And it confirmed §6.1 empirically: regenerating the OpenAPI spec silently
deleted all 361 lines of the atlas paths with "Swagger-autogen: Success", while
the route manifest kept all six in the same run. That is exactly the
static-analysis-vs-runtime split the fragment merge exists to prevent.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-10 05:29:35 -05:00
parent f1dda8fe66
commit bf470c7658
55 changed files with 4638 additions and 601 deletions

View File

@@ -23,11 +23,21 @@ const assert = require('node:assert/strict')
// never blocked by a bad tree), and the admin needs to be told what is wrong
// with their path;
// • a model failure degrades to a 500 rather than a thrown/uncaught error.
const pub = require('../src/router/v1/public/atlas.controller')
// The module's files read core through their `core` shim, which register()
// normally fills. Nothing registers modules in a unit test, so install the
// module's own fake ctx first — before any of its files are required, since the
// controller resolves its logger at require time.
require('../../modules/uo/server/test/_ctx').installFakeCtx()
// SPIKE ARTIFACT (see admin/shardAtlas.controller.js): the public atlas
// controller and its model are module-uo's now. Phase 3 moves this test into the
// module alongside them; until the admin half moves too, one test file has to
// see both sides.
const pub = require('../../modules/uo/server/router/atlas.controller')
const admin = require('../src/router/v1/admin/shardAtlas.controller')
const atlas = require('../src/model/shardAtlas/shardAtlas.model')
const atlas = require('../../modules/uo/server/model/shardAtlas/shardAtlas.model')
const activity = require('../src/model/activity/activity.model')
const visibility = require('../src/utils/shardVisibility')
const visibility = require('../../modules/uo/server/utils/visibility')
const db = require('../src/utils/db')
after(() => db.close())
@@ -36,7 +46,7 @@ after(() => db.close())
// module-internal getConfig, which an exports-level stub would not intercept — it
// would hit the closed DB port and cost a ~10s pool timeout per test before
// falling back to these same defaults.
const visibilityModel = require('../src/model/shardVisibility/shardVisibility.model')
const visibilityModel = require('../../modules/uo/server/model/shardVisibility/shardVisibility.model')
visibilityModel.listAll = async () => [] // no overrides ⇒ compiled defaults
visibility.viewerLevel = async (req) => req?.viewerLevel || 'anonymous'