68 lines
9.8 KiB
Markdown
68 lines
9.8 KiB
Markdown
# 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`](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`](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.
|