Merge branch 'mai/knuth/phase-3k-mgmt-survey' (docs-only: teardown plan)
This commit is contained in:
176
docs/plans/mgmt-teardown.md
Normal file
176
docs/plans/mgmt-teardown.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# mgmt.msbls.de teardown — plan
|
||||
|
||||
> Worker: knuth (research shift) · Date: 2026-05-15
|
||||
> Status: **PLAN — pending m's read + go/no-go**. No code touched in this shift.
|
||||
> Source: live audit of `~/dev/web/msbls.de` (gitea `m/msbls.de`) on the date above. Cross-repo grep across `~/dev/` for hardcoded `/mgmt/` URLs.
|
||||
|
||||
## TL;DR
|
||||
|
||||
mgmt.msbls.de is a thin SvelteKit cockpit with **three live routes** plus an auth shell. Two of them (`/mgmt/login`, the auth + cookie infra) projax already does at parity. The third (`/mgmt`, the Work-Cockpit) composes data projax does NOT yet expose — CalDAV `Work` + `Plan` calendars, mWorkRepo PARA folders, mBrian `[topic]` + `[workday]` nodes — but only the CalDAV slice is shipped on mgmt today; mWorkRepo and mBrian slices are stubbed placeholders per Slice 4–5 of `msbls.de/docs/plans/mgmt-self.md`.
|
||||
|
||||
Teardown is **two-thirds achievable today** — projax already provides the auth surface and a dashboard with VTODO + Gitea aggregation. The remaining third (the Work-Cockpit-specific composition: `Work` + `Plan` calendar focus, mWorkRepo PARA cards, HL topic threads) is **either out-of-scope-for-projax** (mWorkRepo is HL-internal content, not project-management data) or a small feature gap (CalDAV calendar-set filtering already exists on projax via `caldav-list` item_links, just needs m to link `Work` + `Plan` to a projax item).
|
||||
|
||||
**Cross-repo dependency check**: a single grep across `~/dev/` finds the string `mgmt.msbls.de` in **only** mgmt's own source and one stale comment in `projax/deploy/dokploy.yaml`. No other repo links to mgmt routes. No cron jobs or external systems hit the mgmt API surface (mgmt has no `/api/*` routes — the cockpit is server-load only).
|
||||
|
||||
---
|
||||
|
||||
## §1 What mgmt.msbls.de actually does today
|
||||
|
||||
### Routing model
|
||||
|
||||
mgmt is **mounted via host-routing**, not a plain subpath:
|
||||
|
||||
- `mgmt.msbls.de` (the host) is recognised by `src/lib/host-routing.ts`.
|
||||
- `src/hooks.ts` reroute maps incoming `mgmt.msbls.de/…` URLs onto `/mgmt/…` so file-based routing works.
|
||||
- `src/hooks.server.ts` enforces existence-leak: any `/mgmt/*` URL arriving on a non-cockpit host (`www.msbls.de`, apex) returns plain `Not Found` before the route loads. So `www.msbls.de/mgmt/self` and `mgmt.msbls.de/self` both work, but only on the right host.
|
||||
- Compat: a legacy Traefik AddPrefix middleware is still expected — `mapToCockpitRoute` is idempotent against it so the deploy can move off Traefik prepending without code change.
|
||||
|
||||
### Routes (the complete list)
|
||||
|
||||
| Path | File | What it does | Who calls it |
|
||||
|---|---|---|---|
|
||||
| `/mgmt` (root) | `mgmt/+page.server.ts` + `mgmt/+page.svelte` | The **Work-Cockpit**: tabs (today / week / quarter), Operational Stream (open VTODOs + VEVENTs from `Work`+`Plan` CalDAV calendars), Strategic Threads (three placeholder stub cards for mWorkRepo + mBrian content not yet wired). All UI in German. | m, in a browser, after auth |
|
||||
| `/mgmt/login` | `mgmt/login/+page.server.ts` + `mgmt/login/+page.svelte` | Email + password against Supabase Auth; sets `access_token` + `refresh_token` cookies scoped to `.msbls.de` so sessions survive subdomain crossing. | m, browser |
|
||||
| `/mgmt/self` | `mgmt/self/+page.server.ts` | **Stub redirect** to `/`. Pre-refactor the cockpit lived at `/mgmt/self`; redirect keeps old bookmarks working. | legacy browser history |
|
||||
| `/mgmt/*` (any other) | `mgmt/+layout.server.ts` | Auth guard. Unauth + safe-method → 404 (no existence leak). Unauth + unsafe-method → 302 to `/login`. | every authenticated path |
|
||||
|
||||
### Auth shell (server-side bits)
|
||||
|
||||
- `hooks.server.ts` — runs on every request, calls `authenticateRequest()`, populates `locals.userId`, persists refreshed tokens as cookies.
|
||||
- `lib/server/auth.ts` — `authenticateRequest()` validates JWT cookie or `Authorization: Bearer`, falls back to `refresh_token`. ~100 lines. Cookies scoped to `msbls.de` (override via `COOKIE_DOMAIN`). Used by the layout guard.
|
||||
- `lib/server/supabase.ts` — `getSupabaseAdmin()` + `getSupabaseAnon()`. Same Supabase project as mBrian.
|
||||
- `lib/server/caldav.ts` — REPORT-based VTODO + VEVENT reader against `dav.msbls.de`. Hand-rolled iCal parsing. Cache TTL 60s.
|
||||
- `lib/server/mbrian.ts` — `mb()` schema helper, `setDbClient(getSupabaseAdmin())` on init. **Not yet consumed** by any route (Slice 5 work).
|
||||
|
||||
### Feature flags / env conditions
|
||||
|
||||
- `COOKIE_DOMAIN` env: shared cross-subdomain by default (`msbls.de`); override to `none` for localhost.
|
||||
- `CALDAV_BASE`/`USER`/`PASS` — required by the calendar reader. Absent → calendar fetches throw `CalDAVError` and the page renders per-calendar error chips (settled-promise pattern).
|
||||
- `GITEA_TOKEN` — referenced in the design for Slice 4 (mWorkRepo runtime API) but **not yet used** in shipped code.
|
||||
- No webhook receivers, no `/api/*` routes, no cron, no background jobs. The site is request-response only.
|
||||
|
||||
### Out-of-scope context
|
||||
|
||||
`docs/plans/mgmt-self.md` (in msbls.de) is the original design doc. It lists 6 slices; only Slice 1–3 (today + week views with CalDAV data) and the auth shell appear shipped. Slices 4–6 (mWorkRepo cards, mBrian topic cards, quarter view, markdown rendering) are placeholders. The design treats the cockpit as a **read-only desktop pull surface** with Obsidian / CalDAV / mBrian remaining the authoring source-of-truth.
|
||||
|
||||
---
|
||||
|
||||
## §2 Mapping mgmt → projax
|
||||
|
||||
| mgmt feature | projax equivalent | gap / notes |
|
||||
|---|---|---|
|
||||
| `/mgmt/login` (Supabase email+password) | `/login` on projax (Supabase email+password) | **parity ✓** — same Supabase project, same access_token/refresh_token cookie pair. Cookie scope differs: mgmt uses `Domain=.msbls.de` for cross-subdomain SSO; projax uses host-scoped (no Domain attribute). Decision needed: do we want projax to inherit cross-subdomain cookies so a session on mgmt carries to projax? See §6 risk. |
|
||||
| `/mgmt/+layout.server.ts` (404-on-anon auth guard) | `web/auth.go authMiddleware` (302-to-login auth guard) | **near-parity** — projax is more permissive (302 instead of 404 for anon) which leaks the existence of authenticated paths but matches the "behind Tailscale anyway" risk model. Could tighten if m wants. |
|
||||
| `lib/server/caldav.ts` (REPORT VTODO + VEVENT against `dav.msbls.de`) | `caldav/caldav.go` (REPORT VTODO + VEVENT + writeback) | **projax is more capable** — adds VTODO PUT, DELETE, ETag-aware writeback (Phase 2.b). The reader surface overlaps. |
|
||||
| `/mgmt` Operational Stream (VTODOs today + VEVENTs today, deduped from `Work`+`Plan`) | `/dashboard` Tasks card (VTODOs from every linked CalDAV list, bucketed Overdue/Today/Tomorrow/Week/NoDue) | **functional parity for tasks; gap for VEVENTs.** projax's dashboard aggregates *every* `caldav-list`-linked calendar, not just `Work`+`Plan`. To restrict to those two, m links only those calendars to a "work" projax item — already supported via `/admin/caldav`. VEVENTs (meetings/calls) are NOT yet on projax's dashboard — see §3 Gap 1. |
|
||||
| `/mgmt` Operational Stream (`[workday]` event-children from mBrian deduped against VEVENTs) | none | **gap, but probably non-blocker** — `[workday]` is mBrian-internal content. projax never planned to consume mBrian; per the original PRD "mBrian topic-hub linkage" is deferred to Phase 3 and exists today only as a mention. Recommend: leave on mgmt's design backlog, do not port to projax. |
|
||||
| `/mgmt` Strategic Threads — mWorkRepo `2 - projects/` + `3 - areas/` cards | none | **gap, parked, probably stays parked** — mWorkRepo is HL-internal Obsidian content. projax exists for project-management data backbone, not for being a markdown viewer. Recommend: park the Strategic Threads tab on mgmt indefinitely (it's only stubs anyway), or, if m really wants a unified surface, render mWorkRepo cards via projax's `gitea-repo` item_link surface (would need a Gitea-content reader, see §3 Gap 2). |
|
||||
| `/mgmt` Strategic Threads — mBrian `[topic]` cards | none | **gap, same recommendation as above** — mBrian topic-hub linkage is a future projax-Phase concern, not a teardown blocker. |
|
||||
| `/mgmt` view toggle (today / week / quarter) | `/dashboard` cards are today-focused with relative bucketing (Overdue / Today / Tomorrow / This week / No due) | **near-parity for today + week**, **gap for quarter view.** Quarter is a Slice-6 placeholder on mgmt anyway — empty in production. Not a teardown blocker. |
|
||||
| `/mgmt/self` legacy redirect → `/mgmt` | n/a | **drop on teardown** — once mgmt is gone, the redirect is irrelevant. |
|
||||
| Cross-subdomain auth (cookies on `Domain=.msbls.de`) | projax cookies are host-scoped | **gap if we want session continuity from www → projax**. See §6. Probably YAGNI — projax has its own /login and m typically signs in once per device. |
|
||||
|
||||
---
|
||||
|
||||
## §3 Gaps that block teardown
|
||||
|
||||
In rough order of cost. Anything not listed is either already on projax or is a deliberate "stays parked" item.
|
||||
|
||||
### Gap 1 — VEVENTs (meetings/calls) on projax dashboard
|
||||
**What's missing:** the dashboard Tasks card shows VTODOs only. The mgmt cockpit also surfaces VEVENTs from `Work`+`Plan` ordered by start-time, with location + categories. So "meetings today" is a real mgmt feature projax does not replicate.
|
||||
|
||||
**Scope:** small. The CalDAV client already lists VEVENTs (via `caldav.ListVEVENTs`); the dashboard handler would need a fourth card or a merged "Today's schedule" tab combining VTODOs + VEVENTs. Sort by due/start-time.
|
||||
|
||||
**Suggested phase:** 3l (small follow-on).
|
||||
|
||||
### Gap 2 — mWorkRepo content cards (if m wants them on projax)
|
||||
**What's missing:** mWorkRepo `2 - projects/` + `3 - areas/` rendered as cards with title + last-modified. This is a Slice-4 design goal on mgmt that **never shipped** — even mgmt only shows placeholder stubs today.
|
||||
|
||||
**Scope:** medium. Would need a Gitea-content reader (`GET /repos/.../contents/<path>?ref=main`) plus a new dashboard card. Cache TTL like the issues card. Could surface as a "linked-repo files" disclosure inside the existing Issues card rather than a separate card.
|
||||
|
||||
**Suggested phase:** 3m or later (low priority; current value is "zero" because mgmt never shipped this either).
|
||||
|
||||
### Gap 3 — mBrian `[topic]` cards
|
||||
**What's missing:** HL topic cards (paliad, schadensberechnung) summarising recent linked events.
|
||||
|
||||
**Scope:** medium-large — first need mBrian access from projax (the PRD parked this to Phase 3). Then per-topic recent-events rollup.
|
||||
|
||||
**Suggested phase:** out-of-scope for teardown. mgmt never shipped this either. If m wants topic surfacing, it's a future Otto-PWA / mBrian project, not projax.
|
||||
|
||||
### Gap 4 — Cross-subdomain SSO between www.msbls.de and projax (optional)
|
||||
**What's missing:** projax cookies are host-scoped. A session on `www.msbls.de/login` does not carry to `projax.msbls.de`.
|
||||
|
||||
**Scope:** small (one-line cookie-domain change) but **probably YAGNI** — m signs in to projax once per device, the session lives a year, this is a non-issue in practice.
|
||||
|
||||
**Suggested phase:** skip unless m specifically asks.
|
||||
|
||||
---
|
||||
|
||||
## §4 Migration sequence
|
||||
|
||||
Order matters: don't remove anything until projax covers the equivalent + browser history can route around it.
|
||||
|
||||
1. **(Optional, only if m wants meetings on the dashboard)** Build Gap 1 — add VEVENTs to projax's `/dashboard`. One slice, on a fresh branch. Ship + verify.
|
||||
2. **Confirm projax is the daily-driver.** m uses `/dashboard` for ~1 week, sees that everything he was checking on mgmt is now there (modulo §3 gaps he's chosen to drop).
|
||||
3. **Set up Traefik / Dokploy redirects on mgmt.msbls.de** pointing to projax equivalents:
|
||||
- `mgmt.msbls.de/` → `projax.msbls.de/dashboard` (HTTP 301)
|
||||
- `mgmt.msbls.de/login` → `projax.msbls.de/login`
|
||||
- `mgmt.msbls.de/self` → `projax.msbls.de/dashboard`
|
||||
- any other `/mgmt/*` → `projax.msbls.de/dashboard` (catch-all)
|
||||
4. **Verify external dependencies = zero** (already done in this audit — see §6). Wait one week with redirects live so any stragglers in browser history surface.
|
||||
5. **Remove `src/routes/mgmt/**` from m/msbls.de** in a PR. Drop `src/hooks.ts` reroute hook, drop the cockpit-host branches in `src/hooks.server.ts`, drop `src/lib/host-routing.ts` + its tests. mgmt is now gone from the codebase.
|
||||
6. **Drop unused auth code IF mgmt was the only consumer:**
|
||||
- msbls.de's `src/lib/server/auth.ts`, `supabase.ts`, `caldav.ts`, `mbrian.ts` were added specifically for the cockpit. Remove them.
|
||||
- Keep `hooks.server.ts` only if any other route needs auth (today: none — strip the file entirely or reduce it to a no-op pass-through).
|
||||
- Drop env vars from Dokploy: `SUPABASE_*`, `CALDAV_*`, `COOKIE_DOMAIN`, `GITEA_TOKEN` (msbls.de side — projax keeps its own).
|
||||
7. **Update m/msbls.de homepage** (if it currently advertises mgmt — it doesn't, just checking).
|
||||
8. **Decommission the `mgmt.msbls.de` Traefik label / DNS entry** on Dokploy. Optional final step — leaving the redirect live forever is also fine.
|
||||
|
||||
---
|
||||
|
||||
## §5 What stays in m/msbls.de
|
||||
|
||||
The public face of msbls.de:
|
||||
|
||||
- `/` — services + slop CTA homepage (`+page.svelte` at root)
|
||||
- `/impressum` — required legal
|
||||
- `/slop` — slop CTA landing
|
||||
- `/[code]` — Shlink-style short-URL fallback (`+server.ts`)
|
||||
- The whole `src/lib/components/` set + styles (Hero, CardGrid, etc.)
|
||||
|
||||
What can go: every `src/routes/mgmt/` file, every `src/lib/server/` file (only used by mgmt), the cockpit-aware reroute hook, `src/lib/host-routing.{ts,test.ts}` if no other host-routing is needed. The Dockerfile's mBrian submodule clone step is mgmt-only and can be removed.
|
||||
|
||||
---
|
||||
|
||||
## §6 Risks
|
||||
|
||||
### Bookmark / history breakage — LOW
|
||||
- Redirects in §4 step 3 cover the common URLs. Worst case: m has a bookmark to a deep `/mgmt/self?v=quarter`-style URL and hits the catch-all redirect to `/dashboard`. Acceptable.
|
||||
|
||||
### Other repos linking to `/mgmt/*` — VERIFIED ZERO
|
||||
- Grep across `~/dev/` for the strings `mgmt.msbls.de`, `/mgmt/self`, `/mgmt/login` found:
|
||||
- `m/msbls.de` itself (expected — the routes + their tests).
|
||||
- `projax/deploy/dokploy.yaml` — one stale comment about "federated with mgmt.msbls.de" cookies. Not a runtime dependency; safe to update at teardown time or leave as historical breadcrumb.
|
||||
- No other repo references mgmt. No cross-repo runtime coupling exists.
|
||||
|
||||
### External systems hitting mgmt API — NONE
|
||||
- mgmt has no `/api/*` routes. No webhook receivers, no cron entry points, nothing external can hit it. Pure browser-only surface.
|
||||
|
||||
### Cookie-scope semantics change — LOW
|
||||
- mgmt's cookies are `Domain=.msbls.de`. After teardown, the only cookies on `*.msbls.de` will be projax's (host-scoped) and whatever flexsiebels uses (different domain). The cross-subdomain `Domain=.msbls.de` cookie pair becomes effectively orphaned — browsers will keep them until expiry but no server reads them. Optional cleanup: set them to `Max-Age=0` on first projax response. Not worth the code.
|
||||
|
||||
### Loss of the Work-Cockpit Slice 4–5 design — INTENTIONAL
|
||||
- The mWorkRepo + mBrian topic surfacing was the design's strategic value-add. It never shipped. By tearing down mgmt we explicitly accept that this surface won't be built on msbls.de. If m later wants it, it lives more naturally on projax (with a Gitea-content reader) or on a future Otto-PWA consumer.
|
||||
|
||||
### Single-user assumption — UNCHANGED
|
||||
- mgmt assumed single-user owner-mode. projax has the same assumption. Teardown does not introduce new multi-user surface area.
|
||||
|
||||
---
|
||||
|
||||
## Summary numbers (for the report)
|
||||
|
||||
- **mgmt features audited: 4 routes + auth shell + 4 server libs** (caldav, supabase, mbrian, auth).
|
||||
- **Already covered by projax: 3** — login, auth guard, CalDAV VTODO reading.
|
||||
- **Gaps blocking teardown: 1 small (VEVENTs on dashboard) + 0 mandatory.** Two further "gaps" (mWorkRepo cards, mBrian topic cards) are park-forever recommendations — mgmt never shipped them either.
|
||||
|
||||
**Recommendation:** Ship Gap 1 (small) → wait one week → set up redirects → wait one week → remove mgmt. Two phases of projax work + two waiting weeks = ~14 days end to end. Could be compressed to ~3 days if m skips the waiting weeks; risk is bookmark breakage in his own browser history, which he can self-mitigate.
|
||||
Reference in New Issue
Block a user