fix(authz): complete the #955 prune, dropping general_roman_calendar (#539) - #540
Merged
Conversation
…539) Closes #539. Mirrors LiturgicalCalendarAPI#970 and CatholicOS/cdcf-infra#44. The rbac e2e seed has been failing on `development` and on every open PR since 2026-09-02 07:37: FGA write 400: Invalid tuple 'general_roman_calendar:temporale#admin@user:389059157879160837'. Reason: type 'general_roman_calendar' not found #530 is not at fault. It was written to issue #527's instruction — "the API stays additive for a whole migration window" — and deliberately kept the e2e seeds on the legacy type, because the API's fallback made them resolve. That window closed 18 hours after #530 merged: API#970 dropped every legacy code path at 17:11, and cdcf-infra#44 removed both retired types from the model at 17:22. `authz-seed` clones cdcf-infra at `main` AT RUN TIME, so CI picked it up immediately. The failure is a WRITE, which no fallback could ever have rescued: the API's widening applied to checks, while OpenFGA validates a tuple's type against the model before any API code runs. Three groups, treated differently. **Seeds and specs.** `users.ts` seeds grc-admin/grc-editor on `rite_calendar:roman/temporale`; spec 14's decrees object becomes `rite_calendar:roman/decrees`; `requestAccess.ts`'s union follows `AccessRequestRepository::VALID_OBJECT_TYPES`. **The authorization fallback, now dead weight.** `legacyRiteCalendarObject()` and `LEGACY_RITE_CALENDAR_TYPE` are gone, as is the second ask in `capabilities.js`, `admin-decrees.js`'s legacy `DECREES_OBJECTS` entry, and `AuthHelper::canViewRiteCalendarResource()`'s legacy branch. Nothing resolves against the type, so each was a round-trip to a guaranteed negative. PHPStan then caught `RITE_CALENDAR_FIXED_SUBRESOURCES` left unused by that branch's removal. **Grant dropdowns, which were actively harmful.** `admin-permissions.php`'s grant modal and `permission-requests.js`'s `roleObjectTypes` still OFFERED the retired types — selecting one handed the user the same FGA error the seed just hit. Both now offer `rite_calendar` and `rite_calendar_test`. That closes a gap #530 left open on purpose: `test_editor` was still on `general_roman_calendar_test` and had no rite-level option at all, because no id branch existed for its successor. It has one now, and `rite_calendar_test` ids are the BARE rite (`roman`, `ambrosian`) — its id IS the rite — not rite-qualified like the data types. The FILTER select keeps both legacy options. Filtering finds, it does not create, and stored access requests still carry the old names; an admin who cannot filter for them cannot find them. **Deliberately kept.** The `objectTypeNames` display maps in `admin-permissions.js` and `permission-requests.js`, and `includes/change-request-i18n.php`. `audit_log` rows are never rewritten, so historical records keep the old names permanently; a map without them renders those rows as a raw type id. The #530 regression test — "STILL labels a legacy general_roman_calendar row after #955" — stays green. `admin-tests.php`'s `general_roman_calendar` is untouched: it is a UI-local `#testScopeType` token that `deriveScope()` turns into `rite_calendar_test:<rite>`. The four tests that pinned the fallback now assert its ABSENCE rather than being deleted. A fallback creeping back would restore an authorization path the model no longer has, and would show controls whose writes the API refuses. Verified against the real post-prune model, not just statically: re-seeded the local OpenFGA store from cdcf-infra `main` (`general_roman_calendar` gone, `rite_calendar` present), repinned OPENFGA_MODEL_ID, recreated the API, and ran yarn playwright test --project=rbac 34 passed (2.0m) including `07 grc-admin — card visibility` and the whole `14 admin-decrees capability matrix` — the specs that were previously green only because of the fallback this removes. Also: yarn test:unit (518), yarn lint, yarn typecheck, composer parallel-lint, composer lint, composer analyse, composer test (52 tests, 162 assertions). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011r2AEViGig1EQXoP6ZNuUs
…test type The Administration section's test_editor gate asked `canViewAnyResourceOfType(..., 'general_roman_calendar_test')` alongside the three current types. That name was removed from the FGA model at the #955 prune milestone (CatholicOS/cdcf-infra#44), so `/auth/dashboard-scopes` cannot report a scope under it — the extra argument could only ever match nothing. Missed in the previous commit because it reads as a display list rather than an authorization ask; it is the latter. Verified the gate still behaves, rather than assuming a removal is inert: yarn playwright test --project=rbac \ e2e/rbac/15-dashboard-tests-card-matrix.spec.ts \ e2e/rbac/07-dashboard-card-scoping.spec.ts 9 passed (30.3s) covering both halves of the Tests-card matrix — a test_editor WITH a scope still sees the card, one WITHOUT still does not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011r2AEViGig1EQXoP6ZNuUs
Contributor
|
Warning Review limit reachedNext included review available in 20 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (14)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #539. Mirrors LiturgicalCalendarAPI#970
and CatholicOS/cdcf-infra#44.
This unblocks
developmentand every open PR. The rbac e2e seed has beenfailing since 2026-09-02 07:37:
#530 is not at fault
It was written to issue #527's explicit instruction — "the API stays additive for
a whole migration window" — and deliberately kept the e2e seeds on the legacy
type, because the API's fallback made them resolve. The window closed 18 hours
after it merged:
rite_calendar. Additive.authz-seedclones cdcf-infra atmainat run time, so CI picked it upimmediately. A stack seeded before the prune keeps passing, which is why this can
look machine-specific — it is not.
Why no fallback could have rescued it. The API's widening applied to checks.
This is a write, and OpenFGA validates a tuple's type against the model before
any API code runs.
Three groups, treated differently
1. Seeds and specs.
users.tsseeds grc-admin/grc-editor onrite_calendar:roman/temporale; spec 14's decrees object becomesrite_calendar:roman/decrees;requestAccess.ts's union followsAccessRequestRepository::VALID_OBJECT_TYPES.2. The authorization fallback — now dead weight.
legacyRiteCalendarObject()and
LEGACY_RITE_CALENDAR_TYPEare gone, as is the second ask incapabilities.js,admin-decrees.js's legacyDECREES_OBJECTSentry, andAuthHelper::canViewRiteCalendarResource()'s legacy branch. Nothing resolvesagainst the type, so each was a round-trip to a guaranteed negative. PHPStan then
caught
RITE_CALENDAR_FIXED_SUBRESOURCESleft unused by that removal — worthnoting as evidence the analysis gate earns its place.
3. Grant dropdowns — actively harmful. The grant modal and
permission-requests.js'sroleObjectTypesstill offered the retired types;selecting one handed the user the same FGA error the seed hit. Both now offer
rite_calendarandrite_calendar_test.That closes a gap #530 left open on purpose:
test_editorwas still ongeneral_roman_calendar_testand, once that type went, had no rite-level optionat all. It has one now — and
rite_calendar_testids are the bare rite(
roman,ambrosian), because there the id is the rite, unlike therite-qualified data types.
The filter select keeps both legacy options. Filtering finds, it does not
create, and stored access requests still carry the old names; an admin who cannot
filter for them cannot find them.
Deliberately kept
The
objectTypeNamesdisplay maps andincludes/change-request-i18n.php.audit_logrows are never rewritten, so historical records keep the old namespermanently — a map without them renders those rows as a raw type id. #530's
regression test, "STILL labels a legacy
general_roman_calendarrow after#955", stays green.
admin-tests.php'sgeneral_roman_calendaris untouched: it is a UI-local#testScopeTypetoken thatderiveScope()turns intorite_calendar_test:<rite>.The tests assert the absence
The four cases that pinned the fallback are rewritten, not deleted. A fallback
creeping back would restore an authorization path the model no longer has, and
would show controls whose writes the API refuses.
Verification — against the real model, not just statically
The whole point is a model change, so I reproduced it rather than reasoning about
it. Re-seeded the local OpenFGA store from cdcf-infra
main(confirmedgeneral_roman_calendargone,rite_calendarpresent), repinnedOPENFGA_MODEL_ID, recreated the API, then:including
07 grc-admin — card visibilityand the whole14 admin-decrees capability matrix— precisely the specs that were previously green because ofthe fallback this removes.
A second commit fixes one straggler the first missed:
admin-dashboard.php'stest_editor gate still asked about
general_roman_calendar_test. It readslike a display list but is an authorization ask. Re-verified both halves of the
Tests-card matrix afterwards (9 passed).
Also green:
yarn test:unit(518),yarn lint,yarn typecheck,composer parallel-lint,composer lint,composer analyse,composer test(52 tests, 162 assertions).
🤖 Generated with Claude Code