Commit Graph

112 Commits

Author SHA1 Message Date
jubnl e62f463296 refactor(server): plan 4 — unify the trip-access predicate's Kysely copies
TripsRepository.findForViewer/listForUser/activeTrip each hand-wrote the
identical trip-access boolean (t.user_id = ? OR m.user_id IS NOT NULL)
through the Kysely expression builder. Task 7's security review (M1)
evaluated a shared helper and set it aside for time, falling back to the
TRIPREPO-041 cross-method parity test as a regression guard instead.

Extracted the boolean into one generic helper, tripAccessExpr
(_shared/trip-access.ts), following the reservation-visibility.ts
publicReservationExpr precedent: fully generic over <DB, TB> since the
predicate has no correlated subquery, so it composes across
TripSelectKyselyDB and ActiveTripKyselyDB without needing a narrower
fixed-alias shape. The LEFT JOIN itself stays hand-written at each call
site — tripSelectQuery's own docstring already explains why a shared join
helper can't be typed across these differently-joined outer queries.

feeds.service.ts and memories-access.service.ts no longer duplicate this
predicate at all (Task 2's facade-inline sweep already converted both onto
TripsRepository.findAccessible/getFeedTokenIfReachable/
listReachableActiveTrips, which read through the canonical MikroORM
QueryBuilder form, accessibleTripsQuery) — the remaining duplication this
task closes is the three Kysely copies inside this file.

TRIPREPO-041 (64/64 in the file) stays green as the unification's own
regression guard.
2026-09-24 06:05:30 +02:00
jubnl 7f61d69add fix(server): plan 4 — RULE12 paren-count scanner ignores string literals
The entity generator's RULE12_fixGarbledCheckExpressions CHECK-expression
paren-balance scanner counted every `(`/`)` character regardless of
whether it fell inside a single-quoted SQL string literal. A CHECK
expression like `status IN ('confirmed)', 'tentative')` has a literal `)`
inside its first string value; the scanner would hit depth 0 at that
in-string character and truncate the expression, losing its own real
closing paren. The scanner now tracks single-quote string state (handling
the doubled `''` SQLite escape) and skips parens while inside one.

