Commit Graph

240 Commits

Author SHA1 Message Date
jubnl 1853156da3 fix(server): plan 4 — plugin discovery's delete+reinsert pairs are atomic
install/discovery.ts#upsert refreshed a plugin's actions and settings-field
descriptors as two independent delete-then-reinsert pairs (DI5-DI8) with no
transaction spanning either pair, let alone both: a crash between a delete
and its own reinsert left that plugin with an EMPTY actions or
settings-field set until the next discovery run, instead of its previous
still-valid rows. Wraps both pairs in one uow.transactional, so a discovery
refresh for a plugin's descriptors is now all-or-nothing.

Deliberate behaviour change, named for the user per the task brief.

DiscoveryRepos grows a UnitOfWork; PluginRegistryService (the other
production caller, registry.service.ts) picks it up the same @Optional()
way PluginRuntimeService already does, with the same guard-throw. Updates
the two hand-constructed test call sites that actually exercise discovery
(discovery.test.ts, registry.test.ts) to pass a real UnitOfWork.
2026-09-24 06:17:23 +02:00
jubnl 51327e75c0 refactor(server): plan 4 — inline canAccessTrip/isOwner off DatabaseService (trip-domain services) 2026-09-24 05:47:21 +02:00
jubnl fe69a3b9a7 fix(server): plan 3j close-out — serialized audit-chain appends, atomic metadata and scheduler limits, rollback and race proofs for the plugin repositories 2026-09-24 04:52:18 +02:00
jubnl d522882590 refactor(plugins): install-time gates, the capability-audit hash chain and the registry through repositories 2026-09-24 03:24:23 +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 ab63eaf9ad refactor(plugins): runtime lifecycle, config CRUD and the uninstall cascade through repositories 2026-09-24 02:46:01 +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 425d889983 refactor(share): public share links, the pre-init photo fallback, and collection-places survivors through repositories 2026-09-24 01:24:21 +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 a51aedbc62 feat(server): plan 3j groundwork — scheduler onto CronRegistrarService, SDK-contract confirmation, repository fitness 2026-09-24 01:16:10 +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 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 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 c6687b2574 refactor(notifications): reminder crons, mailer, ntfy and webhook transports through repositories 2026-09-23 20:59:07 +02:00
jubnl db2db7f5a3 refactor(photos): trek photos, memories access and cache sweeps through repositories 2026-09-23 17:58:20 +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 2aeecd98fa refactor(accommodations): stays through repositories inside the existing transactions 2026-09-23 15:57:51 +02:00
jubnl 7ee0403eaf refactor(reservations): reservations, endpoints and travelers through repositories 2026-09-23 14:58:36 +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 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 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 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 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 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 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
jubnl d82395d0ae refactor(oauth): OAuth server tables through repositories
OauthClientsRepository/OauthTokensRepository/OauthConsentsRepository
replace OauthService's raw SQL (OA1-OA33). revokeChain's recursive CTE
and the oauth_clients join (its FK actually targets client_id, not the
row id the generated relation assumes) go through em.getKysely();
OA19's chain revoke is one nativeUpdate($in); OA12's consent grant is
em.upsert on the (client, user) unique key. revokeAllForUser built now
for Task 5. Every row-out read is disableIdentityMap: true; inserts go
through em.insert.
2026-09-22 21:18:08 +02:00
jubnl 44cf31c958 fix(server): non-numeric route ids answer the legacy not-found, never NaN (tokens, categories, tags); mint path back to two statements; identity-map regression pinned 2026-09-22 21:08:06 +02:00
jubnl 8d0dddf385 fix(db): row-out repository reads bypass the identity map — stale write-back over nativeUpdate at flush; insertUser via em.insert; settings round-trip pinned 2026-09-22 20:32:35 +02:00
jubnl 7453c7dafa feat(server): pre-init photo route and WS handshake run in a request context; InviteTokensRepository 2026-09-22 18:48:24 +02:00
jubnl e98f86efba fix(server): plan 3a re-review 2 follow-ups — absent-ORM boot branch pinned; airports boot hook never rejects; BOOT-SWEEP-001 asserts the seven routes; duplicate comment removed 2026-09-22 18:13:28 +02:00
jubnl 66703efeb7 feat(db): generated entities declare their repository type; test casts dropped 2026-09-22 18:01:45 +02:00
jubnl 46bb11f508 fix(server): plan 3a re-review follow-ups — plugin boot activation and the airports backfill inside a request context; the supervisor answers the child before failing closed; BOOT-SWEEP-001 drives the real boot hooks; ws adapter seam pinned 2026-09-22 17:39:38 +02:00
jubnl 761cd14b2b fix(server): plan 3a review follow-ups — fail closed without an ORM at every choke point; seam and D5 ratchet tests; dead method and DDL copies removed 2026-09-22 16:54:45 +02:00
jubnl 6db91c8bf3 refactor(addons): addon catalog and photo providers through repositories 2026-09-22 14:06:57 +02:00
jubnl 86c558cdd6 fix(audit): audit rows are native inserts, not a unit-of-work flush; closed test ORMs 2026-09-22 12:56:03 +02:00
jubnl c2da9d62f7 refactor(audit): audit log writes through AuditLogRepository 2026-09-22 12:34:49 +02:00
jubnl 7908914345 refactor(permissions): permission flags through AppSettingsRepository 2026-09-22 12:30:20 +02:00
jubnl ae2af05cad fix(server): phase 1 review follow-ups — awaited returns, logged upload-filter rejections, covered handshake/notice branches, call-graph gate in CI, dead test imports 2026-09-22 07:54:09 +02:00
jubnl 5c8decd3ea refactor(assignments, public-api, accommodations, places): async DB-touching methods; transactions through UnitOfWork 2026-09-22 05:21:48 +02:00
jubnl 3a8b54d761 fix(server): the journey hooks are awaited by their callers, not detached 2026-09-22 04:38:12 +02:00
jubnl 37992de7ab refactor(memories, photos, packing, share): async DB-touching methods; transactions through UnitOfWork 2026-09-22 02:21:06 +02:00
jubnl e28dc6de28 refactor(plugins): async DB-touching methods; transactions through UnitOfWork 2026-09-22 00:00:53 +02:00
jubnl e413308227 refactor(llm-parse, mcp-shared, oauth, place-shadow, route-usage, storage, todo, trip-invite): async DB-touching methods; transactions through UnitOfWork 2026-09-21 23:27:01 +02:00