mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
docs: tick permissions and auditLog in migrate.md and refresh the migration graph
This commit is contained in:
+3
-3
@@ -12,8 +12,8 @@ or the MCP layer gets a handle to the Nest app (app.get(TodoService)). Better to
|
||||
|
||||
Wave 2 — cross-cutting leverage (parallel to wave 3, high payoff)
|
||||
|
||||
4. permissions (149 lines, zero deps, 17 Nest consumers) → an injectable PermissionsService. Every module wrapper already calls checkPermission; this converts the single most-imported seam in one move.
|
||||
5. auditLog (171 lines, 13 Nest consumers) → AuditService.
|
||||
4. permissions (149 lines, zero deps, 17 Nest consumers) → an injectable PermissionsService (done 2026-07 — every module wrapper, the airtrail-import controller and PluginHostDepsFactory now inject it; the cache stays module-scoped so the DI singleton and permissions.bridge — kept for mcp/_shared.ts + adminService/authService/backupService/collectionsService — share one invalidation). Every module wrapper already calls checkPermission; this converts the single most-imported seam in one move.
|
||||
5. auditLog (171 lines, 13 Nest consumers) → AuditService (done 2026-07 — writeAudit is the injectable; getClientIp and the log*/LOG_LEVEL logger stay plain modules in nest/audit/ (client-ip.ts, audit-log.logger.ts with its frozen-at-import level + mkdir as a documented parity exception); audit.bridge covers mcp/index, oauthProvider and the legacy airtrail/immich/oauth services).
|
||||
6. tripAccess (9 lines) — don't migrate, delete: it's a wrapper around canAccessTrip, which DatabaseService now exposes. Absorb its 11 call sites opportunistically.
|
||||
|
||||
Wave 3 — domain services with existing modules, low fan-in
|
||||
@@ -27,7 +27,7 @@ Wave 4 — the coupled cluster (order matters here)
|
||||
importing legacy functions. — **Correction (migration-graph.md, borne out by the migration): the claimed ordering constraint doesn't exist at the service layer.** reservationService (done 2026-07) imported neither budgetService nor
|
||||
dayService; the budget/day coupling lives in the Nest wrapper's budget-sync seam and the MCP registrars, which keep their legacy imports until those domains migrate. Reservations went first as the frontier residue fold; dayService
|
||||
(done 2026-07 — the 592-line service folded into the wrapper `DaysService`, the accommodations seam in `nest/reservations/` now injects it, and the hand-rolled reorder/insert transactions became `db.transaction()`) followed;
|
||||
budgetService is next in the cluster (after the Wave-2 permissions + auditLog pair per migration-graph.md).
|
||||
budgetService is next in the cluster (the Wave-2 permissions + auditLog pair is done 2026-07; the exchangeRateService fold precedes it per migration-graph.md).
|
||||
9. Then placeService (7 internal deps, mostly on things migrated by now) and tripService (10 deps — the biggest hub; last in this wave, since nearly everything it needs will already be injectable).
|
||||
|
||||
Wave 5 — the heavyweights, last
|
||||
|
||||
+51
-44
@@ -1,8 +1,8 @@
|
||||
# Legacy `src/services/` dependency graph
|
||||
|
||||
Generated from the actual imports in `server/src` on **2026-07-27** (after the
|
||||
dayService migration — step 1 of the dependency-honest order below, following
|
||||
the reservationService residue fold).
|
||||
Wave-2 permissions + auditLog pair — step 1 of the dependency-honest order
|
||||
below, following the dayService fold).
|
||||
Regenerate any
|
||||
time — the extraction script only parses `from './x'` /
|
||||
`from '../services/x'` imports:
|
||||
@@ -26,14 +26,17 @@ How to read it:
|
||||
## Node classification
|
||||
|
||||
- **Already DI-native (legacy file deleted):** tags, categories, todo, packing, day-notes,
|
||||
trip-invite, assignments, share, settings, files, collab, vacay, reservations, day.
|
||||
trip-invite, assignments, share, settings, files, collab, vacay, reservations, day,
|
||||
permissions (module-scoped cache retained on purpose — the bridge and DI instances share
|
||||
one invalidation), audit (the `writeAudit` injectable; `client-ip.ts` and the deliberately
|
||||
side-effectful `audit-log.logger.ts` stay plain modules inside `nest/audit/`).
|
||||
- **Domain migration targets** (the wave material): adminService, airportService, atlasService,
|
||||
authService, backupService, budgetService, collectionsService,
|
||||
journeyService, journeyShareService, mapsService, notificationService, oauthService,
|
||||
oidcService, passkeyService, placeService, transitService,
|
||||
transitItineraryService, tripService, weatherService, wikiService.
|
||||
- **Cross-cutting Wave-2 targets:** permissions (17 nest consumers), auditLog (13 nest + 5
|
||||
out-of-container), tripAccess (delete, don't migrate).
|
||||
- **Cross-cutting Wave-2 targets:** permissions and auditLog are done (2026-07) — see the
|
||||
DI-native list above; only tripAccess remains (delete, don't migrate).
|
||||
- **Helpers that stay as plain modules** (pure/infra, not wave material): avatarUrl,
|
||||
queryHelpers, conflictResult, cookie, demo, distanceService, ephemeralTokens, apiKeyCrypto,
|
||||
mfaCrypto, passwordPolicy, webauthnConfig, timezoneService, llmConfig, kmlImport, placeImage,
|
||||
@@ -57,8 +60,7 @@ flowchart TD
|
||||
weather[weatherService]:::ready
|
||||
airport["airportService (boot special case)"]:::ready
|
||||
wiki[wikiService]:::ready
|
||||
permissions[permissions W2]:::ready
|
||||
auditLog[auditLog W2]:::ready
|
||||
collections[collectionsService]:::ready
|
||||
end
|
||||
|
||||
trip[tripService]:::hub
|
||||
@@ -75,8 +77,7 @@ flowchart TD
|
||||
passkey[passkeyService]:::blocked
|
||||
journey[journeyService]:::blocked
|
||||
journeyShare[journeyShareService]:::blocked
|
||||
collections[collectionsService]:::blocked
|
||||
backup[backupService]:::blocked
|
||||
backup["backupService (last by design)"]:::infra
|
||||
notifCluster["notifications cluster<br/>(notifications + prefs + inApp + channelRegistry)"]:::infra
|
||||
memories["memories/ cluster"]:::infra
|
||||
fx[exchangeRateService]:::infra
|
||||
@@ -89,37 +90,38 @@ flowchart TD
|
||||
maps --> notifCluster
|
||||
transit --> maps
|
||||
transitItin --> transit
|
||||
notifSvc --> notifCluster & auditLog
|
||||
notifSvc --> notifCluster
|
||||
admin --> auth & notifSvc & cleanup
|
||||
auth --> atlas & permissions
|
||||
oauth --> admin & auditLog
|
||||
auth --> atlas
|
||||
oauth --> admin
|
||||
oidc --> auth
|
||||
passkey --> auth
|
||||
journey --> memories
|
||||
journeyShare --> journey
|
||||
collections --> permissions
|
||||
backup --> permissions
|
||||
memories --> notifSvc & admin
|
||||
```
|
||||
|
||||
(`placeService → mapsService` is via the `placeEnrichment` helper; `mapsService/notificationService
|
||||
→ notifications cluster` are hard imports. `memories/` ↔ admin/notificationService edges make the
|
||||
journey/memories corner tangle with the admin corner.)
|
||||
journey/memories corner tangle with the admin corner. The former
|
||||
`auth/collections/backup → permissions` and `notifSvc/oauth → auditLog` edges are gone since the
|
||||
2026-07 Wave-2 pair: the permissions consumers repointed to `nest/permissions/permissions.bridge`,
|
||||
the writeAudit consumers to `nest/audit/audit.bridge`, and the log*-only consumers to the plain
|
||||
`nest/audit/audit-log.logger` — none of them block a migration anymore.)
|
||||
|
||||
## Full adjacency table
|
||||
|
||||
| service | imports (services/) | imported by (services/) | nest consumers | out-of-container consumers |
|
||||
|---|---|---|---|---|
|
||||
| `adminService` | apiKeyCrypto, authService, avatarUrl, llmConfig, memories/helpersService, notificationService, passwordPolicy, permissions, userCleanupService | airtrail/airtrailSync, memories/thumbnailService, oauthService | nest/addons/addons.service.ts, nest/admin/admin.service.ts, nest/booking-import/booking-import.service.ts, nest/booking-import/features.controller.ts, nest/collab/collab.mcp.ts, nest/collections/collections-addon.guard.ts, nest/integrations/airtrail-addon.guard.ts, nest/journey/journey.service.ts, nest/llm-parse/llm-config.resolver.ts, nest/oauth/oauth.service.ts, nest/packing/packing.mcp.ts, nest/platform/platform.routes.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/plugins/journal-entry-rows.controller.ts, nest/plugins/plugin-runtime.service.ts, nest/plugins/plugins.service.ts, nest/todo/todo.mcp.ts, nest/vacay/vacay.mcp.ts | mcp/index.ts, mcp/resources.ts, mcp/tools/atlas.ts, mcp/tools/budget.ts, mcp/tools/journey.ts, mcp/tools/prompts.ts, mcp/tools/trips.ts, scheduler.ts |
|
||||
| `adminService` | apiKeyCrypto, authService, avatarUrl, llmConfig, memories/helpersService, notificationService, passwordPolicy, userCleanupService (+ `permissions.bridge`) | airtrail/airtrailSync, memories/thumbnailService, oauthService | nest/addons/addons.service.ts, nest/admin/admin.service.ts, nest/booking-import/booking-import.service.ts, nest/booking-import/features.controller.ts, nest/collab/collab.mcp.ts, nest/collections/collections-addon.guard.ts, nest/integrations/airtrail-addon.guard.ts, nest/journey/journey.service.ts, nest/llm-parse/llm-config.resolver.ts, nest/oauth/oauth.service.ts, nest/packing/packing.mcp.ts, nest/platform/platform.routes.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/plugins/journal-entry-rows.controller.ts, nest/plugins/plugin-runtime.service.ts, nest/plugins/plugins.service.ts, nest/todo/todo.mcp.ts, nest/vacay/vacay.mcp.ts | mcp/index.ts, mcp/resources.ts, mcp/tools/atlas.ts, mcp/tools/budget.ts, mcp/tools/journey.ts, mcp/tools/prompts.ts, mcp/tools/trips.ts, scheduler.ts |
|
||||
| `airportService` | (none) | (none) | nest/airports/airports.service.ts, nest/booking-import/kitinerary-mapper.ts | db/database.ts, mcp/tools/mapsWeather.ts, mcp/tools/transports.ts |
|
||||
| `apiKeyCrypto` | (none) | adminService, airtrail/airtrailService, authService, llmConfig, mapsService, memories/helpersService, memories/immichService, memories/photoResolverService, memories/synologyService, memories/unifiedService, notifications, oidcService, unsplashService | nest/plugins/plugin-oauth.service.ts, nest/plugins/plugin-runtime.service.ts, nest/plugins/plugins.service.ts, nest/settings/settings.service.ts | db/migrations.ts |
|
||||
| `atlasService` | (none) | authService | nest/atlas/atlas.service.ts, nest/plugins/host/plugin-host-deps.factory.ts | mcp/resources.ts, mcp/tools/atlas.ts |
|
||||
| `auditLog` | (none) | airtrail/airtrailService, airtrail/airtrailSync, memories/immichService, notificationService, notifications, oauthService | nest/admin/admin.controller.ts, nest/auth/auth-public.controller.ts, nest/auth/auth.controller.ts, nest/auth/passkey.controller.ts, nest/backup/backup.controller.ts, nest/integrations/airtrail.controller.ts, nest/memories/immich.controller.ts, nest/oauth/oauth-api.controller.ts, nest/oauth/oauth-public.controller.ts, nest/plugins/plugin-runtime.service.ts, nest/plugins/plugins.controller.ts, nest/trip-invite/trip-invite.controller.ts, nest/trips/trips.controller.ts | index.ts, mcp/index.ts, mcp/oauthProvider.ts, middleware/globalMiddleware.ts, scheduler.ts |
|
||||
| `authService` | apiKeyCrypto, atlasService, avatarUrl, demo, distanceService, ephemeralTokens, mfaCrypto, passwordPolicy, permissions, tripMembership, userCleanupService, webauthnConfig | adminService, oidcService, passkeyService | nest/assignments/assignments.mcp.ts, nest/auth/auth.service.ts, nest/auth/passkey-enabled.guard.ts, nest/collab/collab.mcp.ts, nest/days/day-notes.mcp.ts, nest/days/days.mcp.ts, nest/oidc/oidc.service.ts, nest/packing/packing.mcp.ts, nest/reservations/reservations.mcp.ts, nest/tags/tags.mcp.ts, nest/todo/todo.mcp.ts, nest/vacay/vacay.mcp.ts | mcp/index.ts, mcp/tools/atlas.ts, mcp/tools/budget.ts, mcp/tools/collections.ts, mcp/tools/journey.ts, mcp/tools/notifications.ts, mcp/tools/places.ts, mcp/tools/transit.ts, mcp/tools/transports.ts, mcp/tools/trips.ts |
|
||||
| `authService` | apiKeyCrypto, atlasService, avatarUrl, demo, distanceService, ephemeralTokens, mfaCrypto, passwordPolicy, tripMembership, userCleanupService, webauthnConfig (+ `permissions.bridge`) | adminService, oidcService, passkeyService | nest/assignments/assignments.mcp.ts, nest/auth/auth.service.ts, nest/auth/passkey-enabled.guard.ts, nest/collab/collab.mcp.ts, nest/days/day-notes.mcp.ts, nest/days/days.mcp.ts, nest/oidc/oidc.service.ts, nest/packing/packing.mcp.ts, nest/reservations/reservations.mcp.ts, nest/tags/tags.mcp.ts, nest/todo/todo.mcp.ts, nest/vacay/vacay.mcp.ts | mcp/index.ts, mcp/tools/atlas.ts, mcp/tools/budget.ts, mcp/tools/collections.ts, mcp/tools/journey.ts, mcp/tools/notifications.ts, mcp/tools/places.ts, mcp/tools/transit.ts, mcp/tools/transports.ts, mcp/tools/trips.ts |
|
||||
| `avatarUrl` | (none) | adminService, authService, budgetService, inAppNotifications, journeyService, tripService | nest/collab/collab.service.ts, nest/files/files.service.ts, nest/packing/packing.service.ts, nest/reservations/reservations.service.ts | (none) |
|
||||
| `backupService` | permissions | (none) | nest/backup/backup.controller.ts, nest/backup/backup.service.ts | (none) |
|
||||
| `backupService` | (none — `permissions.bridge` only) | (none) | nest/backup/backup.controller.ts, nest/backup/backup.service.ts | (none) |
|
||||
| `budgetService` | avatarUrl, exchangeRateService, tripAccess | tripService, userCleanupService | nest/booking-import/booking-import.service.ts, nest/budget/budget.service.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/reservations/reservations.mcp.ts, nest/reservations/reservations.service.ts, nest/trips/trips.service.ts | mcp/resources.ts, mcp/tools/budget.ts, mcp/tools/transports.ts, mcp/tools/trips.ts |
|
||||
| `collectionsService` | permissions, placeImage | (none) | nest/collections/collections.service.ts, nest/plugins/host/plugin-host-deps.factory.ts | mcp/tools/collections.ts |
|
||||
| `collectionsService` | placeImage (+ `permissions.bridge`) | (none) | nest/collections/collections.service.ts, nest/plugins/host/plugin-host-deps.factory.ts | mcp/tools/collections.ts |
|
||||
| `conflictResult` | (none) | placeService | nest/packing/packing.controller.ts, nest/packing/packing.service.ts, nest/places/places.controller.ts, nest/plugins/host/plugin-host-deps.factory.ts | (none) |
|
||||
| `cookie` | (none) | (none) | nest/auth/auth-public.controller.ts, nest/auth/auth.service.ts, nest/auth/passkey.controller.ts, nest/oidc/oidc.controller.ts, nest/oidc/oidc.service.ts | (none) |
|
||||
| `demo` | (none) | authService | nest/auth/auth.controller.ts, nest/collections/collections.controller.ts, nest/files/files.controller.ts, nest/places/places.controller.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/trips/trips.controller.ts | middleware/auth.ts, middleware/mfaPolicy.ts |
|
||||
@@ -135,13 +137,12 @@ journey/memories corner tangle with the admin corner.)
|
||||
| `mapsService` | apiKeyCrypto, notifications, placePhotoCache | placeEnrichment, transitService | nest/booking-import/booking-import.service.ts, nest/maps/maps.service.ts | mcp/tools/mapsWeather.ts, mcp/tools/places.ts |
|
||||
| `mfaCrypto` | (none) | authService | (none) | (none) |
|
||||
| `notificationPreferencesService` | notifications, notifications/channelRegistry | inAppNotifications, notificationService, notifications, notifications/channelRegistry | nest/admin/admin.service.ts, nest/notifications/notifications.service.ts, nest/plugins/install/manifest.ts | (none) |
|
||||
| `notificationService` | auditLog, inAppNotifications, notificationPreferencesService, notifications, notifications/channelRegistry | adminService, memories/synologyService, memories/unifiedService | nest/admin/admin.controller.ts, nest/collab/collab.service.ts, nest/packing/packing.service.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/trips/trips.service.ts | scheduler.ts |
|
||||
| `notifications` | apiKeyCrypto, auditLog, notificationPreferencesService | mapsService, notificationPreferencesService, notificationService, notifications/builtins, oauthService, transitService, webauthnConfig | nest/auth/auth.service.ts, nest/notifications/notifications.service.ts, nest/oauth/oauth.service.ts, nest/oidc/oidc.service.ts, nest/platform/platform.routes.ts, nest/plugins/plugin-oauth.service.ts | index.ts, mcp/index.ts, mcp/oauthProvider.ts |
|
||||
| `oauthService` | adminService, auditLog, notifications | (none) | nest/oauth/oauth-api.controller.ts, nest/oauth/oauth.service.ts | mcp/index.ts, mcp/oauthProvider.ts |
|
||||
| `notificationService` | inAppNotifications, notificationPreferencesService, notifications, notifications/channelRegistry (+ `audit-log.logger`) | adminService, memories/synologyService, memories/unifiedService | nest/admin/admin.controller.ts, nest/collab/collab.service.ts, nest/packing/packing.service.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/trips/trips.service.ts | scheduler.ts |
|
||||
| `notifications` | apiKeyCrypto, notificationPreferencesService (+ `audit-log.logger`) | mapsService, notificationPreferencesService, notificationService, notifications/builtins, oauthService, transitService, webauthnConfig | nest/auth/auth.service.ts, nest/notifications/notifications.service.ts, nest/oauth/oauth.service.ts, nest/oidc/oidc.service.ts, nest/platform/platform.routes.ts, nest/plugins/plugin-oauth.service.ts | index.ts, mcp/index.ts, mcp/oauthProvider.ts |
|
||||
| `oauthService` | adminService, notifications (+ `audit.bridge`) | (none) | nest/oauth/oauth-api.controller.ts, nest/oauth/oauth.service.ts | mcp/index.ts, mcp/oauthProvider.ts |
|
||||
| `oidcService` | apiKeyCrypto, authService, tripMembership | (none) | nest/oidc/oidc.service.ts | (none) |
|
||||
| `passkeyService` | authService, webauthnConfig | (none) | nest/admin/admin.service.ts, nest/auth/passkey.controller.ts | (none) |
|
||||
| `passwordPolicy` | (none) | adminService, authService | (none) | (none) |
|
||||
| `permissions` | (none) | adminService, authService, backupService, collectionsService | nest/assignments/assignments.service.ts, nest/booking-import/booking-import.service.ts, nest/budget/budget.service.ts, nest/collab/collab.service.ts, nest/days/day-notes.service.ts, nest/days/days.service.ts, nest/files/files.service.ts, nest/integrations/airtrail-import.controller.ts, nest/packing/packing.service.ts, nest/places/places.service.ts, nest/plugins/host/plugin-host-deps.factory.ts, nest/reservations/accommodations.service.ts, nest/reservations/reservations.service.ts, nest/share/share.service.ts, nest/todo/todo.service.ts, nest/trip-invite/trip-invite.service.ts, nest/trips/trips.service.ts | mcp/tools/_shared.ts |
|
||||
| `placeEnrichment` | mapsService | placeService | (none) | (none) |
|
||||
| `placeImage` | (none) | collectionsService, placeService | nest/collections/collections.controller.ts, nest/common/place-image-upload.ts, nest/places/places.controller.ts | (none) |
|
||||
| `placePhotoCache` | (none) | mapsService, placeService | nest/maps/maps.service.ts, nest/share/share.service.ts | scheduler.ts |
|
||||
@@ -169,7 +170,10 @@ journey/memories corner tangle with the admin corner.)
|
||||
and `synology/unified → notificationService` couple this cluster to the admin corner.
|
||||
- **`airtrail/`**: `airtrailClient` (base) ← mapper ← service ← import/sync; `import`/`sync`
|
||||
consume `adminService` and (since the 2026-07 reservations fold) the
|
||||
`nest/reservations/reservations.bridge` instead of the deleted `reservationService`.
|
||||
`nest/reservations/reservations.bridge` instead of the deleted `reservationService`; since
|
||||
the auditLog fold, `airtrailService` writes audits via `nest/audit/audit.bridge` and
|
||||
`airtrailSync` logs via the plain `nest/audit/audit-log.logger` (same split in
|
||||
`memories/immichService` → bridge).
|
||||
|
||||
## Decoding "what's next"
|
||||
|
||||
@@ -177,7 +181,8 @@ journey/memories corner tangle with the admin corner.)
|
||||
|
||||
| Candidate | Why now / why not | Bridge tax (legacy dependents + out-of-container) |
|
||||
|---|---|---|
|
||||
| **permissions / auditLog (Wave 2)** ← pick | Zero deps, giant fan-in (17 / 13 nest consumers) — pure leverage, parallelizable with any domain migration | mcp `_shared.ts`; index/scheduler/middleware for auditLog |
|
||||
| **exchangeRateService fold → budgetService** ← pick | The Wave-2 pair is done (2026-07); this is step 2 of the dependency-honest order and **is** the tripService unblock | `tripService`, `userCleanupService`; mcp budget/transports/trips registrars |
|
||||
| **collectionsService** | Newly frontier-ready — its only legacy deps are the placeImage helper + `permissions.bridge` | `mcp/tools/collections.ts` |
|
||||
| **atlasService** | Zero deps, but its legacy dependent is `authService` (Wave-5) → bridge lives long | `authService`; `mcp/tools/atlas.ts`, `mcp/resources.ts` |
|
||||
| **weatherService / wikiService / airportService** | Independent leaves; airport has the `db/database.ts` boot lazy-require special case | little / none |
|
||||
|
||||
@@ -189,31 +194,33 @@ journey/memories corner tangle with the admin corner.)
|
||||
`collab.bridge` / `vacay.bridge` / `reservations.bridge` / `days.bridge`
|
||||
repoints). Migrating budget **is** the tripService unblock.
|
||||
- `placeService` ← `mapsService` (via placeEnrichment) ← notifications cluster.
|
||||
- `notificationService` ← notifications cluster + `auditLog` (Wave 2 first).
|
||||
- `notificationService` ← notifications cluster (its auditLog edge is now the plain
|
||||
`audit-log.logger` import — gone as a blocker since the 2026-07 Wave-2 pair).
|
||||
- `transitItineraryService` ← `transitService` (← mapsService) — its reservation edge is now
|
||||
the `reservations.bridge` repoint (type-only).
|
||||
- `adminService`/`oauthService`/`authService` corner: `authService` ← `atlasService` +
|
||||
`permissions`; `adminService` ← `authService` + `notificationService`; `oauthService` ←
|
||||
`adminService`. Order inside the corner: permissions → atlas → auth → admin → oauth
|
||||
(oidc/passkey ride auth).
|
||||
- `adminService`/`oauthService`/`authService` corner: `authService` ← `atlasService`
|
||||
(its permissions edge is now the `permissions.bridge` repoint); `adminService` ←
|
||||
`authService` + `notificationService`; `oauthService` ← `adminService`. Order inside the
|
||||
corner: atlas → auth → admin → oauth (oidc/passkey ride auth; permissions done 2026-07).
|
||||
- `journeyService` ← `memories/` cluster (which itself touches admin + notificationService) →
|
||||
`journeyShareService` after.
|
||||
- `collectionsService`/`backupService` ← `permissions` (Wave 2); backup stays last by design
|
||||
(owns the closeDb/reinitialize lifecycle).
|
||||
- `collectionsService`/`backupService`: unblocked since the permissions fold (their edges are
|
||||
`permissions.bridge` repoints now); backup still stays last by design (owns the
|
||||
closeDb/reinitialize lifecycle).
|
||||
|
||||
**Dependency-honest order** (each step's deps are already done at that point;
|
||||
`vacayService`, `reservationService` (the residue fold) and `dayService` were the
|
||||
first three frontier picks — all done 2026-07, after `collabService` completed
|
||||
Wave 3):
|
||||
`vacayService`, `reservationService` (the residue fold), `dayService` and the
|
||||
Wave-2 `permissions` + `auditLog` pair were the first frontier picks — all done
|
||||
2026-07, after `collabService` completed Wave 3):
|
||||
|
||||
1. `permissions` + `auditLog` (Wave 2 — anytime, ideally early and in parallel)
|
||||
2. `exchangeRateService` fold → `budgetService` (then `userCleanupService` is free)
|
||||
3. `tripService` — all remaining domain edges + userCleanup now gone
|
||||
4. notifications cluster → `notificationService`
|
||||
5. `mapsService` → `transitService` → `placeService` → `transitItineraryService`
|
||||
6. `atlasService` → `authService` (+ oidc/passkey) → `adminService` → `oauthService`
|
||||
7. `memories/` cluster → `journeyService` → `journeyShareService`; `collectionsService`
|
||||
8. Independent any time: `weatherService`, `wikiService`, `airportService` (move the
|
||||
1. `exchangeRateService` fold → `budgetService` (then `userCleanupService` is free)
|
||||
2. `tripService` — all remaining domain edges + userCleanup now gone
|
||||
3. notifications cluster → `notificationService`
|
||||
4. `mapsService` → `transitService` → `placeService` → `transitItineraryService`
|
||||
5. `atlasService` → `authService` (+ oidc/passkey) → `adminService` → `oauthService`
|
||||
6. `memories/` cluster → `journeyService` → `journeyShareService`; `collectionsService`
|
||||
(frontier-ready since the permissions fold — can also go any time)
|
||||
7. Independent any time: `weatherService`, `wikiService`, `airportService` (move the
|
||||
boot backfill into Nest bootstrap when you do it); `backupService` last
|
||||
|
||||
**Corrections to `migrate.md` this graph surfaced:**
|
||||
|
||||
@@ -28,7 +28,8 @@ mount to Nest and leaves the sibling trip routes (days, places, ...) on Express.
|
||||
- **Phase 2 (trip sub-domains):** vacay (addon), packing, todo.
|
||||
- **DI-native services (legacy `src/services/*` deleted):** tags, categories,
|
||||
todo, packing, day-notes, trip-invite, assignments, share, settings, files,
|
||||
collab, vacay, reservations, day — see the migration recipe below.
|
||||
collab, vacay, reservations, day, permissions, audit — see the migration
|
||||
recipe below.
|
||||
|
||||
## Cross-cutting Foundation pieces
|
||||
|
||||
@@ -155,11 +156,38 @@ service, `TripsService` + the assignments/reservations MCP controllers
|
||||
converted to injection, and a 6-export `days.bridge.ts` for the legacy
|
||||
`tripService` and the still-legacy transit + transports registrars; the DTO
|
||||
ratchet for its 4 day + 2 accommodation grandfathered body contracts landed
|
||||
as a sibling commit).
|
||||
as a sibling commit);
|
||||
permissions followed (the first Wave-2 **cross-cutting** migration and the
|
||||
first greenfield module in the series — no prior wrapper, controller, MCP
|
||||
surface or DTO of its own: a new `nest/permissions/` whose
|
||||
`PermissionsService` is injected by 16 domain services, the airtrail-import
|
||||
controller and `PluginHostDepsFactory` (its 16th constructor dep) in one move,
|
||||
plus a 5-function `permissions.bridge.ts` for `mcp/tools/_shared.ts` — one
|
||||
repoint covering every `hasTripPermission` call site — and the four legacy
|
||||
consumers adminService/authService/backupService/collectionsService; the
|
||||
permissions **cache stays module-scoped** in `permissions.service.ts` on
|
||||
purpose, so the bridge instance and the container singleton share one cache
|
||||
and backup-restore's bridge-side `invalidatePermissionsCache()` flushes what
|
||||
request handlers serve; the domain e2e suites swapped their path mocks for a
|
||||
`vi.spyOn(app.get(PermissionsService), 'checkPermission')` instance spy);
|
||||
auditLog followed (the other Wave-2 half, split into five files: the
|
||||
injectable `AuditService` (`writeAudit` over `DatabaseService`), the pure
|
||||
`client-ip.ts` (files.constants precedent — the four getClientIp-only
|
||||
controllers stay plain imports), the deliberately side-effectful plain
|
||||
`audit-log.logger.ts` — frozen-at-import `LOG_LEVEL` and the import-time
|
||||
`data/logs` mkdir are a documented parity exception to the no-side-effects
|
||||
rule because `index.ts` lazy-requires it pre-container and tests/setup.ts
|
||||
sets the level pre-import — plus `audit.module.ts` and a full-surface
|
||||
`audit.bridge.ts` for `mcp/index.ts`, `mcp/oauthProvider.ts` and the legacy
|
||||
airtrail/immich/oauth services, while log*-only consumers (index.ts's lazy
|
||||
require strings, scheduler, globalMiddleware, notifications) point at the
|
||||
logger directly; 8 controllers + `PluginRuntimeService` inject `AuditService`,
|
||||
and the domain e2e suites dropped the audit mock entirely — writeAudit runs
|
||||
for real against an `audit_log` table in their temp DBs).
|
||||
Repeat these steps per
|
||||
service (next up: permissions + auditLog — the Wave-2 cross-cutting pair the
|
||||
dependency-honest order in `migration-graph.md` promotes now that dayService
|
||||
is folded; then the exchangeRateService fold → budgetService). This is a
|
||||
service (next up: the exchangeRateService fold → budgetService per the
|
||||
dependency-honest order in `migration-graph.md`, now that the Wave-2
|
||||
permissions + auditLog pair is folded). This is a
|
||||
**pure relocation** — byte-identical
|
||||
SQL, statuses, bodies, and error strings. The plugin RPC host is **no longer a
|
||||
bridge consumer**: since Option A of `src/nest/plugins/DI-MIGRATION.md` it
|
||||
|
||||
@@ -19,7 +19,7 @@ The plugin runtime has three layers. Only the third is "un-Nest".
|
||||
|---|---|---|---|
|
||||
| Sandbox / transport | `supervisor/plugin-supervisor.ts`, `runtime/plugin-host-entry.ts`, `protocol/envelope.ts` | Forked child per plugin, IPC envelopes, permission tables, actor resolution, rate limiting, RSS policing | Intentionally not — this is the security boundary |
|
||||
| Enforcement | `host/rpc-host.ts` (~1330 lines) | `PluginRpcHost`: builds a per-plugin method map at spawn — a handler is registered **only if the plugin holds the unlocking permission** (registration = authorization). Depends only on the `HostDeps` interface | Neutral — decoupled by design |
|
||||
| **Wiring** | `host/plugin-host-deps.factory.ts` (was `create-rpc-host.ts`) | Fills the ~130-member `HostDeps` object. Since Option A: an `@Injectable() PluginHostDepsFactory` with the DI-native domain services (`BudgetService`, `ReservationsService`, `TagsService`, `CategoriesService`, `TodoService`, `PluginOAuthService`) constructor-injected, fourteen domains as of 2026-07; legacy `services/*` domains stay plain function imports until their own migration. Raw `db`/`broadcast` also stay until injectable equivalents exist | **Yes (Option A)** — drains further per §3 |
|
||||
| **Wiring** | `host/plugin-host-deps.factory.ts` (was `create-rpc-host.ts`) | Fills the ~130-member `HostDeps` object. Since Option A: an `@Injectable() PluginHostDepsFactory` with the DI-native domain services (`BudgetService`, `ReservationsService`, `TagsService`, `CategoriesService`, `TodoService`, `PluginOAuthService`) constructor-injected, fifteen domains as of 2026-07 (permissions joined with the Wave-2 pair); legacy `services/*` domains stay plain function imports until their own migration. Raw `db`/`broadcast` also stay until injectable equivalents exist | **Yes (Option A)** — drains further per §3 |
|
||||
| Host state | `host/plugin-host-state.ts` | Deliberately module-level (NOT a provider): the per-plugin data-DB map (`getPluginDataDb`/`closePluginDataDb`) and daily broker budgets (`budgetFor`/`pluginBudgetUsage`). Must be one shared instance across host recreations, and is read by `PluginsService`, which the factory imports from — folding it into the injectable would create a provider cycle | Intentionally not |
|
||||
|
||||
Key fact that made Option A cheap: the wiring is **called from inside a Nest
|
||||
@@ -111,8 +111,11 @@ collabService swapped in 2026-07 — its seven imported symbols became the
|
||||
injected `CollabService`, completing Wave 3; vacayService swapped in 2026-07 —
|
||||
its four imported symbols became the injected `VacayService`; dayService
|
||||
swapped in 2026-07 — its eleven imported symbols (the heaviest single import)
|
||||
became the injected `DaysService`; the remaining factory imports are all
|
||||
Wave-4+ domains: trips, places, journeys, atlas, collections).
|
||||
became the injected `DaysService`; permissions swapped in 2026-07 with the
|
||||
Wave-2 pair — its `checkPermission` import became the injected
|
||||
`PermissionsService` (the auditLog half never touched the factory: the plugin
|
||||
host's audit trail is the separate `plugin-audit.ts`); the remaining factory
|
||||
imports are all Wave-4+ domains: trips, places, journeys, atlas, collections).
|
||||
|
||||
### Test impact (as landed)
|
||||
|
||||
@@ -120,7 +123,7 @@ Wave-4+ domains: trips, places, journeys, atlas, collections).
|
||||
`PluginRpcHost` directly with hand-built `HostDeps`).
|
||||
- `tests/unit/plugins/plugin-host-deps.factory.test.ts` (was
|
||||
`create-rpc-host.test.ts`) — the six DI-domain path mocks became constructor
|
||||
stubs (fourteen stubs as of the 2026-07 day migration); the ~23
|
||||
stubs (fifteen stubs as of the 2026-07 permissions migration); the ~22
|
||||
legacy-service path mocks remain; a file-local shim keeps the
|
||||
historical `createRealRpcHost(id, granted)` call sites and supplies a default
|
||||
no-op router.
|
||||
|
||||
Reference in New Issue
Block a user