# Project、Environment、Slot、Endpoint 与数据库

面向后端开发者解释 Project 托管运行资源与托管 PostgreSQL 产品之间的关系、归属和计费边界。

平台把“服务是什么”“服务部署到哪里”“使用哪份计算资源”“从哪里访问”“使用哪份数据”拆成不同资源。理解这些边界后，开发、测试和生产环境可以独立组合，而不需要复制服务或把配置写进制品。

## 五个核心概念

### Project：后端应用身份

Project 是后端应用唯一的产品身份，由项目服务保存源码和 Git 历史。Hosted Service 是平台提供的托管
能力，不是另一个需要创建、选择或计费的资源，也不存在与 Project 并列的 Hosted Service ID。

一个 Project 可以拥有多个 Environment，例如 `dev`、`test` 和 `prod`。

### Environment：服务环境

Environment 是 Project 的一套环境级配置和部署目标。它保存配置、密钥引用、可选的 Slot 引用、可选的逻辑数据库引用，以及当前部署。

Environment 本身不收费。创建 Environment 时可以暂不选择 Slot，也可以不绑定数据库；但真正部署运行前必须拥有可用的 Slot。

### Slot：托管槽位

Slot 是工作区购买或领取的计算资源单元，提供 CPU、内存和运行副本。免费赠送规格与付费基础规格分开维护，付费基础规格同时只发布一个；需要更多资源时，为指定 Slot 购买 CPU 或内存扩容，不再选择另一套容量档位 SKU。SKU、固定价格、容量计量项和单价都来自已审核目录，平台不会把具体 SKU 或价格写入购买、扩容或部署逻辑。多个 Project Environment 可以共享工作区中的计算资源，同一项目的 `dev`、`test` 等不同 Environment 也可以绑定同一个 Slot；进程、配置、端口、健康检查和路由始终按 Environment 隔离。

Slot 按月独立使用工作区积分结算。续费沿用原规格；已有 Slot 还可单独购买 CPU、内存容量扩展。购买新 Slot 会创建新的资源身份，容量扩展只改变目标 Slot 的运行配额，两者是独立订单和权益。Slot 不包含数据库，也不拥有数据库。

工作区可以幂等领取一个基础赠送 Slot，也可以重复购买多个独立的付费 Slot。基础赠送与付费购买使用同一个 Slot 资源模型；`acquisitionType` 记录取得方式，`slotTypeCode` 只记录规格目录项。已经存在基础赠送 Slot 不会阻止购买第二个 Slot。

CLI 中，`slot create`（兼容别名 `slot claim`）只负责领取基础赠送 Slot。购买流程先读取当前目录及积分价格，再使用返回的已发布 Offer UUID 从工作区共享积分余额中扣费。`skuCode` 是目录中的规格编码，不是购买接口身份：

```bash
baijimu hosted-service slot types <workspaceId>
baijimu hosted-service slot purchase <workspaceId> \
  --offer-id <publishedOfferUuid>

baijimu hosted-service slot quote <workspaceId> \
  --slot-id <slotId> \
  --target-cpu-millicores 500 \
  --target-memory-mib 1024

baijimu hosted-service slot upgrade <workspaceId> \
  --slot-id <slotId> \
  --target-cpu-millicores 500 \
  --target-memory-mib 1024 \
  --yes
```

`slot purchase` 会同步返回扣除的积分和扣费后的余额，不需要扫码支付。网络异常后重试时可以复用同一个 `--idempotency-key <UUID>`，避免重复扣积分。新购时不要传已有 Slot ID；只有续费已有付费 Slot 时才增加 `--renew-slot-id <slotId>`。扣费成功后，新购 Slot 自动激活并出现在 Slot 列表中。

`slot quote` 按已有 Slot 和最终目标 CPU/内存查询服务端实时积分报价，不创建订单、不扣积分。`slot upgrade` 使用相同的最终目标参数并要求 `--yes` 确认，服务端会在同一次下单中重新计价；它不创建新 Slot，也不接收支付渠道。CPU 与内存可以只指定需要调整的一项，但目标值表示升级后的最终规格，不是本次增加的差额。

### Endpoint：服务端点

