diff --git a/auth/handoffs/liturgicalcalendar.md b/auth/handoffs/liturgicalcalendar.md index 76c9d0f..17ed183 100644 --- a/auth/handoffs/liturgicalcalendar.md +++ b/auth/handoffs/liturgicalcalendar.md @@ -76,6 +76,8 @@ Everything in this Zitadel section was re-verified against production on 2026-08 `rite_calendar_test` (relations `admin`/`editor`/`viewer`, identical to `general_roman_calendar_test`, which it generalises — its object id is the bare rite, e.g. `rite_calendar_test:roman`) is **deployed** as of model `01M05SBDS2F7EQFGRW7D997S6K`. It is purely additive: `general_roman_calendar_test` is untouched, so pre-migration tuples on it keep authorizing until `scripts/migrate-rite-test-tuples.php --apply --prune` has run in every environment. + **Not yet deployed:** `rite_calendar` was added to the model *file* (cdcf-infra #41), mirroring `general_roman_calendar` exactly — relations `admin`/`editor`/`viewer`, no `deleter`. It is the production-tier counterpart of the test type above: `general_roman_calendar`'s single fixed id could only ever name the Roman rite-level calendar, so the new type's object ids carry their rite (`rite_calendar:roman/decrees`, `rite_calendar:ambrosian/EDITIO_TYPICA_2024`). The type list above deliberately still describes model `01M05SBDS2F7EQFGRW7D997S6K`, which does **not** contain it. It becomes deployed only when an operator runs `./setup-openfga.sh --target production --create-litcal-store` in `/opt/cdcf-auth/auth` and the resulting model ID lands in `LiturgicalCalendar.lock.json` via a follow-up PR; update both this list and the model ID above at that point. Purely additive: `general_roman_calendar` is untouched, so live editor grants on it keep authorizing until `scripts/migrate-rite-calendar-tuples.php --apply --prune` (LiturgicalCalendarAPI#965) has run in every environment. Dropping `general_roman_calendar` and `general_roman_calendar_test` is a separate, later model version. + Consumers pinning `OPENFGA_MODEL_ID` do **not** pick this up by redeploying — a pin names a specific model ID, so they keep resolving against whatever they pinned until the value below is updated. Local dev and frontend-e2e stores refresh themselves; there is no manual model upload to perform. `LiturgicalCalendarFrontend`'s `authz-seed` service clones this repo at `CDCF_INFRA_REF` (default `main`), writes its own `.env.local`, and runs `./setup-openfga.sh --target local --create-litcal-store` — so bringing the stack up again once the change is on `main` is what picks it up. Those stores get a **new model ID of their own**; the lock guard does not fire against them, because a lock scoped to the production store is `foreign` to a local one and is bypassed. Re-pin `OPENFGA_STORE_ID`/`OPENFGA_MODEL_ID` in that stack from *its* IDs, never from the production values above — model IDs are meaningless across stores. diff --git a/auth/models/LiturgicalCalendar.json b/auth/models/LiturgicalCalendar.json index 02c056e..6db1ece 100644 --- a/auth/models/LiturgicalCalendar.json +++ b/auth/models/LiturgicalCalendar.json @@ -138,6 +138,36 @@ } } }, + { + "type": "rite_calendar", + "relations": { + "admin": { "this": {} }, + "editor": { + "union": { + "child": [ + { "this": {} }, + { "computedUserset": { "relation": "admin" } } + ] + } + }, + "viewer": { + "union": { + "child": [ + { "this": {} }, + { "computedUserset": { "relation": "editor" } }, + { "computedUserset": { "relation": "admin" } } + ] + } + } + }, + "metadata": { + "relations": { + "admin": { "directly_related_user_types": [{ "type": "user" }] }, + "editor": { "directly_related_user_types": [{ "type": "user" }] }, + "viewer": { "directly_related_user_types": [{ "type": "user" }] } + } + } + }, { "type": "national_calendar_test", "relations": {