From 75dbb1536acf77b239f150dc388bfc97299341cb Mon Sep 17 00:00:00 2001 From: "John R. D'Orazio" Date: Sun, 16 Aug 2026 14:46:41 +0200 Subject: [PATCH] chore: delete the dead scripts/openfga-model.additive.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OpenFGA authorization model moved to cdcf-infra (auth/models/LiturgicalCalendar.json) on 2026-08-04. Since then this file has been applied by nothing: no composer script, no CI workflow, no test, and not even scripts/setup-openfga.sh, which reads store and model IDs but explicitly "no longer creates or updates the model". Only docs still named it. docs/ops/rbac-create-governance-runbook.md already asserted, at the top, that it "does not exist in this repo any more" — deleting it makes that sentence true. It was not merely stale, it was harmful. #785 added the rite_calendar_test type here instead of opening the required cdcf-infra PR, so the type shipped in ResourceAdminService's VIEWER_OBJECT_TYPES / TEST_OBJECT_TYPES while being absent from every deployed model. listObjects then returns 400 type_not_found → RuntimeException → the loop-wide catch in ResourceAdminService empties every object type's scope list, collapsing dashboard gating globally. The type is being added properly in CatholicOS/cdcf-infra#31. It also drifted from the deployed model in ways that would silently reintroduce retired surface if anyone did apply it: it still carries the test_definition type and a deleter relation on every type, both of which authz/openfga-expectations.json now explicitly forbids. Alongside the deletion: - docs/ops/test-scope-migration-runbook.md — Step 1 no longer tells an operator to edit the file, and records why that instruction was dangerous. - .github/deploy/rsync-exclude.txt — the comment justifying why scripts/ ships no longer claims an openfga-model*.json is among the things shipped. Comment only; no exclude rule referenced the file. Historical plans and specs under docs/superpowers/ still name it. Those are dated records of decisions as they were made, not instructions — the same reason rbac-create-governance-runbook.md keeps its original steps verbatim under a note saying the world has moved on. Co-Authored-By: Claude Opus 5 (1M context) --- .github/deploy/rsync-exclude.txt | 12 +- docs/ops/test-scope-migration-runbook.md | 13 +- scripts/openfga-model.additive.json | 310 ----------------------- 3 files changed, 17 insertions(+), 318 deletions(-) delete mode 100644 scripts/openfga-model.additive.json diff --git a/.github/deploy/rsync-exclude.txt b/.github/deploy/rsync-exclude.txt index 226c015a3..043bb0404 100644 --- a/.github/deploy/rsync-exclude.txt +++ b/.github/deploy/rsync-exclude.txt @@ -79,11 +79,13 @@ infrastructure/ # --- Dev-only entries inside scripts/ --- # scripts/ itself MUST ship: the operational scripts (mint-official-key, -# migrate-*-tuples, reconcile-resource-tuples, seed-wider-region-membership, -# and the openfga-model*.json they apply) bootstrap from the deployed app -# root's vendor/ + .env and are run ON the server per the RBAC runbook, -# since production OpenFGA/Postgres are only reachable there. Exclude only -# the local coverage tooling and the Docker-bootstrap SQL. +# migrate-*-tuples, reconcile-resource-tuples, seed-wider-region-membership) +# bootstrap from the deployed app root's vendor/ + .env and are run ON the +# server per the RBAC runbook, since production OpenFGA/Postgres are only +# reachable there. No openfga-model*.json ships any more — the authorization +# model lives in cdcf-infra (auth/models/LiturgicalCalendar.json) and is +# uploaded from /opt/cdcf-auth/auth, not from this vhost. Exclude only the +# local coverage tooling and the Docker-bootstrap SQL. scripts/coverage-summary.php scripts/coverage-with-server.sh scripts/merge-pcov-coverage.php diff --git a/docs/ops/test-scope-migration-runbook.md b/docs/ops/test-scope-migration-runbook.md index 45c1171bf..5f2885dea 100644 --- a/docs/ops/test-scope-migration-runbook.md +++ b/docs/ops/test-scope-migration-runbook.md @@ -289,12 +289,19 @@ place so that rolling the API back to pre-#767 code keeps authorizing. ### Step 1 — apply the model -`rite_calendar_test` is added to `scripts/openfga-model.additive.json` alongside -`general_roman_calendar_test`, with an identical relation set. As above, the -authoritative model lives in `cdcf-infra`: land the equivalent change to +`rite_calendar_test` is added alongside `general_roman_calendar_test`, with an +identical relation set (`admin`, `editor`, `viewer`). As above, the model lives +in `cdcf-infra` and **only** there: land the change to `cdcf-infra/auth/models/LiturgicalCalendar.json`, then upload the new model version on the VPS. +> An earlier revision of this step also named `scripts/openfga-model.additive.json` +> in this repo. That file was already dead when it was written — the model moved to +> `cdcf-infra` on 2026-08-04 — and editing it instead of opening the `cdcf-infra` PR +> is exactly how `rite_calendar_test` shipped in the API's allow-lists while missing +> from every deployed model, collapsing dashboard gating for all users. The file has +> since been deleted; `cdcf-infra` is the only place a model change counts. + ### Step 2 — copy the tuples ```bash diff --git a/scripts/openfga-model.additive.json b/scripts/openfga-model.additive.json deleted file mode 100644 index 17fe16ba2..000000000 --- a/scripts/openfga-model.additive.json +++ /dev/null @@ -1,310 +0,0 @@ -{ - "schema_version": "1.1", - "type_definitions": [ - { - "type": "user" - }, - { - "type": "wider_region", - "relations": { - "member_nation": { "this": {} }, - "admin": { - "union": { - "child": [ - { "this": {} }, - { - "tupleToUserset": { - "tupleset": { "relation": "member_nation" }, - "computedUserset": { "relation": "admin" } - } - } - ] - } - }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "member_nation": { "directly_related_user_types": [{ "type": "national_calendar" }] }, - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "national_calendar", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "diocesan_calendar", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "general_roman_calendar", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "test_definition", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "national_calendar_test", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "diocesan_calendar_test", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "general_roman_calendar_test", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - }, - { - "type": "rite_calendar_test", - "relations": { - "admin": { "this": {} }, - "editor": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "viewer": { - "union": { - "child": [ - { "this": {} }, - { "computedUserset": { "relation": "editor" } }, - { "computedUserset": { "relation": "admin" } } - ] - } - }, - "deleter": { "this": {} } - }, - "metadata": { - "relations": { - "admin": { "directly_related_user_types": [{ "type": "user" }] }, - "editor": { "directly_related_user_types": [{ "type": "user" }] }, - "viewer": { "directly_related_user_types": [{ "type": "user" }] }, - "deleter": { "directly_related_user_types": [{ "type": "user" }] } - } - } - } - ] -}