Files
ruoyi-vue-pro/docs/education/migration/07-decisions.md

9.8 KiB

Architecture and Product Decisions

Phase 0 static assessment generated on 2026-07-29. No build, test, application startup, PostgreSQL connection, or Flyway migration was executed during this assessment.

Decisions and constraints established by static evidence

EDU-003 accepted decision — tenant resolution and student principal

The durable rationale, threat model, exact wire contract, compatibility policy, and EDU-004 test matrix are recorded in issues/EDU-003-tenant-resolution-decision.md.

  1. A Tenant Locator Claim is unauthenticated input, not identity. Browser Origin then Referer provides browser-context consistency evidence but is forgeable by non-browser callers.
  2. A supplied hostname may only confirm browser-context evidence; disagreement is a conflict. Preserving browser headers or rejecting forwarding-header forgery does not authenticate Origin/Referer.
  3. Headless clients use tenantHandle. The target currently has no distinct stable Tenant Code, so this is explicitly the unique System tenant name under a case-sensitive ^[A-Za-z0-9._-]{2,64}$, operationally immutable public contract. Legacy public tenantName is rejected rather than aliased.
  4. Public resolution discloses tenant existence on success. The guarantee is only that unknown, disabled, and expired tenants share one response. Reuse public throttling/ingress controls and emit structured probing metrics; spoof-resistant deployments require a future signed/authenticated locator.
  5. Host identity is lowercase, trimmed, trailing-dot-free, bracket-free for IPv6, and port-independent. Canonical System website entries for this resolver are host-only; non-canonical scheme/path/port entries do not match and require configuration correction or a separately scoped Flyway/data ticket.
  6. Local fallback is enabled only by yudao.education.tenant-resolution.local-development-enabled, default false; profiles do not enable it. With the flag true, code-less configured local-host resolution is permitted, while an explicit handle takes precedence.
  7. /education/context is Member-only, obtains the full LoginUser, and continues deriving IDs only from security and tenant contexts. TenantSecurityWebFilter remains responsible for authenticated missing-tenant, mismatch, and availability checks.
  8. Login-method metadata belongs to Member authentication. EDU-004 removes/deprecates Education loginMethods unless a minimal Member-owned interface is first proven necessary.
  9. Exact public business failures use HTTP 200/CommonResult: invalid locator 1005001003 / 租户识别请求无效; conflict 1005001008 / 租户识别信息冲突; unknown/disabled/expired 1005001004 / 当前租户不可用; all have null data and redacted detail. Success is code 0 and only tenantId plus displayName.
  10. Retain TenantCommonApi as the generic System-owned seam. EDU-004 makes lookup methods required and adds System-owned TenantApiImpl contract tests; no Education locator concept enters System.
  11. EDU-003 made no production, database, or Flyway change; verification is static only.

EDU-005 accepted decision — PostgreSQL/Flyway takeover

The durable artifact classification, adoption matrix, version allocation, backfill policy, documentation corrections, and real-PostgreSQL verification gates are recorded in issues/EDU-005-flyway-takeover-decision.md.

  1. Education schema delivery is exclusively module-owned PostgreSQL Flyway under yudao-module-education/src/main/resources/db/migration/education/; root PostgreSQL scripts are manual bootstrap/design history and MySQL scripts are obsolete archives.
  2. V4010 (SELECT 1) and V4020 (native catalog) remain byte-for-byte frozen because execution outside the inspected environment is unverified. The next planned project-wide version is V4030, subject to a fresh version scan at implementation time.
  3. V4030 owns the final Practice core-loop schema, including sessions/questions, reports/details, wrong questions, favorites, and unified education_idempotency. Fresh schema does not create legacy answer/submit idempotency tables.
  4. Existing manually bootstrapped databases require explicit schema comparison and adoption. A verified V4020-equivalent catalog may use an environment-specific 4020 baseline; incompatible environments require a higher-version correction, never falsified history.
  5. Legacy idempotency data is backfilled into the unified table before any later forward cleanup. Legacy tables are preserved during initial adoption.
  6. The Education capability menu seed is a separate conditional V4040 owner only if the administrator endpoint remains approved; role assignment is not seeded.
  7. Docker/manual SQL initialization and MySQL rollback runbooks must be removed from active operations when EDU-006 lands. EDU-016's temporary test bridge becomes Flyway-driven after equivalence is proven.
  8. The inspected local disposable postgresdb had no Flyway history and no Education tables. EDU-005 ran no migration and makes no migration-success claim.

