# Deployment Guide

This guide covers the canonical Cloudflare Pages deployment for `word-editor`.

## Canonical Deployment

```text
Product: word-editor
Cloudflare Pages project: docx-editor
Production origin: https://docx-editor.pages.dev
Custom production domain: https://word.flyfish.dev
Output directory: cloudflare-pages-dist
Cloudflare production branch: main
Git source branch: master
```

## Build Pipeline

Issue and validate the public runtime license in the release branch first, then commit every intended release change:

```bash
npm ci
npm run license:issue-root
npm run test:release-security
git add office-preview-license.json auth/word-editor-license-public-keys.json
git commit
```

Do not run `build:cloudflare` between license issuance and the release commit while the signing checkout is dirty. After committing, create a fresh worktree at that exact release SHA and build the candidate there:

```bash
release_sha="$(git rev-parse HEAD)"
git worktree add --detach /tmp/word-editor-release "$release_sha"
cd /tmp/word-editor-release
npm ci
npm run build:cloudflare
```

The builder fails closed unless the source is the exact committed release in a clean Git worktree. This guarantees the runtime artifact and its bundled corresponding-source archive share one commit identity.

`npm run build:cloudflare` performs these steps:

1. Rebuilds `packages/word-editor/dist`.
2. Copies only runtime files into `cloudflare-pages-dist`.
3. Verifies and copies the ES256 runtime license and public-key gate.
4. Writes `_headers`, `_redirects`, and `word-editor-release.json`.
5. Minifies and mangles JavaScript with Terser.
6. Excludes source maps, TypeScript source files, and `.d.ts` files from the Pages artifact.

## Deploy

Create the Pages project once if it does not exist:

```bash
npm --userconfig=/dev/null exec --yes --package=wrangler@4.101.0 -- \
  wrangler pages project create docx-editor --production-branch main
```

Deploy:

```bash
npm run deploy:cloudflare
```

`deploy:cloudflare` never rebuilds. Run it only after verifying the exact `cloudflare-pages-dist/` directory; this prevents a second randomized sealed payload from replacing the tested artifact.

When publishing the custom Pages domain, issue the runtime license with both the canonical Pages origin and the custom origin before building:

```bash
WORD_EDITOR_LICENSE_EXTRA_ORIGINS=https://word.flyfish.dev npm run license:issue-root
```

The external DNS provider must then create `CNAME word -> docx-editor.pages.dev` after the domain is associated with the Pages project.

## Post-Deploy Verification

```bash
curl -I -L https://docx-editor.pages.dev/
curl -I https://docx-editor.pages.dev/wasm/word-editor-runtime-core.wasm
curl -sS https://docx-editor.pages.dev/word-editor-release.json
curl -sS https://docx-editor.pages.dev/source/index.json
curl -fLO https://docx-editor.pages.dev/source/current.tar.gz
curl -fLO https://docx-editor.pages.dev/source/current.tar.gz.sha256
shasum -a 256 -c current.tar.gz.sha256
```

Expected checks:

- `/` returns the product landing page with HTTP 200.
- `/app` redirects to `/examples/demo/`.
- `word-editor-runtime-core.wasm` returns `Content-Type: application/wasm`.
- `word-editor-release.json` reports `licenseAlgorithm: ES256`.
- `word-editor-release.json` reports `deployOrigin: https://docx-editor.pages.dev`.
- `sourceUrl` and `sourceSha256Url` use the same-origin `/source/current.tar.gz` endpoints.
- `/source/index.json` identifies the same commit and SHA-256 as `word-editor-release.json`.
- `sourceMapsPublished` is `false`.
- `sourceTypeDeclarationsPublished` is `false`.
- `javascriptObfuscation` is enabled.

## Local Release Smoke Test

```bash
npm run build:cloudflare
cd cloudflare-pages-dist
python3 -m http.server 8788
```

Open:

```text
http://127.0.0.1:8788/examples/demo/?fontGateway=0&docx=../../test-fixtures/docx/simple.docx&demoToast=1
```

The runtime license allows `127.0.0.1:*` and `localhost:*` for local verification.

---

# 部署指南

本文档说明 `word-editor` 的标准 Cloudflare Pages 部署。

