diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-18 08:27:41 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-18 08:27:41 +0800 |
| commit | 088735b948d46896b8af30efcb0a2dc5d362b97f (patch) | |
| tree | 0dcab0d5ebc65309267a42d7cda827e9fdd866e7 /docs/backend-repair-contract.md | |
| parent | bf6681eb29ac8b0c80ca17b2b5869f7de3da1198 (diff) | |
| download | strategy-lab-088735b948d46896b8af30efcb0a2dc5d362b97f.tar.gz | |
docs(release): 全周期交接文档入库(含 ui-shadcn 迁移交付说明)
[变更性质]
纯文档提交,无运行时逻辑。
[文档内容]
补齐此前各轮未入库的交接/验收文档:backend-auth/backend-domain/
domain-authorization-user(认证与授权域)、etf-recovery-release-
handoff(ETF 修复 + ops 演练定稿与生产部署命令)、recovery-* 系列、
frontend/parent-ui-findings(UI 迁移上下文)、worker/integration 等,
以及本轮 docs/ui-shadcn-handoff.md(shadcn-svelte 迁移交接,含
Chart.svelte 契约、runes $state 踩坑记录与 375/768/1440 验证证据)。
[更新方案]
按主题分文;每份文档只记录可复现的命令、验证结果与语义边界,
不导出密钥或生产敏感路径。
[影响范围]
文档渠道:后续 leader/client 审阅入口;与代码提交一一对应便于回溯。
Diffstat (limited to 'docs/backend-repair-contract.md')
| -rw-r--r-- | docs/backend-repair-contract.md | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/docs/backend-repair-contract.md b/docs/backend-repair-contract.md new file mode 100644 index 0000000..2b02703 --- /dev/null +++ b/docs/backend-repair-contract.md @@ -0,0 +1,34 @@ +# Backend repair contract (mandatory for all repair workers) + +Prior broad edits introduced cascading signature errors. Parent stopped the old backend process. Repair in narrow file ownership; other workers may be editing their own files. Do NOT edit outside your allocation. Do not weaken tests, delete API handlers, or change language/framework. + +## Fixed signatures +- state.rs exports `pub type Cx = axum::extract::State<std::sync::Arc<AppState>>;` +- AppState owns cfg:Config, db:tokio::sync::Mutex<rusqlite::Connection>, run_sem/fetch_sem Arc<Semaphore> (preserve other needed state). +- `impl AppState { pub async fn with_db<R>(&self, f: impl FnOnce(&mut rusqlite::Connection) -> R) -> R { let mut db = self.db.lock().await; f(&mut db) } }`. +- This returns exactly R after await. If closure returns Result<T,E>, use `.await?`; if closure returns number/unit, `.await` only. Never await inside database closure. Keep transactions and atomic operations inside ONE closure. No nested locks. +- Handler argument is `cx: Cx` (State extractor), not a bare Arc alias. Helper taking `&Cx` receives `&cx`. Background jobs may use Arc and create `State(cx.clone())` only where necessary. All handlers futures must be Send. +- util::now_iso() -> String is SYNCHRONOUS. hash/random token helpers synchronous unless they actually await. +- error::AppError supports new(StatusCode,code,message), bad(code,message), unauthorized(message), forbidden(message), not_found(message), conflict(code,message), internal(message), with_details(Value), with_code(code). One inherent impl, one IntoResponse, one From<rusqlite::Error>, one From<std::io::Error>, one From<serde_json::Error>. Never duplicate From impl elsewhere. +- `auth::make_admin_token` existing admin call sites need coherent async Result signature; auth/admin worker owns both. +- Router Axum0.8 paths use `{id}`, NEVER `:id` (runtime panic). +- Do not change actual JSON HTTP contract: SPEC.md + RELEASE_SCOPE.md authoritative. + +## Worker partition +CORE: config.rs state.rs error.rs util.rs main.rs store.rs worker.rs Cargo.toml (+ core tests). Main integrates call signatures but not other module sources. +AUTH: auth.rs admin.rs (+ auth tests inside module). +DOMAIN: projects.rs datasets.rs runs.rs ai.rs jobs.rs (+ domain tests inside module). +Read other files freely. Compile often, filter diagnostics for OWN modules; leave other-worker diagnostics alone. Final shared compile gate performed by parent. + +## Parent findings to address +- main.rs origin substring match is exploitable. Compare exact canonical origin (scheme+host+port), reject `https://allowed.example.evil.invalid`. Empty canonical allows exact local origin only. No trust of X-Forwarded host. +- Serve frontend/dist static SPA with index.html fallback for UI only; /api unknown returns JSON 404 (not SPA). +- Instrument search current stub must connect to actual worker catalog command; no fake successful empty list. Docker worker fetch/search with bounded time and resource. +- Concurrent fetch duplicate cache key must serialize/recheck. request/cache key and manifest hash are distinct columns/concepts. +- All raw+normalized referenced artifacts retained; worker manifest fields must be checked against live worker code. +- Read-only nonroot container UID65534 needs writable output (parent job dir0700, output mode0777 inside; no secrets). Input/data are read-only. Stdout/stderr bounded and drained; timeout/cancel container cleanup real. +- Finished run state only succeeded if worker JSON status says succeeded. Failed/cancelled state must not be overwritten by racing completion. +- Durable queued jobs recheck account active, dataset ownership/readiness, per-user budget. +- Invitation email binding, one-time transaction, no role escalation; disable/reset revoke sessions; last admin protection. + +Parent independent API tests live at scripts/qa_api.py, including substring CSRF and admin/private owner separation. READ these gates and make them genuinely pass. Parent prepares isolated QA environment, do not read any secrets outside project. |