Other established constraints

  1. Verified source provenance is limited: /Users/tiku1/code/tiku-backend has only main and origin/main at 033701a785c7012139e7f86995eea6041225592e; no local or remote feature/education-core-loop ref exists. Use main/033701a provisionally only, or obtain explicit approval for that baseline.
  2. Verified target branch is feature/education-core-loop and its worktree is dirty. Preserve all existing changes and classify current state at execution time.
  3. Classify target behavior as committed-and-tested, committed-but-not-runtime-verified, dirty/uncommitted, or absent before scheduling work. ce02f8a is committed core-loop evidence; native provider/catalog and much of the schema are dirty.
  4. Verified V4010 is SELECT 1 and V4020 is native catalog only. Practice/report/idempotency/wrong/favorite DDL in sql/postgresql/education is untracked/manual and not proven active Flyway. Convert required DDL to immutable module-owned PostgreSQL Flyway migrations before claiming schema delivery; never modify published migrations.
  5. Keep PostgreSQL/Flyway as the only new schema delivery mechanism. Historical MySQL files and root SQL are not active delivery unless explicitly labeled archival/manual and removed from operational runbooks.
  6. Treat public tenant resolution as an unauthenticated disclosure surface requiring exact redaction and abuse controls. Separately preserve TenantSecurityWebFilter authenticated mismatch checks; the remaining principal issue is Member/UserType enforcement in /education/context.
  7. Treat hostname port and stored-website representation as verified contradictions requiring alignment across implementation, properties, API documentation, System lookup behavior, configuration, and tests.
  8. Treat native catalog isolation as an intentional TenantUtils.executeIgnore/manual-scope boundary, not evidence of a current leak. Make mapper audit and tenant/scope-consistent graph constraints concrete blockers before authoring.
  9. Make the first slice provider-neutral or cover both providers because SCALAR_READ is the verified default and Java provider is conditional. The slice must include fresh browsing and persisted session restoration, with a common option-schema contract and fail-closed behavior.
  10. Do not treat submit idempotency as complete: check-then-insert is not an atomic claim. Reserve keys atomically and define crash recovery before the submit slice.
  11. Add first-class Auth/Profile/extended Learning, tenant appearance/integrations/secrets/codes, and granular platform-admin capability groups so every required legacy cluster has a disposition.
  12. Do not expose paid/private practice until entitlement semantics and public target contracts are decided.
  13. No tests, builds, PostgreSQL connections, Flyway execution, or runtime verification were performed by the Phase 0 assessment unless a later ticket explicitly records otherwise.

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 PUBLIC tenant_id=0 rows may reference only PUBLIC parents, whether tenant-owned rows may reference global rows, and the precise composite constraint/trigger strategy.
  3. Whether untracked /Users/tiku1/code/ruoyi-vue-pro/sql/postgresql/education files are intended for promotion into Flyway or are design/manual artifacts.
  4. Whether V4010/V4020 or any manual core-loop DDL has ever run successfully in PostgreSQL; no runtime migration evidence exists.
  5. 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.
  6. 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.
  7. Whether legacy assets are migrated, re-uploaded, re-scanned, or retired, and who owns ClamAV/scanner integration.
  8. Which legacy RLS, triggers, functions, grants, seeds, queue leases, retry behavior, and operational semantics are contractual and need Java/constraint/event/job reproduction.
  9. Whether the ten required Phase 0 artifacts must be committed files or may remain in reviewed scratch form during discovery.
  10. Whether a future System-owned immutable Tenant Code or signed bootstrap locator is required beyond the accepted public-handle/existence-disclosure contract.

Decision rule

Questions answerable from code, Git history, configuration, tests, or documentation must be investigated. Only genuine product choices should be escalated. Hard-to-reverse decisions should become ADRs before dependent implementation begins.