---
name: tling-app-publisher
description: 使用用户提供的一次性连接码，将静态 HTML 应用发布到图羚应用平台。
metadata:
  version: "2026-09-06"
---

# 发布应用到图羚应用平台

仅当用户明确要求把当前项目发布到图羚时，才使用本流程。

## 安全规则

- 请用户提供短期有效的 `tlc_...` 一次性连接码。不得索要用户的账号密码、短信验证码、实名材料、Admin 密钥、长期凭据或其他长期秘密。
- 上传前，向用户说明应用名称以及本次会包含哪些文件。新应用的免费网址由平台随机分配，不要要求用户命名域名或 slug。
- MVP 阶段只发布静态前端文件。ZIP 包根目录必须包含 `index.html`。
- 不得把 `.env` 文件、私钥、访问令牌、包含秘密信息或凭据的源映射文件、实名材料放入 ZIP 包。
- 将接口返回的 `tlp_...` 令牌视为秘密。它只能用于当前任务，不得输出到日志，也不得提交到项目代码中。

## 连接平台

用户会提供平台基础地址和一次性连接码。使用以下请求兑换一次：

```http
POST /api/agent/v1/pairings/exchange
Content-Type: application/json

{"code":"tlc_USER_PROVIDED_CODE"}
```

响应中包含 `api_base_url`、`public_app_url_template`、`runtime_origin_template` 和短期有效的 `token`。后续请求都应通过 `X-Tling-Api-Key` 请求头携带该令牌。新建应用时应优先直接使用创建响应中的 `public_url`。兼容旧应用时，才用应用 slug 替换 `public_app_url_template` 中的 `{app}`；不得自行猜测端口或域名。`runtime_origin_template` 是隔离加载用户 HTML 的运行源，只用于应用自身回调和技术核对，不应作为首选分享链接。

## 发布流程

1. 调用 `GET /api/platform/v1/apps` 获取应用列表。
2. 如果已有应用与待发布项目匹配，继续使用该应用。如果不存在，调用 `POST /api/platform/v1/apps`，由平台分配 slug 和公开地址，请求体如下：

```json
{
  "name": "我的应用",
  "runtime_kind": "static",
  "visibility": "public",
  "identity_mode": "platform"
}
```

3. 创建 ZIP 包，并确保根目录包含 `index.html`。排除依赖缓存、版本控制数据、本地数据库、环境配置文件和任何秘密信息。
4. 将 ZIP 包作为 multipart 表单字段 `archive`，上传到 `POST /api/platform/v1/apps/{app_id}/deployments/static`。
5. 调用 `GET /api/platform/v1/apps/{app_id}`，读取平台分配的活动运行域名并核对其状态。面向用户的完整访问网址优先使用第 2 步创建响应中的 `public_url`。
6. 调用 `GET /api/platform/v1/apps/{app_id}/deployments`，确认新生成的不可变版本及其 SHA-256 摘要。
7. 告诉用户平台分配的网址、版本号和上传结果。如果该工作空间尚未通过实名审核，应明确说明：版本已经保存，但在审核通过前，公网运行地址仍不可访问。

## 异常处理

- `401/403`：连接令牌无效、已过期、已撤销或缺少所需 scope（权限范围）。请用户重新生成一次性连接码。
- `404`：不得猜测 ID；重新获取用户的应用列表。
- `409`：系统暂时无法分配唯一地址，或当前操作与系统状态冲突。不要自行改成用户指定 slug；安全地重试一次，再失败则告知用户。
- `422`：检查接口返回的校验信息，安全地重新生成 ZIP 包；说明需要修改的内容后再重试。
- 不得使用或探测任何 Admin API 接口。
