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.
- A Tenant Locator Claim is unauthenticated input, not identity. Browser
OriginthenRefererprovides browser-context consistency evidence but is forgeable by non-browser callers. - 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. - Headless clients use
tenantHandle. The target currently has no distinct stable Tenant Code, so this is explicitly the unique System tenantnameunder a case-sensitive^[A-Za-z0-9._-]{2,64}$, operationally immutable public contract. Legacy publictenantNameis rejected rather than aliased. - 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.
- 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.
- Local fallback is enabled only by
yudao.education.tenant-resolution.local-development-enabled, defaultfalse; profiles do not enable it. With the flag true, code-less configured local-host resolution is permitted, while an explicit handle takes precedence. /education/contextis Member-only, obtains the fullLoginUser, and continues deriving IDs only from security and tenant contexts.TenantSecurityWebFilterremains responsible for authenticated missing-tenant, mismatch, and availability checks.- Login-method metadata belongs to Member authentication. EDU-004 removes/deprecates Education
loginMethodsunless a minimal Member-owned interface is first proven necessary. - Exact public business failures use HTTP 200/CommonResult: invalid locator
1005001003/租户识别请求无效; conflict1005001008/租户识别信息冲突; unknown/disabled/expired1005001004/当前租户不可用; all have null data and redacted detail. Success is code 0 and onlytenantIdplusdisplayName. - Retain
TenantCommonApias the generic System-owned seam. EDU-004 makes lookup methods required and adds System-ownedTenantApiImplcontract tests; no Education locator concept enters System. - 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.
- 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. - 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. - 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. - 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.
- Legacy idempotency data is backfilled into the unified table before any later forward cleanup. Legacy tables are preserved during initial adoption.
- The Education capability menu seed is a separate conditional V4040 owner only if the administrator endpoint remains approved; role assignment is not seeded.
- 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.
- The inspected local disposable
postgresdbhad no Flyway history and no Education tables. EDU-005 ran no migration and makes no migration-success claim.
Other established constraints
- 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.
- Verified target branch is feature/education-core-loop and its worktree is dirty. Preserve all existing changes and classify current state at execution time.
- Classify target behavior as committed-and-tested, committed-but-not-runtime-verified, dirty/uncommitted, or absent before scheduling work.
ce02f8ais committed core-loop evidence; native provider/catalog and much of the schema are dirty. - 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.
- 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.
- Treat public tenant resolution as an unauthenticated disclosure surface requiring exact redaction and abuse controls. Separately preserve
TenantSecurityWebFilterauthenticated mismatch checks; the remaining principal issue is Member/UserType enforcement in/education/context. - Treat hostname port and stored-website representation as verified contradictions requiring alignment across implementation, properties, API documentation, System lookup behavior, configuration, and tests.
- 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.
- 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.
- 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.
- 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.
- Do not expose paid/private practice until entitlement semantics and public target contracts are decided.
- 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
- 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.
- 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.
- Whether untracked /Users/tiku1/code/ruoyi-vue-pro/sql/postgresql/education files are intended for promotion into Flyway or are design/manual artifacts.
- Whether V4010/V4020 or any manual core-loop DDL has ever run successfully in PostgreSQL; no runtime migration evidence exists.
- 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.
- 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.
- Whether legacy assets are migrated, re-uploaded, re-scanned, or retired, and who owns ClamAV/scanner integration.
- Which legacy RLS, triggers, functions, grants, seeds, queue leases, retry behavior, and operational semantics are contractual and need Java/constraint/event/job reproduction.
- Whether the ten required Phase 0 artifacts must be committed files or may remain in reviewed scratch form during discovery.
- 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.