Commit Graph

151 Commits

Author SHA1 Message Date
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 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 33b9488653 refactor(auth): AuthService and account cleanup through repositories 2026-09-22 23:17:17 +02:00
jubnl daef15be70 refactor(tokens): MCP and API tokens through McpTokensRepository 2026-09-22 20:23:11 +02:00
jubnl 57f4e29b9a refactor(auth): users table through UsersRepository; JWT and MFA lookups repository-backed 2026-09-22 19:39:01 +02:00
jubnl 66703efeb7 feat(db): generated entities declare their repository type; test casts dropped 2026-09-22 18:01:45 +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 6fafcd72f2 fix(settings): drop dead wiring and the speculative deleteForUser; strict row assertions 2026-09-22 15:47:02 +02:00
jubnl 59fa932ec8 test(server): harness constructors follow the Task 5 repository signatures; one test ORM per handle in the plugin host 2026-09-22 15:19:58 +02:00
jubnl 6763648c45 refactor(settings): user and instance settings through repositories
SettingsRepository (getForUser/upsertForUser/getOne/deleteForUser) replaces
the per-user settings table's raw SQL; SettingsService drops DatabaseService
entirely. instance-api-keys.ts's readInstanceApiKey/writeInstanceApiKey/
resolveApiKey take an explicit AppSettingsRepository/UsersRepository instead
of a raw connection.

An earlier version resolved those two repositories itself from the active
MikroORM request context, so none of its six callers needed to change. That
worked in production and e2e (always inside a real request) but broke
service construction in plain unit tests across every calling domain
(addons, auth x2, maps, transit, unsplash - 185 failures on a full run),
since none of them wrap a request context. Each of those six services now
injects its own AppSettingsRepository/UsersRepository and passes them
through explicitly, matching how every other converted repository in this
migration is consumed; their own SQL is untouched (outside Plan 3a).
2026-09-22 15:08:49 +02:00
jubnl 98e906a88e chore(addons): well-known gate wraps only the addon read in a request context; drop unused test factories 2026-09-22 14:23:39 +02:00
jubnl 6db91c8bf3 refactor(addons): addon catalog and photo providers through repositories 2026-09-22 14:06:57 +02:00
jubnl aa1067035f refactor(categories, tags): repositories replace raw SQL 2026-09-22 13:54:13 +02:00
jubnl e9391a9ae1 fix(server): non-HTTP entrypoints run inside an ORM request context; permission loads fail closed on context errors 2026-09-22 13:25:17 +02:00
jubnl b0905f9867 docs(db): owned-lookup call-site convention; refresh side effect; e2e ORM module spread notes 2026-09-22 12:53:47 +02:00
jubnl 4209343328 fix(db): PK reads refresh past the identity map; typed owned-lookup generics; e2e ORM module mirrors production config 2026-09-22 12:38:59 +02:00
jubnl 7908914345 refactor(permissions): permission flags through AppSettingsRepository 2026-09-22 12:30:20 +02:00
jubnl f460ae4fcb feat(db): AppSettings and Users repositories; forFeature wiring pattern 2026-09-22 12:06:13 +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 869d139412 refactor(reservations, booking-import, calendar, integrations, roadtrip): async DB-touching methods; transactions through UnitOfWork 2026-09-22 06:11:41 +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 845320e0a4 refactor(journey, oidc, place-enrichment, tokens, trip-members): async DB-touching methods; transactions through UnitOfWork 2026-09-22 04:16:07 +02:00
jubnl cb177ce655 refactor(vacay, admin, doc-sync): async DB-touching methods; transactions through UnitOfWork 2026-09-22 03:29:33 +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 6b755314d8 refactor(collab, collections, maps): async DB-touching methods; transactions through UnitOfWork 2026-09-22 01:49:18 +02:00
jubnl 4df2d83137 refactor(notifications, place-photos, backup): async DB-touching methods; transactions through UnitOfWork 2026-09-22 00:22:11 +02:00
jubnl fac181f45b chore(plugins): drop gate-only asyncs; observe the scheduler's rejection; async event-sink stub 2026-09-22 00:12:56 +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
jubnl aa587e2fb6 refactor(budget, common, day-notes, days): async DB-touching methods; transactions through UnitOfWork 2026-09-21 22:39:11 +02:00
jubnl 953e2526bb refactor(atlas, school-holidays, settings): async DB-touching methods; transactions through UnitOfWork 2026-09-21 21:23:10 +02:00
jubnl 0cf99a9939 refactor(realtime, systemNotices, addons, airports, audit, categories, permissions, query-helpers, tags, transit, trip-membership): async DB-touching methods; transactions through UnitOfWork 2026-09-21 20:48:03 +02:00
jubnl 27d044f9e8 chore(server): promise safety net and sweep tooling for the async migration 2026-09-21 19:01:38 +02:00
jubnl ef184ec7c2 test(server): ORM suites open the schema snapshot; RESET_TABLES derived from the schema 2026-09-21 18:12:07 +02:00
jubnl 418bd1c6b5 fix(test): route MikroORM's dynamic imports through vitest from the setup file, not the ORM config 2026-09-21 10:35:16 +02:00
jubnl 2bc9e927be test(server): snapshot harness keeps the legacy id semantics 2026-09-21 10:22:18 +02:00
jubnl e846c91a16 test(server): integration suites boot on the migrated schema snapshot 2026-09-21 10:13:40 +02:00
jubnl d7f39916d5 feat(db): request-context and unit-of-work helpers for the ORM, with concurrency tests 2026-09-21 10:01:36 +02:00
jubnl 565f72740b test(db): createTestOrm binds an ORM to a suite's own SQLite handle 2026-09-21 09:17:17 +02:00
Maurice 77a16d6f26 fix(places): deleting a place cancels the nights booked at it
A stay whose place was deleted kept its row with place_id NULL: still drawn in the
day header, still naming a hotel through its partner booking, and pointing
nowhere. Nothing could reach it any more and nothing cleaned it up.

