Read calendar event creators from the admin module, and archive the old ones #14
@@ -6,7 +6,8 @@ left to write.
|
||||
|
||||
> Read the deploy checklist under step 4 before applying anything. "Done" below means the
|
||||
> code exists on a branch, **not** that production has it - and in particular production has
|
||||
> none of the three migrations.
|
||||
> none of the three migrations. Step 5 is scoped but deliberately unstarted: it must not be
|
||||
> built on top of a step 4 that has not been deployed and watched.
|
||||
|
||||
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
|
||||
@@ -156,14 +157,62 @@ 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.** Remove `users.service.ts`'s session handling, the `sessions`
|
||||
table, `created_by_id`, and the legacy half of the step 3 read (the `users` join and its
|
||||
`legacy_*` aliases - the snapshot fallback stays, it is what makes dropping the table
|
||||
safe). The names were archived ahead of time by
|
||||
`sql/calendar/002_snapshot_legacy_creator_names.sql`, so nothing is lost here. Legacy `/calendar/users/*` stays
|
||||
only if something still calls it - otherwise delete it too. `X-Session-Id` /
|
||||
`X-Session-Key` can then come out of the CORS `allowedHeaders` list in
|
||||
`src/app.factory.ts`.
|
||||
5. **Drop the legacy path.** Not started - and deliberately not started until step 4 has been
|
||||
deployed and watched, because it removes the fallback step 4 still leans on. Scoped and
|
||||
decided 2026-09-06; what follows is the agreed shape, not a suggestion.
|
||||
|
||||
**Prerequisite: step 4 live in production and behaving.** Until then the legacy join is
|
||||
what renders the author of every pre-cutover event, and the legacy routes are what an old
|
||||
cached bundle talks to. Doing this first turns a recoverable deploy into an unrecoverable
|
||||
one.
|
||||
|
||||
Code, in one branch:
|
||||
|
||||
- **Delete `src/models/calendar/users/` entirely** - `users.router.ts`, `users.service.ts`,
|
||||
`session.interface.ts`, `user.interface.ts` - and the `calendarRouter.use('/users', ...)`
|
||||
line in `Calendar.router.ts`. *(Decided: delete outright rather than unmount.)* This
|
||||
removes the last unauthenticated account-creation and mail-sending endpoint in the API.
|
||||
A survey on 2026-09-06 confirmed nothing outside that directory imports it, and nothing
|
||||
outside it touches the `users`/`sessions` tables except the two joins below.
|
||||
- **Drop the legacy half of the read** in `events.service.ts`: the two
|
||||
`LEFT OUTER JOIN users` clauses, the `legacy_*` aliases, and `created_by_id` /
|
||||
`version_created_by_id` from the SELECT and the row mapper. The snapshot fallback stays -
|
||||
it is what makes this safe. Remove `createdById` / `lastModifiedById` from
|
||||
`event.interface.ts` and their (already deprecated) swagger properties.
|
||||
- **Remove `X-Session-Id` / `X-Session-Key`** from the CORS `allowedHeaders` in
|
||||
`src/app.factory.ts`. Nothing has sent them since the tickets and feedback frontends were
|
||||
redeployed.
|
||||
- **Drop the obsolete test mocks**: `test/feedback/feedback.auth.test.ts`,
|
||||
`test/tickets/tickets.auth.test.ts` and `test/admin/auth-binding.ts` each mock
|
||||
`calendar/users/users.service.js` and assert `checkSession` is never called. That
|
||||
tripwire is meaningless once the module does not exist; remove the mock and the
|
||||
assertion, keep the rest.
|
||||
|
||||
Database, as `sql/calendar/004_*.sql`:
|
||||
|
||||
- Drop the foreign keys `events_users_user_id_fk` and `event_versions_users_user_id_fk`,
|
||||
then the `created_by_id` and `version_created_by_id` columns.
|
||||
- **`RENAME TABLE users TO users_legacy_archive`**, same for `sessions`. *(Decided: rename
|
||||
rather than drop.)* The reasoning: the display names are already snapshotted so nothing
|
||||
visible depends on these rows, but they still hold the old e-mail addresses and password
|
||||
hashes, and a rename makes the tables unreachable without destroying anything. Dropping
|
||||
them later is one statement, at a moment when nobody is mid-deploy.
|
||||
- Mirror all of it in `docker/init/01-calendar-schema-dev.sql` (the archive tables need no
|
||||
mirror - a fresh dev database has nothing to archive).
|
||||
|
||||
Documentation: `DEFERRED_SECURITY.md` items **3** (activation token has no expiry) and
|
||||
**4** (password reset token has no expiry) close outright - both describe code that ceases
|
||||
to exist. Item 2 (no event ownership check) stays open.
|
||||
|
||||
Two consequences to accept explicitly rather than discover:
|
||||
|
||||
- Any activation or password-reset e-mail already sent points at
|
||||
`api.nachklang.art/calendar/users/activate` and becomes a 404. Those links were only ever
|
||||
valid for legacy accounts, which no longer open anything.
|
||||
- `Event.createdById` disappears from the API response. The Angular frontend never read it
|
||||
(its `Event` model has only `createdBy`, the name), so this is not a breaking change for
|
||||
the only known consumer - but it is a wire-format removal, so check anything else that
|
||||
reads `/calendar/events/*/json` first.
|
||||
|
||||
## What the code actually looks like (surveyed 2026-09-06)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user