The unit tests are supposed to run with no database, no server and no
built client, but tests/test_configjs.py imported spoolman.main, which
builds the SPA handler at module level and so needs client_v2/build to
exist. That passed locally, where the bundle is lying around, and failed
CI's style job, which never builds the client.
Moves the rendering into client.render_config_js, which the endpoint now
calls, so the test exercises the real code path without the app.
Task 10: config.js JSON-encodes the base path, so a backslash cannot
escape the string literal the way the old " check allowed; search.py
escapes LIKE wildcards at both its call sites, using a helper moved into
database/utils.py so it and extra_field_query share one implementation.
Task 9 was a pair of decisions rather than fixes. /info keeps its paths:
both clients render them and removing response fields breaks API v1, while
the disclosure buys nothing against an API that is unauthenticated anyway.
/metrics keeps its shape but now says what it publishes when switched on.
Also pins the unit tests to a throwaway data directory -- importing
spoolman.main creates one as a side effect, and it was the real one.