feat(education): enforce catalog graph scope

This commit is contained in:
2026-07-30 19:53:05 +08:00
parent 55a991d3e4
commit 4db4a7d371
7 changed files with 517 additions and 18 deletions

View File

@@ -1,9 +1,9 @@
# EDU-010 — Tenant content publication and graph integrity
- **Status:** blocked
- **Status:** in progress — catalog graph-integrity slice delivered; authoring/publication lifecycle remains
- **Type:** implementation program
- **Phase:** 3
- **Blockers:** EDU-004, EDU-009, provider-authority decision, PUBLIC graph-semantics decision
- **Blockers:** EDU-004 ✓ (done), EDU-009 ✓ (done), provider-authority decision ✓ (resolved 2026-07-30, see decisions.md), PUBLIC graph-semantics decision ✓ (resolved 2026-07-30, see decisions.md)
## Tenant-admin outcome
@@ -21,11 +21,36 @@ Authorized tenant administrators can author, classify, publish, archive, and ret
## Acceptance criteria
- [ ] Admin permission and data-scope matrix is explicit.
- [ ] Cross-tenant graph relationships cannot be persisted.
- [ ] PUBLIC and tenant-owned reference rules are enforced and tested.
- [x] Cross-tenant graph relationships cannot be persisted in the current V4020 catalog graph.
- [x] PUBLIC and tenant-owned reference rules are enforced across the current 19 reference edges, with exact trigger-mapping and focused behavior tests.
- [ ] Unpublished/archived content is never student-visible.
- [ ] Publication is transactional and auditable.
- [ ] Database changes use `flyway-postgresql` and forward migrations.
- [x] Database graph-integrity changes use `flyway-postgresql` and forward migration V4070.
## Delivery progress — graph-integrity slice (2026-07-30)
Delivered:
- `V4070__enforce_catalog_reference_scope.sql` guards all 19 current foreign-key edges and makes ownership scope immutable on all 11 catalog tables:
- PUBLIC children may reference only PUBLIC parents;
- tenant-owned children may reference PUBLIC or same-tenant parents;
- cross-tenant and PUBLIC-to-tenant references fail closed;
- `tenant_id` and `scope` cannot change after insert, so parent mutations and concurrent ownership moves cannot invalidate existing children.
- V4070 installs write guards before historical pre-validation, eliminating the migration-time validation/write window. The reference trigger function uses a fixed `search_path`, locks referenced rows during validation, and exposes no PUBLIC execute grant.
- Real PostgreSQL/Flyway integration tests cover fresh and 4009-baselined migration histories, allowed and rejected references, parent ownership immutability, exact configuration of all 19 reference guards and 11 scope guards, function ACLs, and historical invalid-data failure.
No non-Education module changed. Application rollback can disable native authoring when it is introduced; database recovery remains a higher forward migration and must preserve existing content.
## Remaining publication slice
Do not add a local-only admin write path while `SCALAR_READ` remains the default authoritative provider: a successful PostgreSQL write would not be visible to students. The next bounded slice is a `JAVA_READ`-only tenant question `draft → publish → archive → student read` path that fails closed in unsupported provider modes.
Before its Flyway/application implementation, resolve and document:
1. the exact `DRAFT/PUBLISHED/ARCHIVED/RETIRED` state machine and mapping of V4020 `HIDDEN/INACTIVE` rows;
2. immutable question-version and transactional publication-audit ownership;
3. whether ancestor entry/node/collection/archive state makes a question unavailable to fresh student reads;
4. the explicit tenant-admin versus platform-curator permission/data-scope matrix.
## Risk and rollback

View File

@@ -36,7 +36,7 @@ EDU-000 Phase 0 artifacts done
└── EDU-005 PostgreSQL/Flyway takeover decision done
EDU-009 + provider/content decisions
└── EDU-010 Tenant content publication blocked
└── EDU-010 Tenant content publication in progress (graph integrity delivered; lifecycle remains)
└── EDU-011 Import/export/assets/scanning blocked
EDU-004
@@ -52,7 +52,8 @@ All owner/contract decisions
## Recommended execution order
1. Select the next unblocked content-management decision/ticket after EDU-009.
1. **EDU-010** — Continue with the provider-consistent question publication lifecycle; V4070 graph integrity is delivered.
2. Continue through EDU-011/EDU-012 as their blockers clear.
## Phase 0 completion caveat