Files
crearte-monorepo/docs/plans/2026-09-30-hosted-submission.md

50 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P6 hosted 投稿(方案 A)· 实施计划
依据:`docs/specs/2026-09-30-hosted-submission-design.md`(D-A…D-F 定稿)。分支名统一 `feat/p6-hosted`,各仓各自实现者自拉自提交,**不 push**;合主由控制者 `--no-ff`。
## Task 1 · server 校验收紧(crearte-server)
基线 master(`ca24805` 起)。改动点:
1. `src/internal/service/content.go` `ValidateSubmission`(约 :327 起的 switch):
- `metadata_change` 分支:取现有 work 后新增不可变校验——`RuntimeOrDefault(p) != work.Runtime` → `ValidationError{Fields: []string{"runtime: immutable on metadata_change"}}`(D-B)。
- 通用(new_work 与 metadata_change 都过):`runtime == hosted && bundleUploadID != ""` → `ValidationError{Fields: []string{"bundle_upload_id: hosted works cannot carry a bundle"}}`(D-C)。
- `new_version` 分支已 virtual-only,不动。
2. 单测(同文件所在包 service):
- hosted+bundle → 校验失败且字段名精确;
- metadata_change 改 runtime(hosted↔external/virtual 双向至少各一)→ 失败;runtime 相同 → 通过既有路径;
- 回归确认:hosted new_work 无 bundle、带合法 https hostedUrl 仍通过(validate.go:140 既有)。
3. 集成测试(带 `TEST_DATABASE_URL` 的既有风格,参考 admin 面集成六场景文件):hosted 草稿→submit-review→approve→`works` 行 `hosted_url/play_origin/fallback` 读回一致;`GET /api/games/<user/slug>` 载荷含 `runtime:"hosted"` 与 `hostedUrl`。
4. `CHANGELOG.md` 中英成对,版本 **0.13.0**(Added=校验护栏+集成覆盖;Changed 若有措辞按实际)。
红线:零迁移、零新依赖、不动 handler 响应形状、不动 audit/admin 面、Approve 落库路径(PayloadToWork 映射已全,见 spec §1)不改。
验证(容器内,goproxy.cn 姿势同 AGENTS.md):`gofmt -l` 空、`go vet ./...`、`go build ./...`、`go test -p 1 ./internal/...`;带 db 的集成腿控制者跑,实现者确保无 `TEST_DATABASE_URL` 时 skip 语义与既有一致。
## Task 2 · crearte 前端表单打通
基线 master(`900f13a` 起),源码根 `crearte/src`。改动点:
1. 内容层类型:提交 payload runtime 联合扩为三档,`hostedUrl`、`fallback` 字段落位(对齐 server `WorkPayload` json 名 `hostedUrl`/`fallback`/`runtime`)。
2. `app/views/SubmitFormView.vue`:
- `:33` 表单 runtime 加 `'hosted'`;`:408-415` radio 组加第三项「自托管内嵌」(`data-testid="runtime-hosted"`)。
- hosted 档字段:`hostedUrl`(必填 https)、`fallback` 选择(`external|hosted|none`,默认 `external`);fallback=external 时 `url` 必填(前端校验镜像 server)。
- 提交形状:hosted 时 payload 带 `runtime:'hosted'` + `hostedUrl` + `fallback`,**不带** bundle/version/entry/features;`kind` 仅 new_work / metadata_change(new_version radio 保持 virtual-only 逻辑)。
- 删除 `:144-147` hosted 预填拒绝;预填回填 hostedUrl/fallback(注意 server GET 载荷字段名)。
- hosted 档下 cover 上传照常。
3. vitest(SubmitFormView.test.ts 等):hosted 提交形状、必填校验失败面、预填回填、new_version 禁入 hosted。
4. e2e:`admin-flow.spec.ts` 或提交流既有夹具内加 hosted 提交流(表单→draft payload 断言);**不动** `full-loop.spec.ts` / `playwright.stack.config.ts`。
5. `docs/CHANGELOG.md` 中英成对,版本 **0.19.0**。
红线:不动运行时三件套(sw/agent/bootstrap/GameHost/useGameFrame——播放端零改动是 spec 决策);不动管理面;apiRepo 无新端点。
验证(`crearte/src`):`npx vitest run`、`npm run typecheck`、`npx playwright test e2e/admin-flow.spec.ts`、`npm run e2e` 全 RC=0。
## Task 3 · deploy 核证(控制者,非实现者任务)
生产/dev 主站响应头无 `frame-src` 限制即记录在案;若有则模板补丁+复验。
## 合主与验收(控制者)
双路独立审查(spec→代码逐条,PASS with notes 起)→ 六腿验收(spec §5)→ `--no-ff` 合主推送 → wrapper 记账(ROADMAP P6 行 + spec/plan 索引行 + CHANGELOG 0.2.7)→ 删分支。