Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-017-tenant-appearance.md

39 lines
3.4 KiB
Markdown

# EDU-017 — Tenant appearance, public settings, and theme lifecycle
- **Status:** done — bounded appearance/theme slice implemented and verified
- **Type:** tenant administration / public presentation configuration
- **Phase:** 4 / tenant operations
- **Blockers:** EDU-003, System Tenant authority, Vben admin foundation
## Decision
System Tenant remains authoritative for tenant identity, display name, lifecycle, and bound websites. Education owns only presentation-specific configuration: branding extensions, student/admin feature flags, public runtime configuration, and draft/published theme state. The public tenant locator response remains the minimal EDU-003 contract; appearance is exposed separately under the normal request tenant context.
Platform theme templates are global trusted configuration and are explicitly excluded from MyBatis tenant injection. Tenant appearance rows extend `TenantBaseDO`, retain one live row per tenant, and use optimistic versions for every update. RuoYi System RBAC, tenant validation, admin projection, API access/operation logging, and the normal `tenant-id` security filter remain authoritative.
## Delivered contract
- Admin read, branding write, settings write, theme preview, and theme publish endpoints with independent permissions.
- `GET /education/tenant-appearance/public` is anonymous but not tenant-ignored; it requires the normal validated tenant header/context and returns no admin flags or draft data.
- System tenant name is the lazy-row default and fallback; no duplicate Education tenant identity or domain authority is created.
- Three legacy-compatible templates are seeded: `classic`, `focus`, and `high-contrast`.
- Theme preview is a shallow template/override merge. Publication revalidates the persisted draft and clears it atomically.
- Recursively rejects secret/password/token/private-key/API-key-like public keys except `secretRef`; theme tokens, CSS variables, icons, assets, colors, radii, modes, and density are allowlisted and unsafe renderable strings fail closed.
- Vben page `education/tenant-appearance/index` manages branding, JSON settings, templates, draft preview, and explicit publication with client-side preflight checks.
## Verification
- Policy unit tests cover recursive secret rejection, closed theme/asset key sets, colors/radii/CSS, URLs, and shallow merge.
- Service unit tests cover System-name fallback, optimistic conflict, sanitized draft persistence, and public projection.
- Method-security contract tests prove query, branding, settings, and theme permissions are independent.
- Real PostgreSQL service tests prove lazy defaults, shared templates, settings, draft/publish, public projection, stale-version rejection, and cross-tenant isolation through the production MyBatis interceptor.
- Flyway tests prove the V4290 schema, exact template seeds, menu shape, unique tenant row, and draft/publish database state.
## Explicitly open
- Domains stay in System Tenant `websites`; no Education domain CRUD authority is planned.
- Payment-account configuration must compose Pay rather than copy the legacy table.
- Authentication-provider configuration must reuse System/Member authentication seams.
- Tenant secret storage/rotation needs a dedicated encrypted private-storage decision and must never be added to the public appearance table.
- Activation codes and coupons need a Mall Promotion/Member entitlement ownership and idempotent redemption decision.