2.8 KiB
2.8 KiB
EDU-019 — Secure learning activation codes
Status
Done for the bounded V4310 contract. Legacy activation-code import and coupons remain separate.
Decision
Activation codes are Education learning-access credentials, not Mall Promotion coupons. They reference a Mall-owned SPU through the existing tenant-scoped education_resource_product_binding, authenticate redemption with the existing Member principal, and grant access through the existing idempotent EducationEntitlementService event pipeline. No product, member, coupon, or second entitlement ledger is introduced.
Delivered contract
- Tenant-owned activation-code batches and codes with database constraints, tenant-composite foreign keys, optimistic versions, and separate query/manage/generate permissions.
- Admin batch page/create/update/generate and masked code page/disable endpoints.
- Member-only app check/redeem endpoints; administrator and anonymous principals fail closed.
- Cryptographically random codes normalized for redemption. Plaintext is returned only by the successful generation response; persistence stores SHA-256 digest and a mask.
SELECT ... FOR UPDATEserializes redemption. A successful grant writes the existing entitlement event/aggregate, marks the code redeemed, and increments the batch count in one transaction.- Same-member retry returns the existing entitlement idempotently; another member receives an already-used conflict.
- Batch SPU, duration, and prefix become immutable after generation. Disabled batches, codes, or resource bindings cannot be redeemed.
durationDays=0intentionally means no expiry. - Vben page
education/activation-code/indexprovides batch and masked-code tables, create/edit/generate flows, copy/download, unsaved-plaintext dismissal warning, and disable confirmation. Closing the generation modal clears plaintext.
Verification
- PostgreSQL Flyway verifies both tables, constraints, cross-tenant batch references, four menu rows, and migration history through V4310.
- Controller contracts verify independent admin permissions and Member-only app access.
- Unit tests verify digest/mask persistence, entitlement composition, replay/conflict, target validation, and generated-batch immutability.
- Real PostgreSQL service tests verify digest-only persistence, tenant isolation, entitlement/event creation, same/different-member behavior, disabled dependencies, and one winner under concurrent redemption.
- Vben formatting, lint, Vue typecheck, and production build cover the fifteenth custom Education page.
Explicit non-goals
- Importing or preserving plaintext from legacy activation-code rows.
- Coupon templates, claims, discounts, stacking, or redemption; those remain Mall Promotion-owned.
- Payment/order/refund fulfillment, legacy payment mode/provider mapping, tenant PNVS, or generic encrypted secret rotation.