From 69c1e4926c3862485b332f19681788e6634189cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Sun, 6 Sep 2026 23:49:25 +0200 Subject: [PATCH] Record the calendar migration as complete and deployed Every step is live as of 2026-09-06. The status header said "awaiting deploy", which is exactly the kind of staleness that nearly caused a bad deploy earlier in this project - the step 4 checklist was written because "done" had been read as "in production". Also records the one surprise from the deploy: a cached pre-cutover bundle looked signed in and showed every event's status as "Error", because the legacy checkSessionValid route still answered between steps 4 and 5 while the events call went out without a cookie and came back without a status field. That route is gone now, so a stale bundle fails honestly instead. Co-Authored-By: Claude Opus 5 --- docs/calendar-auth-migration.md | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/calendar-auth-migration.md b/docs/calendar-auth-migration.md index e1810aa..a6da2c3 100644 --- a/docs/calendar-auth-migration.md +++ b/docs/calendar-auth-migration.md @@ -1,13 +1,22 @@ # Migrating the Calendar domain onto the admin identity module -Status: **complete.** Steps 1, 3 and 4 were deployed and verified in production on -2026-09-06; step 2 was dropped by decision and part of step 5 brought forward. Step 5 is -implemented and awaiting deploy - see its own checklist below, whose ordering is the -**opposite** of step 4's. +Status: **complete and deployed, 2026-09-06.** Every step is live. Step 2 was dropped by +decision and part of step 5 brought forward; the rest went out as written. -Verified live after step 4: the public calendar still answers anonymously, all 23 public -events kept a resolvable author, restricted calendars still refuse without a credential, -legacy query credentials answer 401, and `calendar.nachklang.art` is trusted for sign-out. +The calendar now shares one identity with the tickets, feedback and admin apps: writes sit +behind `requireAppAccess('calendar')` against the shared session cookie, reads resolve that +cookie optionally, and the calendar's own `users`/`sessions` tables are renamed aside and +referenced by nothing. `DEFERRED_SECURITY.md` items 1, 3 and 4 closed with it. + +Verified in production after the final deploy: the public calendar answers anonymously on all +three endpoints (23 events, 23 VEVENTs in the iCal feed, the next-event teaser intact), +restricted calendars still refuse without a credential, unauthenticated writes answer 401, +all six `/calendar/users/*` routes answer 404, CORS grants only `Content-Type`, sign-out from +`calendar.nachklang.art` succeeds, and **every event kept its author** - rendered from the +`created_by_name` snapshot, since the table it was copied from no longer exists under that +name. That last one is the whole reason part of step 5 was brought forward. + +Remaining, at your leisure: `DROP TABLE sessions_legacy_archive, users_legacy_archive;` Written 2026-09-05 alongside the admin module (step 2 of `docs/plan-admin-auth.md` in the nachklang-admin repo), which deliberately left the calendar alone. Steps 1-4 of that plan @@ -157,8 +166,8 @@ Each step is meant to leave production working on its own. **One-way door:** any iCal subscription whose URL carries `?sessionId=&sessionKey=` rather than `?password=` stops working permanently. The shared-password URLs are unaffected. -5. **Drop the legacy path.** **Implemented 2026-09-06** on `feature/calendar-drop-legacy-path`; - not yet deployed. Gated on step 4 being live, which it now is. +5. **Drop the legacy path.** **Deployed 2026-09-06.** Gated on step 4 being live, which it + was. What went: @@ -178,7 +187,7 @@ Each step is meant to leave production working on its own. `DEFERRED_SECURITY.md` items **3** and **4** (activation and reset tokens never expiring) close with it - not by adding expiries but by deleting the code that issued them. - ### Deploy checklist — note the order is REVERSED from step 4 + ### Deploy checklist — kept for the record; the order was REVERSED from step 4 Step 4's migration only added columns, so it went first. `004` *removes* columns and a table that the currently running build still selects and joins, so running it first fails @@ -209,6 +218,15 @@ Each step is meant to leave production working on its own. **One-way door:** `Event.createdById` and `lastModifiedById` leave the API response. Check anything reading `/calendar/events/*/json` that is not the calendar frontend. + **Observed during the deploy, worth keeping.** A browser holding a *cached pre-cutover* + Angular bundle looked signed in and showed every event's status as "Error". The old bundle + called `/calendar/users/checkSessionValid`, which still existed between step 4 and step 5, + so it rendered as authenticated - then fetched events with no cookie, got the anonymous + listing, which omits `status`, and the UI's status switch fell through to its error label. + Signing out and back in fixed it. After this step that route 404s, so a stale bundle now + fails honestly instead of faking a session. This is the same "does not look broken" window + the step 4 checklist warns about, seen from the other side. + ## What the code actually looks like (surveyed 2026-09-06) Four things found while doing step 1 that change how the later steps should be built: