Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0e6800fe8 | ||
|
|
23d11b0d21 | ||
|
|
c3598820ef | ||
|
|
7e1bc48ee0 |
@@ -0,0 +1,29 @@
|
||||
# `next/`失败冻结记录
|
||||
|
||||
> 决策日期:2026-07-30
|
||||
> 状态:用户验收失败,永久冻结,禁止部署
|
||||
|
||||
## 结论
|
||||
|
||||
`next/`采用重新实现方式建立,与本次迁移的真实目标不一致。用户确认其页面视觉、布局和基础功能
|
||||
未达到原系统等价要求,因此该目录不再作为产品候选、迁移成果或后续重构基础。
|
||||
|
||||
原发布候选`xiaobai-next-rc-20260730-1`自本记录生效起作废。不得使用`next/Dockerfile`、
|
||||
`next/compose.yaml`或`next/compose.preflight.yaml`部署任何正式或预检环境。
|
||||
|
||||
## 冻结边界
|
||||
|
||||
1. `next/`只保留作失败复盘、测试思路和迁移工具参考,不再修补产品功能或视觉。
|
||||
2. 后续迁移不得从`next/`反向覆盖原系统,也不得把其页面作为视觉基准。
|
||||
3. 原系统仍是唯一产品事实和视觉基线;后续工作必须采用原代码保真式结构迁移。
|
||||
4. 未经用户新的明确决定,不删除`next/`,不移动失败标签,不恢复其发布候选身份。
|
||||
5. `next/data/`中的本地迁移副本继续保持Git忽略,不作为生产数据。
|
||||
|
||||
## 失败原因
|
||||
|
||||
- 错误地把“建立独立目录并迁移”执行成了重新设计和重新实现。
|
||||
- 自动测试主要验证新实现内部契约,没有证明与原系统逐页面、逐状态、逐像素等价。
|
||||
- 以代码行数下降和规格案例覆盖代替了原系统完整行为保真。
|
||||
- 用户人工验收确认视觉、布局及基础功能不可作为正式产品使用。
|
||||
|
||||
本记录优先于`next/`内所有阶段完成、发布候选、预检和切换说明。
|
||||
@@ -1,9 +1,13 @@
|
||||
# 小白复盘重建迁移章程
|
||||
# 小白复盘重建迁移章程(本轮实施失败冻结)
|
||||
|
||||
> 状态:执行中
|
||||
> 建立日期:2026-07-30
|
||||
> 状态:失败冻结,禁止继续或部署
|
||||
> 建立日期:2026-07-30
|
||||
> 产品真相源:`docs/product/小白复盘-完整产品规格说明书.md`
|
||||
|
||||
> 2026-07-30用户人工验收确认`next/`的视觉、布局和基础功能未达到原系统等价要求。
|
||||
> 本章程后续阶段记录只作为失败过程留档,不再构成完成证明。权威处置记录见
|
||||
> [`next失败冻结记录.md`](next失败冻结记录.md)。
|
||||
|
||||
## 1. 唯一目标
|
||||
|
||||
在当前仓库的`next/`目录内,从零重建小白复盘。新系统必须完整实现产品规格说明书定义的功能、权限、数据口径、交互状态、视觉和终端行为,同时显著减少重复实现、补丁层和隐式依赖,使后续人工维护可操作。
|
||||
|
||||
+5
-1
@@ -1,4 +1,8 @@
|
||||
# 小白复盘重建版
|
||||
# 小白复盘重建版(失败冻结)
|
||||
|
||||
> **禁止部署或继续开发。** 本实现已于2026-07-30被用户判定为迁移失败,原发布候选已作废。
|
||||
> 冻结原因和后续边界见[`../docs/migration/next失败冻结记录.md`](../docs/migration/next失败冻结记录.md)。
|
||||
> 本目录以下内容只保留作历史取证,不再代表产品现状或交付状态。
|
||||
|
||||
本目录是依据产品规格说明书从零建立的新系统。旧系统只用于行为对照,新系统不得在运行时导入或读取旧系统源码。
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 新系统部署与回退
|
||||
# 新系统部署与回退(已作废,禁止执行)
|
||||
|
||||
> `next/`已于2026-07-30被用户判定为迁移失败。本文件仅保留历史取证,不授权构建、部署或切换。
|
||||
> 权威冻结决定见`../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
本说明只适用于 `next/` 重建版。旧容器在最终人工确认前继续运行,不得原地覆盖。
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
- 新版地址:`http://127.0.0.1:8877`
|
||||
- 新版数据库:`next/data/local-preflight/xiaobai-normalized-v7.db`
|
||||
- 旧版`8765`未启动、未占用、未修改。
|
||||
- 旧版`8765`未启动、未占用;旧版源码仅修复静态首页被API权限注册表误拦截的既有回归,
|
||||
未增加产品功能。
|
||||
- 本轮未连接NAS,未执行Docker构建或容器切换。
|
||||
|
||||
## 迁移校验
|
||||
@@ -47,12 +48,20 @@
|
||||
## 自动质量门
|
||||
|
||||
- Ruff:通过
|
||||
- pytest:111项通过
|
||||
- pytest:113项通过
|
||||
- Vue类型检查:通过
|
||||
- Vitest:7项通过
|
||||
- Vite生产构建:通过
|
||||
- Playwright:26项通过;在隔离测试数据库中重跑,包含注册、权限、16工作区、日夜、390px、长页路由复位和4K结构断言。
|
||||
|
||||
## 旧版并行可运行性
|
||||
|
||||
- 使用独立空数据目录和临时端口`8890`启动旧版,未读取或写入真实旧库,也未占用正式端口`8765`。
|
||||
- `/api/health`返回`200 application/json`,静态首页`/`返回`200 text/html`。
|
||||
- 发现并修复旧版既有回归:API权限注册表曾错误处理静态路径,使首页返回404;现仅`/api/*`
|
||||
进入权限注册表,静态资源仍由原静态服务处理。
|
||||
- 旧版全量基线为231项测试和32项subtest全部通过;静态首页绕过API注册表有直接回归测试。
|
||||
|
||||
## 未关闭项
|
||||
|
||||
- 4K信息密度和审美仍需用户人工确认。
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 阶段 15 总验收
|
||||
# 阶段15总验收(结论已由用户人工验收否决)
|
||||
|
||||
> 本文件只保留当时的自动化证据,不再构成产品完成或可用性证明。权威冻结决定见
|
||||
> `../../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
## 产品覆盖
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 重建版完成度审计
|
||||
# 重建版完成度审计(历史记录,验收结论已撤回)
|
||||
|
||||
> 用户人工验收确认本实现未达到原系统视觉、布局和基础功能等价要求。本文中的自动测试和阶段结论
|
||||
> 不能再作为产品完成证明。权威冻结决定见`../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
更新日期:2026-07-30
|
||||
|
||||
@@ -14,6 +17,7 @@
|
||||
## 已确认完成的基础
|
||||
|
||||
- 新旧运行时完全分离,新版不导入旧版 `server.py`、`database.py`、`app.js` 或旧样式覆盖层。
|
||||
- 旧版已在独立数据目录和临时端口完成首页、健康检查及231项测试与32项subtest验收;迁移期仍可运行。
|
||||
- 账户、会话、管理员与会员双维度权限、私有数据隔离、系统凭据加密和模型密钥不回显已有服务端测试。
|
||||
- 行情供应商通过唯一 `DataGateway` 和来源策略进入业务层;公开展示源不能进入正式计算。
|
||||
- 情绪、竞价、观势、观气、观心、选股和复盘的核心确定性计算已有固定样本测试。
|
||||
@@ -71,7 +75,8 @@
|
||||
- 图表夜间加载首帧、主题同步切换、7板布局和观心夜间关键文字对比度均已有浏览器直接断言,不再只依赖截图。
|
||||
- 16个主工作区、策略跟踪、提醒、复盘助手、账户/会员及系统管理已逐项区分加载、真实空和失败;统一API客户端不会向页面泄露上游错误正文。
|
||||
- 后台任务不再把`AppError`内部元组直接展示到系统管理;历史记录读取时兼容清理,新增失败按用户可读说明入库。
|
||||
- 本轮验证为Ruff、111项pytest、Vue类型检查、7项Vitest、生产构建和26项Playwright全部通过。
|
||||
- 当前主分支本轮复核为Ruff、113项pytest、Vue类型检查、7项Vitest、生产构建和
|
||||
26项Playwright全部通过。
|
||||
|
||||
## 本轮范围外项目
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# NAS切换清单
|
||||
# NAS切换清单(已作废,禁止执行)
|
||||
|
||||
> `next/`已被用户否决,本清单不再具备切换效力。权威冻结决定见
|
||||
> `../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
此清单是最终人工确认前的准备资产,不授权当前任务停止或替换正式容器。
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 旧实现清理方案
|
||||
# 旧实现清理方案(已作废,禁止执行)
|
||||
|
||||
> `next/`已被用户否决。禁止依据本方案删除原系统任何代码、容器或数据。权威冻结决定见
|
||||
> `../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
本文只定义正式切换后的清理边界,不授权当前阶段删除旧代码、旧容器或旧数据。
|
||||
清理目标是让仓库最终只保留 `next/` 新系统及不可替代的产品和研究资产,不保留两套运行时。
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 人工维护手册
|
||||
# 人工维护手册(失败实现历史资料)
|
||||
|
||||
> `next/`已被冻结,禁止依据本手册继续维护或扩展该实现。后续保真迁移不得把这里的结构当作
|
||||
> 既定方案。权威冻结决定见`../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
## 从哪里开始
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 页面状态覆盖矩阵
|
||||
# 页面状态覆盖矩阵(历史记录,不能证明迁移等价)
|
||||
|
||||
> `next/`已被用户否决。本矩阵不得再作为页面可用性或视觉等价证明,权威冻结决定见
|
||||
> `../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
更新日期:2026-07-30
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 重建版发布候选清单
|
||||
# 重建版发布候选清单(已作废)
|
||||
|
||||
> **禁止部署。** 用户已于2026-07-30否决本实现,`xiaobai-next-rc-20260730-1`不再是有效发布候选。
|
||||
> 本文件仅保留历史记录,权威冻结决定见`../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
发布日期:2026-07-30
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 产品规格覆盖矩阵
|
||||
# 产品规格覆盖矩阵(历史记录,不能证明迁移等价)
|
||||
|
||||
> 本矩阵只证明被列出的新实现契约,不证明与原系统完整功能和视觉等价。`next/`已被用户否决,
|
||||
> 权威冻结决定见`../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
> 本文件记录第25节固定案例的当前直接证据。84个案例已由确定性测试或浏览器直接断言证明;`U04`
|
||||
> 的结构边界已自动验证,但4K信息密度仍需人工视觉验收,因此当前不得表述为“85/85完成”。
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# 减法与结构审计
|
||||
# 减法与结构审计(历史记录,不能作为成功指标)
|
||||
|
||||
> 用户验收确认代码量下降伴随了不可接受的产品偏差。本文件只保留作失败复盘,不得以行数减少
|
||||
> 证明迁移成功。权威冻结决定见`../../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
## 结论
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Portainer 网页端预检
|
||||
# Portainer 网页端预检(已作废,禁止执行)
|
||||
|
||||
> 用户已于2026-07-30否决`next/`实现。本流程及其中的Git标签、镜像标签和端口说明全部作废,
|
||||
> 不得在NAS或其他环境执行。权威冻结决定见`../../docs/migration/next失败冻结记录.md`。
|
||||
|
||||
本流程适用于不使用 SSH、通过 Portainer 管理 `192.168.200.11` Docker 的环境。
|
||||
它只在 `8876` 启动重建版,不停止、不修改现有 `8765` 容器,也不授权正式切换。
|
||||
|
||||
@@ -44,3 +44,19 @@ def test_portainer_preflight_is_pinned_to_the_release_candidate() -> None:
|
||||
assert "546c5af1a3010bbf0cf37e5d8b1a440fe6dfbfe80b471cddf430d4363a7b1a4a" in manifest
|
||||
for expected in ("用户 | 3", "自选 | 6", "选股归档 | 107", "策略跟踪 | 16"):
|
||||
assert expected in manifest
|
||||
|
||||
|
||||
def test_image_context_excludes_private_and_non_runtime_assets() -> None:
|
||||
ignored = {
|
||||
line.strip()
|
||||
for line in ROOT.joinpath(".dockerignore").read_text(encoding="utf-8").splitlines()
|
||||
if line.strip() and not line.lstrip().startswith("#")
|
||||
}
|
||||
assert {".git", ".venv", "data", ".env", "docs/evidence", "tests"} <= ignored
|
||||
|
||||
dockerfile = ROOT.joinpath("Dockerfile").read_text(encoding="utf-8")
|
||||
assert "COPY . " not in dockerfile
|
||||
assert "COPY backend/ ./backend/" in dockerfile
|
||||
assert "COPY config/ ./config/" in dockerfile
|
||||
assert "COPY tools/ ./tools/" in dockerfile
|
||||
assert "COPY --from=frontend-build /build/frontend/dist ./frontend/dist" in dockerfile
|
||||
|
||||
@@ -4779,10 +4779,11 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||
if parsed.path == "/api/auth/me":
|
||||
self.auth_me()
|
||||
return
|
||||
if parsed.path.startswith("/api/") and not self.require_auth():
|
||||
return
|
||||
if not self.require_access("GET", parsed.path):
|
||||
return
|
||||
if parsed.path.startswith("/api/"):
|
||||
if not self.require_auth():
|
||||
return
|
||||
if not self.require_access("GET", parsed.path):
|
||||
return
|
||||
if parsed.path == "/api/admin/settings":
|
||||
self.send_json(
|
||||
{"ok": True, **SERVICE.system_status(), "users": SERVICE.admin_users()}
|
||||
|
||||
@@ -281,6 +281,22 @@ class PublicKnowledgePermissionTests(unittest.TestCase):
|
||||
self.handler("/api/heaven/sector-phases/%E6%B2%B9%E6%B0%94", "send_json")
|
||||
)
|
||||
|
||||
def test_static_shell_bypasses_the_api_access_registry(self):
|
||||
handler = RequestHandler.__new__(RequestHandler)
|
||||
handler.path = "/"
|
||||
handler.require_auth = lambda: (_ for _ in ()).throw(
|
||||
AssertionError("static request required authentication")
|
||||
)
|
||||
handler.require_access = lambda *_: (_ for _ in ()).throw(
|
||||
AssertionError("static request entered the API registry")
|
||||
)
|
||||
served: list[str] = []
|
||||
handler.serve_static = served.append
|
||||
|
||||
RequestHandler.do_GET(handler)
|
||||
|
||||
self.assertEqual(served, ["/"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user