Endpoint 是某次环境部署对外或对内提供的稳定访问入口。端点把域名、路径、端口和当前运行版本连接起来。更换 Artifact 或重新部署时，Endpoint 可以保持稳定。

### 共享测试数据库、Database Instance 与 Database Profile

开发和测试可以通过数据库服务的 `createSharedTestDatabase` 申请共享测试数据库。这个方法直接创建可绑定的
Database Profile（Logical Database），返回 `profileRef`，不需要先购买独享实例。
共享测试数据库只用于开发和测试；当前可用性、配额和生命周期限制以工作区 Runtime 的方法定义为准。

Database Instance 是工作区购买的托管 PostgreSQL 实例，也是使用工作区积分结算的收费资源。首版以阿里云 RDS PostgreSQL 15 为基线。

一个 Database Instance 可以创建多个 Database Profile。对开发者而言，一个 Database Profile 就是一个
可绑定的 Logical Database（逻辑数据库）：创建 Profile 会在选定的 Database Instance 中同时创建逻辑库
及其 Allocation，并返回该逻辑库独立的数据库名、账号凭据和 `profileRef`。CLI 中
`baijimu db-profile create` 完成的就是这一个动作，不存在“先选择 Profile，再创建 Logical Database 和
Allocation”的第二套申请流程。

`profileRef` 是 Hosted Service 配置绑定使用的稳定引用；当前数据库 Provider 返回的形式为
`db-allocation:<id>`。其中 Allocation 是 Database Profile 的内部资源记录，不是开发者还要单独创建的
产品资源。创建 Database Profile 和把它绑定到 Environment 都不单独收费，费用由所属 Database Instance
的规格和周期决定。

## 资源关系

- Workspace
  - Project
    - Environment：dev，可选引用 Slot 和 Database Profile
    - Environment：prod，可选引用 Slot 和 Database Profile
  - 共享测试 Database Profile（开发和测试）
  - Database Instance（付费）
    - Database Profile A（一个 Logical Database Allocation，免费创建）
    - Database Profile B（一个 Logical Database Allocation，免费创建）

Environment 通过 `profileRef` 引用 Database Profile，而不是直接引用数据库实例。多个 Database Profile
可以位于同一个实例中，因此开发者可以按隔离要求选择“共享实例、不同逻辑数据库”，也可以购买独立实例。

## 计费边界

| 资源                                 | 是否收费 | 说明                                  |
| ---------------------------------- | ---- | ----------------------------------- |
| Project                            | 否    | 后端应用的源码与部署身份                        |
| Environment                        | 否    | 环境配置、部署和资源引用                        |
| Slot                               | 是    | 计算规格，按周期收费                          |
| Endpoint                           | 否    | 随环境部署管理，不作为独立商品                     |
| 共享测试 Database Profile              | 否    | 供开发和测试使用；可用性与配额以当前方法定义为准            |
| Database Instance                  | 是    | PostgreSQL 计算与存储规格，按周期收费            |
| Database Profile（Logical Database） | 否    | 创建逻辑库及其 Allocation，使用所属实例容量         |
| Environment 数据库绑定                  | 否    | 只保存 Database Profile 的 `profileRef` |

平台商品统一从工作区共享积分余额扣费。Slot 新购、续期和容量扩展，以及 Database Instance 新购、续费和变配，都只接受已发布的 `POINT` 价格。支付宝、微信等人民币渠道仅用于给工作区充值积分，不直接创建商品订单；提现和第三方资金账户仍按其独立的人民币资金规则处理。

## PostgreSQL 可购规格

平台只开放当前产品目录中已激活且已发布 POINT 价格的规格，不允许用户直接提交任意云厂商规格代码。规格、价格、可用地域和可用区都属于可变化的目录事实；购买前必须实时查询，不能从示例、历史订单或客户端内置列表推断。