## 标准部署信息

```text
产品名：word-editor
Cloudflare Pages 项目：docx-editor
生产域名：https://docx-editor.pages.dev
自定义生产域名：https://word.flyfish.dev
输出目录：cloudflare-pages-dist
Cloudflare 生产分支：main
Git 源码分支：master
```

## 构建流程

先在发布分支签发并验证公开运行授权，然后提交本次发布的全部变更：

```bash
npm ci
npm run license:issue-root
npm run test:release-security
git add office-preview-license.json auth/word-editor-license-public-keys.json
git commit
```

不要在授权签发完成但尚未提交的脏工作区运行 `build:cloudflare`。提交后，应基于该发布 SHA 创建全新的 worktree，再构建候选产物：

```bash
release_sha="$(git rev-parse HEAD)"
git worktree add --detach /tmp/word-editor-release "$release_sha"
cd /tmp/word-editor-release
npm ci
npm run build:cloudflare
```

构建器会在源码不是已提交发布版本或 Git worktree 不干净时失败，从而保证运行时产物和随包发布的对应源码归属于同一个 commit。

`npm run build:cloudflare` 会执行：

1. 重建 `packages/word-editor/dist`。
2. 只复制运行所需文件到 `cloudflare-pages-dist`。
3. 验证并复制 ES256 运行授权和公钥门禁。
4. 写入 `_headers`、`_redirects` 和 `word-editor-release.json`。
5. 使用 Terser 压缩混淆 JavaScript。
6. 发布目录不包含 source map、TypeScript 源码或 `.d.ts` 文件。

## 发布

如果 Pages 项目不存在，先创建一次：

```bash
npm --userconfig=/dev/null exec --yes --package=wrangler@4.101.0 -- \
  wrangler pages project create docx-editor --production-branch main
```

发布：

```bash
npm run deploy:cloudflare
```

`deploy:cloudflare` 不会再次构建。只有在验证当前 `cloudflare-pages-dist/` 后才能运行，避免第二次随机密封 payload 替换已经测试的产物。

发布自定义 Pages 域名时，必须在构建前同时为标准 Pages 域名和自定义域名签发运行授权：

```bash
WORD_EDITOR_LICENSE_EXTRA_ORIGINS=https://word.flyfish.dev npm run license:issue-root
```

然后在外部 DNS 服务商处将 `word` 的 `CNAME` 指向 `docx-editor.pages.dev`。自定义域名必须先在 Pages 项目中完成关联。

## 发布后验证

```bash
curl -I -L https://docx-editor.pages.dev/
curl -I https://docx-editor.pages.dev/wasm/word-editor-runtime-core.wasm
curl -sS https://docx-editor.pages.dev/word-editor-release.json
curl -sS https://docx-editor.pages.dev/source/index.json
curl -fLO https://docx-editor.pages.dev/source/current.tar.gz
curl -fLO https://docx-editor.pages.dev/source/current.tar.gz.sha256
shasum -a 256 -c current.tar.gz.sha256
```

预期：

- `/` 以 HTTP 200 返回产品首页。
- `/app` 跳转到 `/examples/demo/`。
- `word-editor-runtime-core.wasm` 返回 `Content-Type: application/wasm`。
- `word-editor-release.json` 中 `licenseAlgorithm` 为 `ES256`。
- `word-editor-release.json` 中 `deployOrigin` 为 `https://docx-editor.pages.dev`。
- `sourceUrl` 和 `sourceSha256Url` 使用同源 `/source/current.tar.gz` 地址。
- `/source/index.json` 与 `word-editor-release.json` 中的 commit 和 SHA-256 完全一致。
- `sourceMapsPublished` 为 `false`。
- `sourceTypeDeclarationsPublished` 为 `false`。
- `javascriptObfuscation` 已启用。

## 本地发布包烟测

```bash
npm run build:cloudflare
cd cloudflare-pages-dist
python3 -m http.server 8788
```

打开：

```text
http://127.0.0.1:8788/examples/demo/?fontGateway=0&docx=../../test-fixtures/docx/simple.docx&demoToast=1
```

运行授权包含 `127.0.0.1:*` 和 `localhost:*`，可用于本地验证。
