feat(server): gate writes outside a transaction with lint:tx

The rule that a multi-statement write runs in uow.transactional was
written down but nothing held it. scripts/tx-writes.mjs reads every class
under src/ with the TypeScript parser and counts, per method, the writes
it issues outside a transactional callback: repository calls that build
an INSERT, UPDATE or DELETE, calls to methods that write (on the class
itself or on a constructor-injected one), and a transaction holding
writes as one. A write in a loop counts twice, of two branches only the
larger counts, local helpers count where they are called, and a helper
whose every call sits inside a transaction is not reported. --explain
lists the line of every call that counted.

Today's 102 reported methods sit in scripts/tx-writes-baseline.json and
may only shrink; most are syncs with network I/O between their writes,
plugin lifecycle steps and adapters calling two service writes. A new
method fails CI, and an entry above what its method holds fails until
--update lowers it, the same ratchet as lint:size and lint:boundaries.

Two JSDoc tags mark the deliberate cases with their reason in the tag:
@txStandalone for a write that stands on its own whatever the caller does
(the audit row, notification sends, the booking price mirror, the
assignment journey refresh, the quota retention purge), @txIndependent
for writes complete one by one on purpose (the OAuth token retention
sweep, the notification claim and its release). Runs in CI after
lint:boundaries; documented in server/CLAUDE.md, the root CLAUDE.md and
the wiki's dev setup page.
This commit is contained in:
Maurice
2026-10-08 15:38:06 +02:00
parent 9dd2e1b983
commit 8018f10273
14 changed files with 901 additions and 5 deletions
+6
View File
@@ -260,6 +260,12 @@ jobs:
# scripts/import-boundaries-baseline.json and may only shrink.
run: cd server && npm run lint:boundaries
- name: Writes outside a transaction
# A method that writes twice does it inside one uow.transactional.
# Today's exceptions sit in scripts/tx-writes-baseline.json and may
# only shrink; @txStandalone/@txIndependent mark the deliberate ones.
run: cd server && npm run lint:tx
- name: Open request schemas may only shrink
# Needs the shared build above. Counts open shapes (records of
# unknown, passthrough, any) in shared's request schemas.