It goes with the place now, through the accommodations domain rather than a
DELETE in the places path, because a stay takes its partner booking, that
booking's expense and the day stop it wrote with it — none of which is the places
domain's business to know. Both delete paths, single and bulk.

The service moves into an AccommodationsDomainModule, the assignments-domain
precedent: the service never touches PlacesService, only the MCP tool that writes
a place and a stay together does, so it can sit in a module PlacesModule is free
to import without closing a loop. AccommodationsModule keeps exporting it, so
every existing consumer is unchanged.
2026-09-13 15:36:02 +02:00
Maurice e3471e2dc8 fix(reservations): a night booked on the form belongs on the drive too
The booking form wrote the stay row itself, so it was the one door that left the
day stop out. A hotel entered there stayed invisible to road trip mode, which is
the same complaint as before with a different way in: enter the place twice or it
is not on the route.

It writes the stop now, through AccommodationsService rather than a second copy of
its SQL. The permission argument for not doing so does not hold: the night already
shows in the day header the moment the booking is saved, and the stop is that same
night in the other view, not a second edit to the plan.

Two holes go with it. Moving the booking left the stop on a day nobody sleeps there
any more, and deleting it left the stop behind entirely — in both cases still
carrying the booking's id, which is what the day list hides on, so nobody could
reach it to remove it. The stop now follows the stay and goes with it, and only
once the trip_id guard has confirmed the stay was this trip's to delete.
2026-09-13 12:38:21 +02:00
Maurice f0e1da2d81 feat(accommodations): put a booked night on its check-in day
A road-trip stop is a day assignment: the rail, the server-side plan and the
map all build their stops from day_assignments and only look the stay up
afterwards, to hang check-in and check-out on one. A stay written without an
assignment was therefore invisible to every routing surface, so a hotel entered
in the day planner never reached the road-trip view and had to be entered a
second time as an ordinary place. The road-trip side has always written both
halves in one go; this is the day planner catching up, in the domain that
writes the stay.

Booking a night now also assigns its place to the check-in day, inside the
transaction that already writes the stay and its partner hotel reservation, and
types the place as a hotel stop when it carries no type of its own, so it reads
exactly like a night booked in the road trip. Only the check-in day gets a
stop; the later nights ride on the stay row. A place already planned for that
day gets no second stop and the booking claims none, so cancelling it cannot
delete a stop somebody placed by hand. Moving the booking moves its own stop,
deleting it takes its own stop back, and a trip re-date carries it along with
the stay. All four write surfaces (REST, plugin RPC and both MCP tools) run the
same write and announce the same events; the answers carry the stop too,
because the broadcast skips the socket that sent the request.

New nullable day_assignments.accommodation_id marks a stop as a booking's own.
It stays NULL for every existing row on purpose: everything planned before this
was planned by hand, and no backfill rewrites a finished trip. A stay booked
earlier picks up its stop the next time somebody saves it.

The booking form keeps writing stays on its own: that surface is gated on
reservation_edit and the day stop is day_edit work.
2026-09-13 01:13:25 +02:00
Maurice 218d8baf0a feat(server): read visits and recorded routes from Dawarich
A new `integrations/dawarich` domain behind its own addon. Each reader
connects their own instance; the API key is encrypted at rest and never
returned. Nothing is written back to Dawarich, and no raw position is
kept in TREK: the recorded route is fetched per request for the window
being looked at and thrown away again.

What it produces are suggestions, never facts. A recorded stay becomes a
proposed place or journal entry, a country or city becomes a proposed
Atlas mark, and a stay near a wish becomes a proposed tick-off; each one
waits for the reader to confirm it. Identity is (user, Dawarich visit),
so a second sync neither duplicates nor overwrites what was accepted,
and deleting the result puts the suggestion back on the list.

The sync runs as a job on the central scheduler, one user at a time,
guarded against overlapping runs.
2026-09-12 23:36:49 +02:00
Maurice 41b18f970c feat(vacay): add manual school holiday calendars 2026-09-12 12:51:27 +02:00