Repository navigation
fix(plugin-auth, driver-sql)!: fail closed on a missing auth secret outside development; compile window functions from closed tables - #25563
Conversation
…t only The ephemeral fallback secret was admitted whenever NODE_ENV was not exactly `production`, so an unset or custom NODE_ENV booted with a predictable secret. Gate it on `isDevelopmentBoot` from @objectstack/core (or NODE_ENV=test, the pair core's production fuse reads) and refuse to boot otherwise. `os serve` / `os start` default an unset NODE_ENV to production and `--dev` sets development, so CLI boots are unchanged. Claude-Session: https://claude.ai/code/session_01SNJgKweepTFKCrYgaKeFZK Co-authored-by: Claude <noreply@anthropic.com>
…ed columns `findWithWindowFunctions()` built its OVER clause by string concatenation. The function name and sort direction now come from closed tables (anything else is refused with INVALID_QUERY / 400), and every partitionBy / orderBy field is emitted as a quoted column reference. Claude-Session: https://claude.ai/code/session_01SNJgKweepTFKCrYgaKeFZK Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SNJgKweepTFKCrYgaKeFZK Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 30 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin f646d778c9c0a077dc1b7f74444c7c3e4606573c && git checkout f646d778c9c0a077dc1b7f74444c7c3e4606573c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 041a120b6189e9b174a3f4b8cf6202f22ace2bbd 329dd94ac1e36cb9d6f93303a2e5a6d8844c6c33 && git checkout -B drift-repro 041a120b6189e9b174a3f4b8cf6202f22ace2bbd && git merge --no-ff 329dd94ac1e36cb9d6f93303a2e5a6d8844c6c33
node scripts/docs-audit/affected-docs.mjs --json 041a120b6189e9b174a3f4b8cf6202f22ace2bbd
|
Requested by Tesla · project thread
Clause-②: no (narrowing)
Metadata-protocol: none
Two small hardenings, one commit each, each with its own changeset. Draft: it waits for the maintainer's review.
1 · plugin-auth: the temporary auth secret is admitted on a development boot only
generateSecret(auth-manager-database-secret.ts) fell back to a temporarydev-secret-value wheneverNODE_ENVwas anything but exactlyproduction. It now admits that fallback only whenisDevelopmentBootfrom@objectstack/coreholds (NODE_ENV=development) or underNODE_ENV=test, the same pair core's own production fuse reads (isCloudManaged). Every other boot withoutOS_AUTH_SECRET(or its legacy spellings, or asecretoption) refuses to start, asproductionalready did.os servesetsNODE_ENV=productionwhen it is unset anddevelopmentunder--dev;os startdoes the same for the child it spawns. So only an embedder that constructsAuthPlugin/AuthManageritself with no secret and noNODE_ENV=developmentsees the new refusal.testis kept. Vitest setsNODE_ENV=test, and the full plugin-auth suite constructs managers without a secret. Core's own fuse treatstestas non-production for the same reason.auth-manager.test.tsgains an unsetNODE_ENVcase, four custom values (staging,Production,dev, empty), and atestcase.2 · driver-sql:
findWithWindowFunctions()compiles from closed tables and quoted columnsbuildWindowFunctionassembledFUNC() OVER (PARTITION BY … ORDER BY …)as text. Now:row_number,rank,dense_rank,percent_rank,cume_dist(any case). These are the argument-less functions the door's flat shape can express. Anything else answersINVALID_QUERY/ 400 before a statement is sent.ascordesc(any case, defaultasc); anything else answersINVALID_QUERY/ 400.partitionBy/orderByfield is emitted withknex.ref(...).toQuery(), the quoting idiom this file already uses for columns.Why parameterised, not removed. The dispatch preferred deleting the method. Measured first: nothing in objectstack, objectui or hotcrm calls it outside driver-sql's own tests and the turso override. It is still a published door, though. The protocol-17 migration
query-window-functions-retiredand thequery.windowFunctionstombstone inpackages/spec/src/data/query.zod.tsboth prescribeSqlDriver.findWithWindowFunctions()as the replacement for the retired request key, and the 17.0 release notes andcontent/docs/data-modeling/queries.mdxdocument it. Removing it would retire a capability those texts tell embedders to migrate to. This PR keeps it and closes the string assembly instead. If the maintainer prefers removal, that is a follow-up that also rewrites those prescriptions.sql-driver-window-function-compilation.test.tscovers the five functions in mixed case, three refused names, both directions plus the default, a refused direction, the exact compiled text, and a field-slot expression read as a column name.Red on
main, green hereEach fix was committed first, then the source file alone was restored from
main(19d3720) and the new tests were run:main's source; 9 passed with the fix.main's source (the six passes are the accepted spellings); 12 passed with the fix.Local verification
pnpm --filter @objectstack/plugin-auth exec vitest run --maxWorkers=2: 191 files, 3613 passed, 10 skippedpnpm --filter @objectstack/driver-sql exec vitest run --maxWorkers=2: 235 files passed, 12 skipped; 3787 passed, 212 skippeddispatch-gates.mjs --commands) run locally: all 74 derived families exit 0 at329dd94a(dispatch-gates.mjs --ranreconciles 74 run, 0 NOT-MEASURED). Four needed a real-declaration build or a deeper fetch first and were re-run after it.pnpm --filter @objectstack/plugin-auth --filter @objectstack/driver-sql run typecheckafter a real-declaration build of both closures: exit 0Acceptance notes
driver-sqlite-wasmanddriver-turso(local and replica transports) inherit the builder, so they get the same closed compilation. The turso remote transport already refused this door.Generated by Claude Code