Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/40-deployment/local-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pdm install --frozen-lockfile
pnpm install --frozen-lockfile
```

配置 `DATABASE_URL`、`PUBLIC_ORIGIN`、`S3_ENDPOINT_URL`、`S3_BUCKET` 和标准 AWS 凭据 `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`。启用插件文档托管时,另设 `DOCUMENTATION_ORIGIN_TEMPLATE`,例如本地的 `http://{snapshot}.docs.localhost`;模板必须把 32 位快照标识放在第一个 DNS label,使每份不可变快照拥有独立 origin。数据库必须是 PostgreSQL;远程连接默认验证 TLS,localhost 可以不启用 TLS。`PUBLIC_ORIGIN` 是 HTTPS origin,本地允许 localhost HTTP,不含路径。文档内容 origin 在生产必须使用 HTTPS;本地只允许 `.localhost`。文件配置是 dotenv 数据,不应当作 shell 脚本执行;应用从进程环境读取配置。
配置 `DATABASE_URL`、`PUBLIC_ORIGIN`、`S3_ENDPOINT_URL`、`S3_BUCKET` 和标准 AWS 凭据 `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`。启用插件文档托管时,另设 `DOCUMENTATION_ORIGIN_TEMPLATE`,例如本地的 `http://{snapshot}.docs.localhost`;模板必须把 32 位快照标识放在第一个 DNS label,可带固定前后缀,使每份不可变快照拥有独立 origin。数据库必须是 PostgreSQL;远程连接默认验证 TLS,localhost 可以不启用 TLS。`PUBLIC_ORIGIN` 是 HTTPS origin,本地允许 localhost HTTP,不含路径。文档内容 origin 在生产必须使用 HTTPS;本地只允许 `.localhost`。文件配置是 dotenv 数据,不应当作 shell 脚本执行;应用从进程环境读取配置。

生产内容域可以与管理站使用同一可注册域。这样部署时,作者提供的 HTML/JS 可能接收或干扰父域 Cookie;不得在共享父域设置敏感 Cookie。需要浏览器级站点隔离时,应改用独立可注册域,例如 `registry.example.com` 与 `{snapshot}.exampleusercontent.net`。域名应采用 ASCII/Punycode 配置。

Expand Down
2 changes: 1 addition & 1 deletion docs/40-deployment/production-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

`production.yml` 只接受精确 current-main SHA。`verify` 执行仓库检查和容器构建,不修改远程资源。`deploy` 在受保护 production 环境中,重新核验 main 后对已配置 app 向前迁移、配置数据库和单桶 S3 凭据、发布同一镜像,并验证 Heroku app origin。它不自动导入 D1、不改变域名、不创建示例数据,也不删除旧资源。

production 环境需要 `HEROKU_APP_NAME`、`S3_ENDPOINT_URL`、`S3_BUCKET`、`DOCUMENTATION_ORIGIN_TEMPLATE` variables,以及 `HEROKU_API_KEY`、`MIGRATION_DATABASE_URL`、`DATABASE_URL`、`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY` secrets。文档模板必须指向已经配置 wildcard DNS/TLS 的专用内容 origin。生产当前使用 `https://{snapshot}.docs.registry.inkcre.dev`;它与管理站同属 `inkcre.dev`,因此部署接受作者 HTML/JS 与管理站同站、可能接收或干扰父域 Cookie 的风险。`inkcre.dev` 下的服务不得设置可发送到该内容域的敏感父域 Cookie。首次配置保持既有 R2 桶,S3 token 仅授予该桶的对象读写。`MIGRATION_DATABASE_URL` 使用 `registry_owner`,仅交给迁移容器与可信角色配置命令;`DATABASE_URL` 使用同一数据库的普通 `registry_app` 角色和独立密码。迁移创建该角色及业务表授权,控制器设置密码后以 `web=1:eco` 启动应用。owner 连接与平台控制 token 不进入运行服务配置。数据库连接属于独立 Registry 项目,不复用 core-py 的数据库或发布生命周期。
production 环境需要 `HEROKU_APP_NAME`、`S3_ENDPOINT_URL`、`S3_BUCKET`、`DOCUMENTATION_ORIGIN_TEMPLATE` variables,以及 `HEROKU_API_KEY`、`MIGRATION_DATABASE_URL`、`DATABASE_URL`、`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY` secrets。文档模板必须指向已经配置 wildcard DNS/TLS 的专用内容 origin。生产当前使用 `https://registry-docs-{snapshot}.inkcre.dev`;每个不可变快照拥有独立 origin,并由 `*.inkcre.dev` DNS catch-all 与证书承载。服务只接受符合该模板的内容 host,其他落入 catch-all 的 host 返回 421。内容域与管理站同属 `inkcre.dev`,因此部署接受作者 HTML/JS 可能接收或干扰父域 Cookie 的风险;`inkcre.dev` 下的服务不得设置可发送到内容域的敏感父域 Cookie。首次配置保持既有 R2 桶,S3 token 仅授予该桶的对象读写。`MIGRATION_DATABASE_URL` 使用 `registry_owner`,仅交给迁移容器与可信角色配置命令;`DATABASE_URL` 使用同一数据库的普通 `registry_app` 角色和独立密码。迁移创建该角色及业务表授权,控制器设置密码后以 `web=1:eco` 启动应用。owner 连接与平台控制 token 不进入运行服务配置。数据库连接属于独立 Registry 项目,不复用 core-py 的数据库或发布生命周期。

Heroku 交付为 Uvicorn 设置 `FORWARDED_ALLOW_IPS=*`,由平台 HTTP 入口提供外部请求协议,补斜杠跳转保持 HTTPS。转发头不参与 namespace 授权或身份判断;认证仍由 publisher credential 决定。部署 smoke 同时检查 `/simple` 跳转到该 origin 的 HTTPS `/simple/`。

Expand Down
2 changes: 2 additions & 0 deletions scripts/check_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def check_content_sites() -> None:
("https://registry.example.com", "https://{snapshot}.exampleusercontent.net", True),
("https://registry.team.github.io", "https://{snapshot}.docs.team.github.io", True),
("https://registry.team.github.io", "https://{snapshot}.other.github.io", True),
("https://registry.example.com", "https://registry-docs-{snapshot}.example.com", True),
("https://registry.example.com", "https://docs.registry-{snapshot}.example.com", False),
("http://localhost", "http://{snapshot}.docs.localhost", True),
("https://registry.example.com", "http://{snapshot}.docs.localhost", False),
):
Expand Down
4 changes: 2 additions & 2 deletions src/inkcre_extension_registry/service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def from_env(cls) -> Settings:
)
if (
documentation_origin.count("{snapshot}") != 1
or not (content.hostname or "").startswith("{snapshot}.")
or "{snapshot}" not in (content.hostname or "").split(".", 1)[0]
or (content.scheme != "https" and not local_content)
or (local_content and not local_http)
or content.username is not None
Expand All @@ -119,7 +119,7 @@ def from_env(cls) -> Settings:
):
raise ValueError(
"DOCUMENTATION_ORIGIN_TEMPLATE must be a separate wildcard HTTPS origin "
"with a leading {snapshot} label"
"with {snapshot} in the leading label"
)
return cls(
database_url=os.environ["DATABASE_URL"],
Expand Down
Loading