规格的 CPU、内存、连接数和可用存储范围以[阿里云 RDS PostgreSQL 主实例规格目录](https://help.aliyun.com/zh/rds/apsaradb-rds-for-postgresql/primary-apsaradb-rds-for-postgresql-instance-types)为基线；实例创建由平台通过[阿里云 CreateDBInstance API](https://help.aliyun.com/zh/rds/developer-reference/api-rds-2014-08-15-createdbinstance)完成。实际可购性还取决于平台当前目录和默认部署位置。

规格代码是不可变版本。实例支持按当前 SKU 续费，也支持目录允许的升配关系；续费或升配按目标 SKU 的已发布积分价格结算，扣费成功后由平台调用 RDS 变配能力。历史订单继续保存购买时的规格和价格快照。

积分售价不写死在数据库服务、客户端或模块方法中。管理员在 factory-list 的“计费中心 → 积分商品价格”创建调价草稿，提交后由另一位管理员审核发布。计量型容量价格也必须进入 POINT 价格簿。新价格按生效时间切换，历史价格和订单不会被覆盖。

## 数据库供应商和部署位置

用户购买 Database Instance 时不选择云厂商、地域、VPC、子网或可用区。平台管理员在数据库服务中维护可用的 Database Provider、Placement 和供应商规格映射，并指定当前默认 Placement。首版默认 Provider 是阿里云 RDS。

Placement 是 db-service 所属运行环境内的运维目录数据，包含地域、网络、子网、可选可用区以及云凭据引用；它不是 Project Environment 的属性，也不属于 Kubernetes 集群配置。云凭据明文保存在 db-service 的密钥配置中，数据库只保存非敏感的凭据引用。

订单预留时会冻结 Provider、Placement 和供应商规格快照。因此，管理员切换默认 Placement 后，只有新购实例使用新的部署位置；已有实例、待结算订单和历史订单不会被静默迁移。新增已支持 Provider 的地域、网络或规格映射只更新数据库目录，不要求重新发布平台。

## 推荐使用流程

1. 开发和测试可以先用 `createSharedTestDatabase` 创建共享测试 Database Profile；需要独享实例时，再在“数据库服务”读取当前已发布的规格和积分价格并购买 Database Instance。购买请求必须携带 UUID 幂等键，网络异常重试时复用同一个键。
2. 等待实例状态从 `PROVISIONING` 变为 `ACTIVE`。
3. 在实例中创建一个或多个 Database Profile；每个 Profile 会创建一个 Logical Database Allocation，消费者使用返回的 `profileRef` 建立绑定。
4. 到期前按原 SKU 续费，或在同一系列内选择更高 SKU 升配；变配不会改变已有逻辑数据库引用。
5. 领取工作区基础 Slot，或从已发布目录购买一个新的独立付费 Slot；需要更多 Slot 时可以重复购买。
6. 为 Project 创建 Environment，可先不绑定 Slot 和数据库。
7. 在需要运行时为 Environment 选择 Slot；需要持久化数据时用 `profileRef` 绑定一个 Database Profile。
8. 构建 Artifact、部署到 Environment，并通过 Endpoint 验证业务。

没有消费者或令牌不代表 Environment 已停止。临时释放运行资源时使用 `stop`：

```bash
baijimu hosted-service env stop <workspaceId> \
  --environment-id <environmentId> \
  --yes
```

停止会从共享 Slot revision 移除目标进程、终止运行资源、移除路由并解除 Slot 绑定，但保留环境、
配置、Secret、消费者、token 和逻辑数据库 Allocation。重新分配 Slot 并部署后即可恢复运行。

环境永久不再使用时，显式退役：

```bash
baijimu hosted-service env retire <workspaceId> \
  --environment-id <environmentId> \
  --yes
```

退役会撤销该环境的 token、停止运行资源、移除路由并软删除环境；如果同一 Slot 还有其他 Environment，平台会
先生成不包含目标环境的完整 Slot revision，不会停止其他环境。逻辑数据库 Allocation 独立保留，
如需销毁数据，必须再通过数据库产品的释放流程处理。

不要把数据库连接串或密码 写进源码、Artifact 或普通环境 JSON。Hosted Service 能力会在部署阶段通过配置 Provider 解析绑定。数据库结构或数据变更必须通过与运行制品同源的
[数据库迁移 Artifact](/development/backend-development/database-migrations/)执行，不能由 Module 或 Bundle 声明。

基础能力申请、Runtime 发现和 Resource Binding 的通用流程见
[基础能力与 Resource Binding](/features/resource-bindings/)。
