feat(education): add tenant content node lifecycle
This commit is contained in:
@@ -117,6 +117,9 @@ The durable artifact classification, adoption matrix, version allocation, backfi
|
||||
8. Question Placement means assigning a DRAFT question's `node_id`; it does not mean Category CRUD. The `education_category` table has no Question relationship in the current target model.
|
||||
9. Placement targets must be visible, active, selectable PUBLIC or same-tenant Content Nodes. Placement has an independent optimistic version, becomes immutable after publication, and publication CAS includes that version.
|
||||
10. Node-route student visibility is evaluated atomically in the Question/Content Node query. Node availability gates that route but does not change direct question visibility or historical snapshots.
|
||||
11. Tenant Content Node authoring is JAVA_READ-only, current-tenant TENANT_OWNED-only, and uses `DRAFT → ACTIVE → ARCHIVED` with one CAS `authoring_version` shared by revisions and transitions.
|
||||
12. Content Node activation requires a structurally available entry and parent. Student discovery and Question Placement treat only ACTIVE nodes as available. Content Node lifecycle audit is transactional and append-only.
|
||||
13. Content Node permissions are `education:content-node:author`, `education:content-node:publish`, and `education:content-node:archive`; V4100 seeds no permission, menu, role, or role grant.
|
||||
|
||||
**Permission and data-scope matrix:**
|
||||
|
||||
@@ -126,7 +129,10 @@ The durable artifact classification, adoption matrix, version allocation, backfi
|
||||
| Classifier | `education:question:classify` | Place or re-place current-tenant `TENANT_OWNED` drafts on allowed Content Nodes | Tenant-wide shared catalog asset; PUBLIC/same-tenant targets only |
|
||||
| Publisher | `education:question:publish` | Current-tenant `TENANT_OWNED` drafts | Tenant-wide shared catalog asset; department/self DataPermission does not expand access |
|
||||
| Archiver | `education:question:archive` | Current-tenant `TENANT_OWNED` published questions | Tenant-wide shared catalog asset; department/self DataPermission does not expand access |
|
||||
| Platform curator | none in this slice | No PUBLIC or tenant-owned writes through these endpoints | Fail closed |
|
||||
| Content Node author | `education:content-node:author` | Create/revise current-tenant TENANT_OWNED drafts | Current tenant; structural entry/parent validation |
|
||||
| Content Node publisher | `education:content-node:publish` | Activate current-tenant TENANT_OWNED drafts | Tenant-wide shared catalog asset; authoring-version CAS |
|
||||
| Content Node archiver | `education:content-node:archive` | Archive current-tenant TENANT_OWNED active nodes | Tenant-wide shared catalog asset; authoring-version CAS |
|
||||
| Platform curator | none in this slice | No PUBLIC writes through these endpoints | Fail closed |
|
||||
|
||||
V4080/V4090 conditionally seed the five Education permissions (`education:capability` plus author/classify/publish/archive) when the adopted platform schema contains `system_menu`. They fail when a fixed ID is already occupied by a different permission and deliberately do not assign the permissions to any role.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# EDU-010 — Tenant content publication and graph integrity
|
||||
|
||||
- **Status:** in progress — catalog graph-integrity, the verified JAVA_READ tenant-question lifecycle, and Question Placement slices are delivered; category, collection, and blueprint authoring remain
|
||||
- **Status:** in progress — catalog graph-integrity, JAVA_READ tenant-question lifecycle, Question Placement, and tenant Content Node lifecycle slices are delivered; category, collection, and blueprint authoring remain
|
||||
- **Type:** implementation program
|
||||
- **Phase:** 3
|
||||
- **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)
|
||||
@@ -85,7 +85,18 @@ Delivered:
|
||||
- Student node-route reads join Question and Content Node in one PostgreSQL statement. A hidden, inactive, non-selectable, cross-scope, or deleted node cannot expose questions through that route; direct question visibility still follows the question Publication State.
|
||||
- V4090 conditionally seeds `education:question:classify` at fixed ID 6805, fails closed on conflicting rows, and grants no role.
|
||||
|
||||
Category CRUD, Content Node authoring, Collection/Blueprint authoring, PUBLIC curator workflows, and a distinct Retire state remain outside this slice. In the target domain, `education_category` is not connected to Question; the delivered classification seam is explicitly Question Placement through `question.node_id`.
|
||||
Category CRUD, Collection/Blueprint authoring, PUBLIC curator workflows, and a distinct Retire state remain outside the delivered slices. In the target domain, `education_category` is not connected to Question; classification remains Question Placement through `question.node_id`.
|
||||
|
||||
## Delivery progress — JAVA_READ tenant Content Node lifecycle slice (2026-07-30)
|
||||
|
||||
Delivered:
|
||||
|
||||
- Current-tenant `TENANT_OWNED` Content Nodes expose draft create/revise, activate, and archive commands only in `JAVA_READ`. PUBLIC writes and Category CRUD fail closed/outside the surface.
|
||||
- The command surface is strictly `DRAFT → ACTIVE → ARCHIVED`. One `authoring_version` CAS advances on every draft revision and lifecycle transition; ACTIVE content and ARCHIVED rows are immutable.
|
||||
- Entry and parent validation accepts only active, visible PUBLIC or same-tenant graph parents, requires the parent to belong to the same entry, and rejects self-parenting.
|
||||
- `education:content-node:author`, `education:content-node:publish`, and `education:content-node:archive` are independent controller permissions. V4100 deliberately seeds neither permissions nor roles.
|
||||
- Activation/archive append an actor/version/status audit in the same transaction. V4100 makes that audit append-only and uses a deferred constraint trigger to reject lifecycle changes without the matching audit.
|
||||
- Student catalog discovery and Question Placement continue to require `is_active=true`; V4100 constrains that flag to `publication_status='ACTIVE'`, so drafts/archives cannot appear or accept placement.
|
||||
|
||||
## Verification evidence (2026-07-30)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user