Latent-bug fix — no shipped entity's CHECK expression has hit this shape
yet (3d's ledger: "nothing affected today").
2026-09-24 06:05:14 +02:00
jubnl 8f825e445e fix(server): plan 4 — un-skip PARITY-009 (FK deleteRule and index-name parity) 2026-09-24 05:22:31 +02:00
jubnl 88fa13d55a refactor(server): plan 4 — convert the program's orphaned raw-SQL callers 2026-09-24 04:59:54 +02:00
jubnl f29216c5af refactor(plugins): outbound OAuth tokens and per-user plugin settings through repositories 2026-09-24 03:13:09 +02:00
jubnl 2ba5534c65 fix(server): plan 3i close-out — DemoModule imported where its service is consumed (e2e restored); admin addons list selects the provider relation; saveDemoBaseline awaited; backup tests on the maintenance repository 2026-09-24 02:58:37 +02:00
jubnl f337f116d9 fix(server): plan 3h close-out — new-value-wins COALESCE restores stay/reservation propagation; doc-sync state filter truthiness; request-context and parity ratchets for share, doc-sync and the integrations 2026-09-24 02:39:30 +02:00
jubnl 915ab84faf refactor(demo,backup): seed and reset through DemoRepository, live-connection backup statements through MaintenanceRepository, isDemoUserId through an injected DemoService 2026-09-24 02:04:32 +02:00
jubnl 862799062a refactor(admin): user CRUD, stats, audit log, version check and addon config through repositories 2026-09-24 01:46:09 +02:00
jubnl 36e178c085 refactor(storage): backend/category config and usage stats through AppSettingsRepository; fix the seed-file test race and the shared-replica migration-flip gap 2026-09-24 01:20:46 +02:00
jubnl 14721e9658 feat(server): plan 3i groundwork — AuditLogRepository's reserved methods, the demo connection-swap spike, repository-fitness confirmations 2026-09-24 00:56:52 +02:00
jubnl 8bcfd92142 refactor(doc-sync): connections, reconciler and controller-SQL relocation through repositories 2026-09-24 00:40:23 +02:00
jubnl 1d72c6909b refactor(integrations): dawarich connection, sync, tracks and review-flow through repositories 2026-09-23 23:55:52 +02:00
jubnl 992f9ae4a7 refactor(collections): access model, hydration, export/import and list CRUD through repositories 2026-09-23 23:29:15 +02:00
jubnl 353edd7a48 fix(server): plan 3f close-out — ntfy operator-scope test on the live send path; vacay date-offset and shift-order parity; todo reminder window; coverage and parity ratchets for the atlas and vacay repositories 2026-09-23 22:58:03 +02:00
jubnl 9e75aea73f feat(server): plan 3h groundwork — date-offset dialect helpers, entity/repository fitness confirmations, pre-init and encryption pattern confirmations, survivor re-grep 2026-09-23 22:34:31 +02:00
jubnl 71ebf5588b feat(server): plan 3g groundwork — GALLERY_CHRONOLOGICAL_ORDER Kysely ordering, unixEpochToIsoKysely helper, composite-PK DDL pins, JB5/R7 confirmations 2026-09-23 21:57:16 +02:00
jubnl 847a538509 refactor(atlas): visited countries, regions and bucket list through repositories 2026-09-23 21:40:36 +02:00
jubnl 2f1bb2597e refactor(system-notices): notice dismissals through a Nest provider and repository 2026-09-23 21:30:44 +02:00
jubnl 66b7e6440d fix(server): plan 3e close-out — repository registrations restore the boot; packing assignee and bag updates parse and no-op as legacy; coverage and scoping ratchets for the budget, packing and collab repositories 2026-09-23 21:02:35 +02:00
jubnl 4258f05926 refactor(notifications): in-app notifications and channel preferences through repositories 2026-09-23 20:33:07 +02:00
jubnl a209e851af feat(server): plan 3f groundwork — systemNotices DI shape, TRAVELER_OWNS predicate, ntfy/storage-health specs, composite-PK pins 2026-09-23 20:05:38 +02:00
jubnl 6b4c124a38 fix(server): plan 3d close-out — legacy text shape for stored accommodation ids restores the date-change restamp; reservation ids parsed once at the gate; parity tests for the reservation repositories 2026-09-23 17:44:48 +02:00
jubnl 7489d6d925 feat(server): plan 3e groundwork — packing visibility predicate, memories access-gate audit 2026-09-23 17:21:54 +02:00
jubnl 6102929e8d refactor(calendar): calendar reads and reservation visibility through one predicate 2026-09-23 16:38:47 +02:00
jubnl 26233434f6 refactor(feeds): ICS feed tokens and anonymous feeds through repositories 2026-09-23 15:12:13 +02:00
jubnl 7ee0403eaf refactor(reservations): reservations, endpoints and travelers through repositories 2026-09-23 14:58:36 +02:00
jubnl 3a26d03b00 refactor(roadtrip): roadtrip tables through repositories 2026-09-23 14:44:10 +02:00
jubnl 93324e71c4 feat(server): plan 3d groundwork — dialect helpers, visibility predicate, feed and cron context ratchets 2026-09-23 13:52:38 +02:00
jubnl 4ceb94613f fix(server): plan 3c close-out — days create/insert answer the guard 404 for non-canonical trip ids instead of 500; exact settlement and cross-request yield ratchets 2026-09-23 13:31:26 +02:00
jubnl eaa027750a test(server): plan 3c close-out — copy-source full-row parity, Kysely rollback proofs, identity-map relabels, trips e2e on the snapshot DB 2026-09-23 12:55:20 +02:00
jubnl 175eb3b11b fix(server): plan 3c close-out — non-finite ids bound as NULL, trip id parsed once at every places/days/ws gate
Platform: NulSafeSqlitePlatform now renders a bound NaN as NULL and
+/-Infinity as 9e999/-9e999, matching better-sqlite3's own legacy binding
(rule 22 extension) — the program-wide fail-safe for any caller that still
passes an unguarded Number(untrusted) into a converted statement.

PlacesService.verifyTripAccess and RealtimeGateway.handleJoin stop doing
that: verifyTripAccess parses once with toRowId and threads the parsed id
through create/import/bulk/rating/export.gpx (deleting the seven
toRowId(tripId) ?? -1 sites), and handleJoin gets a Number.isFinite guard.
DaysService gets the same treatment across list/create/getDay/reorder/
insert/resyncAccommodationDays, closing the gap where a hex-spelled trip id
could renumber a real trip's days while the raw-bind inverted-accommodation
guard silently matched nothing.

DatabaseService.getTripTitle is deleted; PlacesService injects
TripsRepository directly and calls getTitle itself.

Template/cheap-item cleanup: DayAssignmentsRepository.listForTimeSort uses
$castTo instead of an unknown bridge; the duplicated TagRow interface in
Places.repository.ts is now imported from Tags.repository.ts;
AssignmentWithPlaceRow extends the guarded DayAssignmentRow instead of
restating its columns; PlaceShadowPicksRepository.totals drops its
unreachable ??-fallback branch; Places.repository.ts's updatePlace types
the NOT NULL name column as string; trip-members.service.ts's
transferOwnership threads one parsed trip id through all three writes and
corrects two stale "raw-bind seam" docstrings that were actually Number()
seams; a dead canAccessTrip mock is removed from reservations.e2e.test.ts.

Tests: the 23 new no-explicit-any warnings in TRIP-SVC-069 are typed
(lint back to 2416); HTTP and WS regression coverage for the non-finite
and non-canonical id shapes across places/days routes, mutation-proved;
TRIP-JOIN-005 asserts the exact concurrent-join settlement instead of
>= 1; a new tests/unit/db/transaction-yield.test.ts pins rule 24's
measured transaction-yield/dirty-read/nested-BEGIN behaviour.
2026-09-23 12:22:36 +02:00
jubnl 46a3246e82 refactor(trips): trip copy through repositories for the owned tables 2026-09-23 10:31:54 +02:00
jubnl 4cb8432ade fix(server): trip ids parsed once at the gate for places and assignments; NUL-safe value quoting on the SQLite platform; places parity tests completed 2026-09-23 10:09:38 +02:00
jubnl 18a4784ebd refactor(trips): trips through repositories 2026-09-23 09:33:48 +02:00
jubnl f19face405 refactor(places): import paths through repositories 2026-09-23 08:53:54 +02:00
jubnl 955809f15f fix(server): place-shadow source counts ordered in SQL; identity-map ratchets load-bearing; photo-cache race pinned 2026-09-23 08:31:36 +02:00
jubnl 9f1f5c45bf refactor(places): places, tags, ratings and place images through repositories 2026-09-23 08:15:05 +02:00
jubnl 94c6efbbcc refactor(trip-members): membership, guests and the trip read model through repositories 2026-09-23 08:00:39 +02:00
jubnl cee6310e59 refactor(server): trip-membership, place-shadow, place-enrichment, place-photos and query helpers through repositories 2026-09-23 06:41:03 +02:00
jubnl f41da98df3 refactor(assignments): day assignments through repositories 2026-09-23 06:27:21 +02:00
jubnl d7f5bc64c1 refactor(days): days and day notes through repositories 2026-09-23 05:31:36 +02:00
jubnl d2e0d7e320 refactor(trips): trip access through TripsRepository; demo seed in a request context; dialect helpers for the trips cluster 2026-09-23 04:46:18 +02:00
jubnl 769b9577ec refactor(server): trip-access primitives async at every caller 2026-09-23 02:46:39 +02:00
jubnl 8efb3c8623 fix(server): plan 3b close-out — case folding on both sides for identifier lookups (non-ASCII login regression); coverage ratchet restored; repository scaffold and instanceof ratchet on TrekRepository; D-shape tests load-bearing 2026-09-23 01:48:27 +02:00
jubnl 8b815891f5 fix(auth): invite validation keeps expires_at null on the wire; password transaction scopes and reset-token burn pinned 2026-09-23 00:00:32 +02:00
jubnl 33b9488653 refactor(auth): AuthService and account cleanup through repositories 2026-09-22 23:17:17 +02:00
jubnl 21ade19d44 refactor(db): TrekRepository base — every repository path validates the request context and reads bypass the identity map by default 2026-09-22 22:37:49 +02:00
jubnl 8ba55bda30 fix(db): generator emits the referenced column for non-PK foreign keys; OAuth client joins through the relation; FK parity un-skipped 2026-09-22 21:53:34 +02:00
jubnl 80a0fdc4d9 fix(auth): non-numeric passkey and invite ids answer the legacy 404, never NaN; invite join type pinned 2026-09-22 21:31:46 +02:00