docs(education): define manual collection contract
This commit is contained in:
@@ -120,6 +120,11 @@ The durable artifact classification, adoption matrix, version allocation, backfi
|
||||
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.
|
||||
14. The next bounded EDU-010 slice is a JAVA_READ-only current-tenant `TENANT_OWNED` Manual Question Collection attached to one existing ACTIVE, visible Content Node. Content Entry creation is excluded, so the target node and its structurally available Content Entry must be pre-provisioned.
|
||||
15. A Manual Question Collection uses `DRAFT → ACTIVE → ARCHIVED` with one optimistic authoring version. Only DRAFT metadata and membership may change; ACTIVE collection content and membership are immutable, and ARCHIVED is terminal.
|
||||
16. Membership is an ordered replace-all command available only in DRAFT. Every member must be a current-tenant `TENANT_OWNED` PUBLISHED Question, and duplicate Question IDs are rejected rather than collapsed or upserted.
|
||||
17. Activation exposes the collection route only when the collection and its existing Content Node are available. Archiving closes only collection-route discovery; it does not alter direct Question visibility or historical Practice Question Snapshots.
|
||||
18. `access_rules` is descriptive reserved metadata in this slice, not entitlement enforcement. PUBLIC Question curation, dynamic filters, paid/private access, Category, Practice Blueprint, and Content Entry creation are excluded.
|
||||
|
||||
**Permission and data-scope matrix:**
|
||||
|
||||
@@ -140,17 +145,17 @@ V4080/V4090 conditionally seed the five Education permissions (`education:capabi
|
||||
|
||||
**ADR:** `docs/adr/0001-native-question-authoring-authority.md`.
|
||||
|
||||
The accepted Manual Question Collection slice does not warrant a separate ADR: it applies the already-recorded native-authority, tenant-ownership, lifecycle, optimistic-concurrency, route-gating, and snapshot-preservation decisions to one narrower aggregate, without adding a hard-to-reverse architectural trade-off.
|
||||
|
||||
## Unresolved decisions
|
||||
|
||||
1. The valid option schema for each question type, including whether absent options are legal; whether malformed published content is omitted or produces a controlled source failure.
|
||||
2. Whether untracked /Users/tiku1/code/ruoyi-vue-pro/sql/postgresql/education files are intended for promotion into Flyway or are design/manual artifacts.
|
||||
3. Whether V4010/V4020 or any manual core-loop DDL has ever run successfully in PostgreSQL; no runtime migration evidence exists.
|
||||
4. Which Auth/Profile/extended Learning semantics are replaced by Member/System/Infra versus Education-owned, including vocabulary, leaderboard, stats, trend, feedback, exam dates, notifications, points, and badges.
|
||||
5. Whether tenant appearance, domains, payment accounts, auth providers, secrets, activation codes, coupons, integrations, marketing, public-bank grants, and sync are in scope or explicitly retired.
|
||||
6. Whether legacy assets are migrated, re-uploaded, re-scanned, or retired, and who owns ClamAV/scanner integration.
|
||||
7. Which legacy RLS, triggers, functions, grants, seeds, queue leases, retry behavior, and operational semantics are contractual and need Java/constraint/event/job reproduction.
|
||||
8. Whether the ten required Phase 0 artifacts must be committed files or may remain in reviewed scratch form during discovery.
|
||||
9. Whether a future System-owned immutable Tenant Code or signed bootstrap locator is required beyond the accepted public-handle/existence-disclosure contract.
|
||||
1. Which Auth/Profile/extended Learning semantics are replaced by Member/System/Infra versus Education-owned, including vocabulary, leaderboard, stats, trend, feedback, exam dates, notifications, points, and badges.
|
||||
2. Whether tenant appearance, domains, payment accounts, auth providers, secrets, activation codes, coupons, integrations, marketing, public-bank grants, and sync are in scope or explicitly retired.
|
||||
3. Whether legacy assets are migrated, re-uploaded, re-scanned, or retired, and who owns ClamAV/scanner integration.
|
||||
4. Which legacy RLS, triggers, functions, grants, seeds, queue leases, retry behavior, and operational semantics are contractual and need Java/constraint/event/job reproduction.
|
||||
5. Whether the ten required Phase 0 artifacts must be committed files or may remain in reviewed scratch form during discovery.
|
||||
6. Whether a future System-owned immutable Tenant Code or signed bootstrap locator is required beyond the accepted public-handle/existence-disclosure contract.
|
||||
7. Which shared environments already carry V4010/V4020 or manual equivalents and what explicit baseline/adoption record each requires. The root `sql/postgresql/education/` classification and the module-owned Flyway authority are resolved; disposable PostgreSQL execution evidence exists, but no shared-environment migration is claimed.
|
||||
|
||||
## Decision rule
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# EDU-010 — Tenant content publication and graph integrity
|
||||
|
||||
- **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
|
||||
- **Status:** in progress — catalog graph-integrity, JAVA_READ tenant-question lifecycle, Question Placement, and tenant Content Node lifecycle slices are delivered; the Manual Question Collection slice is contract-ready but not implemented; category 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)
|
||||
@@ -28,6 +28,11 @@ Authorized tenant administrators can author, classify, publish, archive, and ret
|
||||
- [x] Publication is transactional and auditable.
|
||||
- [x] Tenant Question Placement is permission-separated, tenant-safe, optimistic, and frozen after publication.
|
||||
- [x] Database graph-integrity changes use `flyway-postgresql` and forward migrations V4070/V4090.
|
||||
- [x] The next Manual Question Collection bounded contract, exclusions, pre-provisioning constraint, and readiness gates are explicit before implementation.
|
||||
- [ ] A current-tenant `TENANT_OWNED` Manual Question Collection can be authored only in `JAVA_READ` on an existing ACTIVE, visible Content Node.
|
||||
- [ ] Collection lifecycle is `DRAFT → ACTIVE → ARCHIVED` with one optimistic authoring version; ACTIVE content/membership is immutable and archive is terminal.
|
||||
- [ ] DRAFT membership is ordered replace-all, accepts only current-tenant `TENANT_OWNED` PUBLISHED Questions, and rejects duplicates.
|
||||
- [ ] Collection archive gates only collection-route discovery while direct Question visibility and historical Practice snapshots remain unchanged.
|
||||
|
||||
## Delivery progress — graph-integrity slice (2026-07-30)
|
||||
|
||||
@@ -98,6 +103,35 @@ Delivered:
|
||||
- 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.
|
||||
|
||||
## Next slice — Manual Question Collection bounded contract (accepted 2026-07-31)
|
||||
|
||||
This section records domain and readiness decisions only. No production Java, SQL, Flyway migration, permission seed, or runtime behavior is delivered by this documentation step.
|
||||
|
||||
Accepted boundary:
|
||||
|
||||
1. Native authority only: every collection command is available only in `JAVA_READ`; unsupported modes must fail before persistence access.
|
||||
2. Tenant ownership only: tenant APIs manage current-tenant `TENANT_OWNED` collections. PUBLIC Questions, PUBLIC collection curation, and platform-curator workflows are excluded.
|
||||
3. Placement boundary: a collection belongs to one existing ACTIVE, visible Content Node. Content Entry creation is excluded, so that node and its structurally available Content Entry must already be provisioned before collection authoring.
|
||||
4. Manual assembly only: membership is an explicit ordered list, not a dynamic filter, Category result, Question Bank query, node-descendant query, or Practice Blueprint.
|
||||
5. Lifecycle and concurrency: collections move only `DRAFT → ACTIVE → ARCHIVED`. One optimistic authoring version covers accepted draft revisions, ordered membership replacement, activation, and archive. ACTIVE collection fields and membership are immutable; ARCHIVED is terminal.
|
||||
6. Membership replacement: only a DRAFT collection accepts an ordered replace-all membership command. Every member must be a current-tenant `TENANT_OWNED` PUBLISHED Question. Duplicate Question IDs are a request conflict and are not deduplicated or upserted.
|
||||
7. Visibility: an ACTIVE collection may be discovered only through its available Content Node. Archive closes collection listing and collection-question discovery, but does not archive member Questions, change their direct visibility, or invalidate immutable Practice Question Snapshots already captured.
|
||||
8. Access metadata: `access_rules` remains descriptive reserved metadata. This slice does not interpret it as paid, private, member, SVIP, quota, or other entitlement enforcement.
|
||||
9. Explicit exclusions: dynamic filters, paid/private access, Category CRUD, Practice Blueprint authoring, Content Entry creation, PUBLIC content/curation, Retire, and legacy section/score/required membership extensions.
|
||||
|
||||
### Readiness and implementation gates
|
||||
|
||||
- [x] Current target evidence identifies `education_question_collection_question` as the sole collection-membership fact, with tenant-scoped duplicate prevention and deterministic membership order.
|
||||
- [x] Legacy evidence confirms manual collections, transactional replace-all membership, server-derived counts, active-parent route gating, and an independent `DRAFT/ACTIVE/ARCHIVED` lifecycle; richer dynamic/filter and per-member scoring semantics are deliberately excluded.
|
||||
- [x] Provider-neutral option safety is already resolved by EDU-001 and `QuestionContentSafety`; it is not an EDU-010 blocker.
|
||||
- [x] Root Education SQL is already classified as non-operational manual/design history by EDU-005; module-owned PostgreSQL Flyway remains authoritative. Shared-environment adoption inventory remains an operational rollout gate, not an unresolved schema-owner decision.
|
||||
- [ ] Before implementation, allocate the next project-wide Flyway version through `flyway-postgresql` and design forward adoption from the current boolean collection availability fields.
|
||||
- [ ] Make collection listing and collection-question reads validate collection lifecycle and Content Node availability at the route boundary; the current Java collection-question read loads membership without first proving the parent collection is available.
|
||||
- [ ] Define separate collection author/publish/archive permissions, tenant-bound command requests, lifecycle audit, CAS conflict errors, server-derived `question_count`, and transaction boundaries.
|
||||
- [ ] Add focused service, method-security, and real-PostgreSQL tests for provider fail-before-Mapper behavior, cross-tenant/PUBLIC rejection, duplicate membership, stale versions, ACTIVE immutability, terminal archive, route gating, direct Question visibility, and snapshot preservation.
|
||||
|
||||
No new ADR is added: this bounded slice consistently applies the existing native-authority and lifecycle decisions and does not introduce a separate hard-to-reverse architectural trade-off.
|
||||
|
||||
## Verification evidence (2026-07-30)
|
||||
|
||||
- `mvn -pl yudao-module-education clean test` with the five `EDU_TEST_POSTGRES_*` variables pointed at the local Docker PostgreSQL: **502 tests passed**, including 20 Flyway migration tests and nine lifecycle/placement PostgreSQL integration tests. V4090 was actually executed in disposable PostgreSQL schemas.
|
||||
|
||||
@@ -80,6 +80,30 @@ _Avoid_: Question Placement Version, Question Content Version
|
||||
An append-only Education domain fact recording actor, authoring version, and a valid Content Node Publication State transition in the same transaction.
|
||||
_Avoid_: Operation log as activation proof
|
||||
|
||||
**Manual Question Collection**:
|
||||
A tenant-owned, author-curated ordered set of Published Question Content attached to one existing active, visible Content Node. Its membership is selected explicitly rather than derived from filters, categories, or blueprints.
|
||||
_Avoid_: Dynamic question bank, Category, Practice Blueprint
|
||||
|
||||
**Collection Publication State**:
|
||||
The lifecycle of a Manual Question Collection: Draft is author-editable and undiscoverable, Active is immutable and discoverable through its Content Node, and Archived is terminal and undiscoverable through the collection route.
|
||||
_Avoid_: Question Publication State, hidden flag
|
||||
|
||||
**Collection Authoring Version**:
|
||||
The single non-negative optimistic concurrency version advanced by each accepted draft revision, membership replacement, or collection lifecycle transition.
|
||||
_Avoid_: Question Content Version, Question Placement Version
|
||||
|
||||
**Collection Membership**:
|
||||
The complete ordered list of Published Question Content explicitly curated into a Manual Question Collection. It is replaceable only as a whole while the collection is Draft, and the same question cannot occur more than once.
|
||||
_Avoid_: Dynamic filter result, incremental published playlist
|
||||
|
||||
**Collection Route Discovery**:
|
||||
Student discovery of questions through an Active Manual Question Collection on its Content Node. Archiving the collection closes only this route and does not withdraw directly visible Question Content or alter historical Question Snapshots.
|
||||
_Avoid_: Question publication, snapshot invalidation
|
||||
|
||||
**Collection Access Rules**:
|
||||
Descriptive collection metadata reserved for a future access contract. Its presence does not grant, deny, or prove paid, private, membership, or other entitlement in the current Education model.
|
||||
_Avoid_: Entitlement policy, authorization rule
|
||||
|
||||
**Protected Answer Key**:
|
||||
Server-only correctness and explanation data captured for stable scoring of a practice session. It is never included in a Safe Question, Question Snapshot JSON, or pre-submit response.
|
||||
_Avoid_: Question Snapshot, frontend answer
|
||||
|
||||
Reference in New Issue
Block a user