Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-019-learning-activation-codes.md

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 UPDATE serializes 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=0 intentionally means no expiry.
  • Vben page education/activation-code/index provides 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.