@aipt/idp-deploy
v0.1.35
Published
IDP 私有化部署、外部配置、备份恢复与交付编排 CLI。
Readme
@aipt/idp-deploy (idpctl)
IDP 本地容器服务编排与部署控制面:负责工作区本地依赖(PostgreSQL / Redis 等)启停、本地 Docker 运行与 Kubernetes/GitOps 声明式发布。
0. 首次本地化初始化与场景入口
初始化 Sources 环境(如 $HOME/works/sources),绑定 IDP_CONFIG_DIR、APP_CONFIG_DIR 与 IDP_GITOPS_ROOT,并通过 idp-setup 接入工具链:
# 初始化环境与全局 CLI 套件
corepack pnpm dlx @aipt/idp-setup init --root <Sources根>
source <Sources根>/config/idp/generated/sources.env
# 项目接入与开发就绪
cd <项目>
idp-setup bootstrap核心使用场景与场景入口
1. 工作区本地基础服务管理(PostgreSQL / Redis / 队列等)
解决本地业务开发依赖的数据库与缓存一键启停:
cd <工作区>
# 启动本地开发依赖服务
idpctl workspace dev up
# 查看运行状态与连接信息
idpctl workspace dev status
# 查看服务容器实时日志
idpctl workspace dev logs
# 停止本地依赖服务
idpctl workspace dev down2. 工作区 / 业务应用 Docker 容器化运行
解决在本地使用 Docker 模拟完整容器化环境运行:
cd <工作区>
# 启动工作区全量应用 Docker
idpctl workspace docker up
# 单应用本地容器化运行
idpctl local app up --project <项目>
idpctl local app logs --project <项目>
idpctl local app down --project <项目>3. Kubernetes / GitOps 声明式部署
解决云端环境基于不可变 Plan 与 ComponentContract 的确定性渲染与发布:
# 生成不可变部署计划
idpctl gitops app plan-create --component-contract <组件契约文件>
# 审批并应用发布
idpctl gitops app plan-apply --approve <PlanId>
# 验证发布状态
idpctl gitops app plan-verify --approve <PlanId>4. 平台与部署健康诊断
解决检查本地 Docker、网络、基座服务与部署版本状态:
# 查看发布与部署状态
idpctl release status
# 诊断基座与部署环境
idpctl doctor foundation常用命令速查
| 命令 | 解决的问题 / 使用场景 |
|---|---|
| idpctl workspace dev up\|down\|status\|logs | 工作区本地依赖服务(PG/Redis)启停与状态 |
| idpctl workspace docker up\|down\|status\|logs | 工作区全量 Docker 容器化环境启停 |
| idpctl local app up\|down\|status\|logs | 单个业务应用本地容器化运行 |
| idpctl gitops app plan-create\|apply\|verify | Kubernetes GitOps 声明式发布流水线 |
| idpctl release status | 查看当前已部署版本与发布状态 |
| idpctl doctor | 检查部署环境、容器与基座状态 |
5. 平台基座与 Profiles 说明
| Profile | 服务组成 | 典型用途 |
|---|---|---|
| registry | Verdaccio | 私有 npm 镜像制品库 |
| flow | Flow、Caddy | AI-native SDLC 编排与回环代理 |
| portal | PostgreSQL、Portal、Caddy | 开发者工作台控制门户 |
| tech-only | PostgreSQL、Tech、Caddy | 知识库与技术资产库 |
| foundation | PostgreSQL、Verdaccio、Tech、Caddy | 完整基础服务支撑面 |
| core / full | PostgreSQL、Registry、Tech、Flow、Portal、Caddy | 完整单机 IDP |
Bench 原有部署资产已按能力而非目录整体接收:受控运维语义由本仓 Kernel 承担,旧 Compose 只选择性重建为上述独立片段,cnpmcore 由 Verdaccio 替代;未出现真实 Binding 与批准目标环境的实验中间件、GitOps 和 Terraform 保持延后,不进入默认 Profile。机器可读决策与物理归档门禁见 governance/asset-lifecycle.v1.json。
新项目本地 Docker 部署(不推送 ACR)
development/local 可以使用项目自己的 deploy/compose.local.yaml 直接在本机完成受控构建和部署,不执行 Buildx、不推送远程 ACR、不写 GitOps。该模式固定标记为 local-source、promotable: false;进入 test/production 时仍须从可追溯 Git revision 构建并锁定 amd64/arm64 OCI Index digest。
前置条件:项目已经由 Dyyto Apply/Verify,并包含 project-capabilities.json、config/application-config.json、Dockerfile、deploy/compose.local.yaml 和健康检查。真实配置只位于仓库外 Config Dir。
export IDP_DEPLOY_ROOT="$SOURCES_ROOT/spaces/idp-deploy"
export APPLICATION_ROOT=/absolute/path/to/new-project
export IDP_CONFIG_DIR=/absolute/company/idp/config
export APP_CONFIG_DIR=/absolute/company/app/config
# 1. 根据Dyyto ApplicationConfigContract创建应用.env、secrets/和certs/;重入不覆盖已有值。
idpctl app config-prepare \
--project "$APPLICATION_ROOT" \
--environment local \
--preset local
# 2. 填写命令不能代替外部系统签发的required Secret;不要把值写入项目。
chmod 600 "$APP_CONFIG_DIR/<application-id>/local/secrets/"*
# 3. 生成不可变Local DeploymentPlan;本步只执行docker compose config和安全检查。
idpctl local app plan \
--project "$APPLICATION_ROOT" \
--compose-file "$APPLICATION_ROOT/deploy/compose.local.yaml" \
--output "$APP_CONFIG_DIR/<application-id>/local/plans/local-applications/<application-id>-local.json"
# 4. 审查Plan中的项目、输入摘要、Compose摘要和promotable:false后执行。
idpctl local app apply \
--plan "$APP_CONFIG_DIR/<application-id>/local/plans/local-applications/<application-id>-local.json"
# 5. 随时重新核验精确Plan与容器健康状态。
idpctl local app verify \
--plan "$APP_CONFIG_DIR/<application-id>/local/plans/local-applications/<application-id>-local.json"代码、Dockerfile、Compose、.env 或任一 *_FILE 发生变化后,旧 Plan 会 fail-closed;删除旧 Plan 文件并用新的输出文件名重新 plan、审查和 apply。停止保留容器,移除不删除 Volume:
idpctl local app stop \
--plan "$IDP_CONFIG_DIR/plans/local-applications/<application-id>-local.json" \
--config-dir "$IDP_CONFIG_DIR"
idpctl local app remove \
--plan "$IDP_CONFIG_DIR/plans/local-applications/<application-id>-local.json" \
--confirm <application-id> \
--config-dir "$IDP_CONFIG_DIR"Compose 安全门禁拒绝 privileged、host network、Docker Socket、cap_add、设备直通、显式 container_name、非回环发布端口、项目外绝对 bind mount、项目 Compose Secret 和敏感环境变量字面量;至少一个服务必须提供 healthcheck。应用应原生读取 *_FILE,Compose 不负责把 Secret 展开成环境变量。
数据库只接入内部 Docker 网络;Registry 默认只绑定宿主机 127.0.0.1:4873;Web 入口默认只绑定 127.0.0.1:8080。HTTP 是初始模式,TLS 可以通过配置开关启用。
IDP 平台本地源码部署(不走企业 OCI Registry)
开发机要运行当前 Tech、Workbench、Flow、Portal 源码时,使用 local platform,不要使用 release deploy。前者直接构建当前宿主平台镜像,固定 --pull never 启动,不要求 docker login、Buildx 或 IDP_OCI_REPOSITORY_ROOT;后者用于构建并推送可提升的双平台企业 Release。
export SOURCES_ROOT="$HOME/works/sources"
source "$SOURCES_ROOT/config/idp/generated/sources.env"
idpctl local platform up core \
--sources-root "$SOURCES_ROOT/spaces"
idpctl local platform status
idpctl release status --jsonup 是正式 Plan → Apply → Verify → Evidence 一键入口。它不会修改 .env 或 images.lock.json,本地镜像使用 dyyto-idp-local/... 内容身份并标记为不可提升;release status 会把当前运行态报告为 local-source,并在 currentDeployment 中给出实际运行的本地镜像,最近一次正式 Release 只作为历史参考。Docker 构建在缺少基础镜像或依赖缓存时仍可能访问其原始公共 Registry,但不会访问、拉取或推送企业 OCI Registry。
需要人工审查 Plan 时可拆开执行:
PLAN="$IDP_RUNTIME_DIR/plans/local-platform/core-local.json"
idpctl local platform plan core \
--sources-root "$SOURCES_ROOT/spaces" \
--output "$PLAN"
idpctl local platform apply --plan "$PLAN"
idpctl local platform verify --plan "$PLAN"源码、Config、Dockerfile、Compose、构建合同或活动运行态在 Plan 后变化时,Apply 会在构建或切换前失败关闭。已有运行态会先完成备份、校验和隔离恢复演练;后续失败按 Preimage/CAS 恢复原运行态与 Binding。停止和移除均保留 Volume 与本地镜像缓存:
idpctl local platform stop --plan "$PLAN"
idpctl local platform remove --plan "$PLAN" --confirm <instance-id>默认一键发布与部署
要求 Node.js 20+、Docker Engine 20.10+、Docker Compose v2 和 Buildx。Tech、Flow、Portal 源码仓库应与 idp-deploy 位于同一父目录;真实配置、Secret、证书、数据和发布证据全部位于仓库外。
企业 OCI 仓库根作为非敏感发布事实固定在 release/defaults.v1.json。部署机只需预先指定仓库外 Config Dir、登录该 Registry,然后运行脚本;初始化、Secret 生成、镜像构建、推送、digest 锁定和部署均由脚本完成:
export IDP_CONFIG_DIR=/absolute/company/idp/config
docker login idp-registry.cn-shanghai.cr.aliyuncs.com
./deploy.sh日常发布同样只需重新登录并执行一个命令:
docker login idp-registry.cn-shanghai.cr.aliyuncs.com
./deploy.sh异地或临时 Registry 可通过仓库外 .env 的 IDP_OCI_REPOSITORY_ROOT 或 --oci-repository-root 显式覆盖默认值;脚本不会读取或复制 Docker 凭据文件。config init 与 config generate-secrets 仍可单独用于排障,但不再是发布前置人工步骤。config init 会补齐根/组件 .env 及当前声明的 *_FILE 文件,已有文件和值不会被覆盖,升级新增键前会保存 .env Preimage。
deploy.sh 默认为 foundation;它只转发到与 CLI/AI 共用的 Kernel。等价命令是:
idpctl release deploy foundation
idpctl release deploy foundation --version 0.1.2部署后通过同一控制面查询当前真实版本,不需要翻找 Docker 标签或回执目录:
idpctl release status --json默认查询当前活动 Profile;显式 Profile 查询它最后一次成功发行。结果会区分 active、unverified、drifted、stopped、inactive、untracked 和 not-deployed,并返回版本、完整 releaseTag、活动状态、健康验证和证据摘要。命令全程只读,不访问 Docker 或 Registry。
命令使用 release/defaults.v1.json 中固定的第三方 OCI digest 和 Tech Node 基础镜像,以确定性源码摘要生成统一 tag,例如 0.1.2-r0123456789ab。自研镜像映射固定为:
<IDP_OCI_REPOSITORY_ROOT>:<统一releaseTag>
<IDP_OCI_REPOSITORY_ROOT>/flow:<统一releaseTag>
<IDP_OCI_REPOSITORY_ROOT>/portal:<统一releaseTag>全部当前 Profile 所需自研镜像必须先完成 linux/amd64,linux/arm64 Buildx push,并核对 Buildx metadata 与远端 OCI Index digest,之后才会修改 .env。同一 Config Dir 重入会复用已验证 Artifact;换到 Mac M4 等新机器时,若远端 tag 的 amd64、arm64 镜像都携带与当前版本、组件、源码摘要和不可变 Plan 完全一致的发布标识,脚本会生成本机 Registry 收养证据并复用精确 OCI Index digest,不会重复构建。缺少标识、重复应用平台 Manifest 或任一平台不一致时仍会拒绝复用和覆盖。企业 OCI 仓库必须启用 tag 不可变策略并限制推送权限;这些标识用于跨机确定性核对,不替代 Registry 权限、不可变 tag 或后续可选的签名证明。Build、备份、镜像锁定、pull、switch、verify、bindings sync 与最终回执都持有同一个显式实例 Lease,其他 idpctl 写操作不能插入事务阶段。
Docker Desktop 的 BuildKit 若经宿主代理推送大 Layer 超时,可显式启用“宿主 OCI Layout + ORAS 单并发”回退。该能力默认关闭,且不会下载工具、创建 Builder、切换当前 Builder 或执行 bootstrap。先由企业软件供应链把已批准 ORAS 二进制放入 Config Dir,使用发布方签名或官方 checksum 在平台流程外完成来源核验,再固定本机文件摘要和精确版本:
idpctl config init
# 由企业批准流程安装,不要由部署脚本联网下载。
install -m 0500 <approved-oras-binary> "$IDP_CONFIG_DIR/tools/oras/oras"Builder 也由宿主供应流程预先建好,正式白名单是 docker-container、kubernetes 或 remote driver。当前 Docker Desktop 的 desktop-linux/docker driver 在 containerd image store 上虽有本机 OCI Layout 实测成功证据,但该行为不是可跨版本/context/image store 复现的官方可移植合同,因此发布器仍会拒绝 docker driver。若选择 docker-container,在部署脚本之外用企业批准的 BuildKit digest 创建并 bootstrap;不使用 --use,因为发布命令会显式选择 Builder:
docker buildx create \
--name idp-oci \
--driver docker-container \
--driver-opt 'image=<approved-buildkit-image@sha256:digest>'
docker buildx inspect --bootstrap idp-oci将官方核验后的值写入仓库外 $IDP_CONFIG_DIR/.env:
IDP_OCI_LAYOUT_ORAS_FALLBACK_ENABLED=true
IDP_OCI_LAYOUT_BUILDER=idp-oci
IDP_ORAS_BINARY_PATH=tools/oras/oras
IDP_ORAS_VERSION=1.3.0
IDP_ORAS_SHA256=sha256:<approved-64-hex-digest>开启后,发布器会在 Docker 构建前复验 Config Dir containment、普通单硬链接、owner-only 读/执行权限、文件大小、SHA-256 和 oras version,并仅用无 --bootstrap 的 docker buildx inspect <builder> 检查 driver、running nodes 与双平台联集。正常情况下仍优先走 Buildx 双平台 --push;开启回退时 direct push 和 Layout 导出都固定使用同一 --builder,只有前者进程失败且尚未进入配置 Apply 时,才以相同 Dockerfile/context、Build Args、Secret、四个发布标签、--provenance=mode=max 和固定 SBOM generator 导出仓库外临时 OCI Layout,再固定执行 oras cp --from-oci-layout ... --concurrency 1。发布器不向命令传入明文凭据,也不自行读取或复制 Docker 凭据配置,且不追加 --plain-http/--insecure;宿主必须已按企业流程登录目标 Registry,由 ORAS 的标准宿主凭据发现完成认证。ORAS 返回成功仍不被直接信任,远端 OCI Index digest、双平台数量和 labels 必须与 Layout metadata及不可变 Plan 完全一致,才会生成不含宿主路径和 Secret 的 Artifact。任一步失败都不修改镜像配置或切换运行态,metadata、临时 npmrc 和 Layout 必须清理完成。若当前 release 所有远端 tag 都可收养,则不执行 ORAS 版本探测、Builder inspect 或任何 Buildx 构建。
已有活动 Profile 更新时,脚本会在镜像 Apply 前自动创建备份、校验摘要并执行隔离恢复演练;foundation 分别生成 tech-only 与 registry 两个可独立恢复的 Generation。备份证据写入不可变 Deployment Plan 与最终回执。后续阶段失败时只在 .env 与 images.lock.json 仍等于本次 Apply 结果时恢复 Preimage,用户并发修改不会被覆盖;受管 Binding 使用独立 CAS 令牌恢复;已有活动 Profile 会恢复并重新验收,首次部署则停止本次启动的容器。若数据库迁移导致旧运行态无法重新通过验收,命令会返回 IDP_RELEASE_RECOVERY_REQUIRED 并给出已验证的备份 Generation ID,数据恢复仍需显式确认,不会因普通发布失败而静默覆盖生产数据。
release deploy core 会额外构建 Flow/Portal,并对 Portal 只执行受控的 yarn install --immutable、yarn tsc、yarn build:backend Prebuild。P0 不伪造 Dyyto/Bench 事实;Core 在发布前仍必须按本文正式流程导入两类 Snapshot,缺失时由 doctor core --require-configured fail-closed。
IDP_RUNTIME_PLATFORM 是当前宿主实际运行容器的平台:Intel 验证机使用 linux/amd64,Mac M4 使用 linux/arm64。它与镜像发布门禁是两类事实:为保证同一 Release 能先在 Intel 验证机预验收、再由 Mac M4 原生接收,镜像锁固定要求每个镜像同时包含 linux/amd64、linux/arm64,不能用单平台镜像、宿主仿真或修改运行平台绕过。
因此 Intel 验证机首次运行上面的一键命令会构建并推送双平台镜像;Mac M4 检出相同版本源码、使用相同 Profile 与 OCI 仓库根后,只需 docker login 并再次运行同一条 ./deploy.sh。脚本会核对 Registry 发布身份、收养已存在的 OCI Index,并按 arm64 原生运行,不需要复制 Intel 机器的 Secret 或整个 Config Dir。
images lock 已包含在一键入口中。它先解析同一个 OCI 引用的 linux/amd64、linux/arm64 Manifest,并要求两次解析得到同一个 Index digest;任一平台缺失、tag 在检查期间漂移或证据不一致时,会在任何配置写入前失败。成功后才在 $IDP_CONFIG_DIR/snapshots 保存 .env/旧锁 Preimage,并原子生成权限为 0600 的 images.lock.json v2,逐镜像记录原始引用、digest 固定引用和双平台证据。相同语义重复执行不会改写锁文件。单独运行 idpctl images lock 只用于高级诊断或旧锁迁移,不是正常发布步骤。
images.lock.json 是部署镜像事实,不是普通缓存。doctor --require-configured 会强制校验整体摘要、.env 一致性、双平台证据和当前 Profile 的必需镜像,不能只靠镜像字符串中存在 digest 就放行。旧版 v1 单平台锁会对普通 doctor/pull/up fail-closed;只有 release deploy 的升级事务可以在 Apply 前只读接受 v1,以便先完成旧运行态备份和隔离恢复演练。不要手工改锁或只替换 tag/digest,应以新 SemVer 执行 ./deploy.sh <profile> --version <new-semver>,由标准发布链重建双平台镜像、保存 Preimage 并迁移到 v2。
默认 ./deploy.sh 直接发布 foundation,同时启动 Registry 与 Tech。完整 core 需要 Dyyto Package Catalog 与 Bench Environment Snapshot 两类真实输入;这两类事实不由 idp-deploy 伪造。先完成默认发布,再按以下正式导出链准备 Snapshot,最后执行 ./deploy.sh core。各 Profile 使用同一实例名和数据根,不能并行当作多套环境;多环境必须使用不同的 IDP_CONFIG_DIR、IDP_INSTANCE_ID 和五个互不重叠的数据根。
# ./deploy.sh 已完成foundation部署、verify和bindings sync。
dyyto catalog export --output - | idpctl sources import dyyto --stdin
export BENCH_REPOSITORY_DIR=/absolute/path/to/bench
(
cd "$BENCH_REPOSITORY_DIR"
corepack pnpm --filter @bench/benchctl benchctl export environment \
--config-dir "$IDP_CONFIG_DIR" \
--environment private \
--output "$IDP_CONFIG_DIR/imports/bench-environment-snapshot.candidate.json"
)
idpctl sources import bench \
--file "$IDP_CONFIG_DIR/imports/bench-environment-snapshot.candidate.json"
# 两类Snapshot准备完毕后,统一构建并发布Tech、Flow、Portal,再切换完整Core:
./deploy.sh core普通 up 只能重入当前活动 Profile;跨 Profile 必须使用 switch。部署控制面会把活动 Profile、精确服务集合和配置/渲染摘要写入仓库外 Runtime State,切换时调用 Compose --remove-orphans。verify 对服务集合做严格相等检查,多一个旧容器也会失败。down 同样只能针对当前活动 Profile,避免拿局部 Compose 文件误停另一套运行服务。
外部配置安全模型
IDP_CONFIG_DIR必须以原始绝对路径提供并位于仓库外,目录权限最大0700;相对路径不会根据当前工作目录自动展开。.env权限最大0600,Secret/私钥最大0600,公开证书最大0644。- 部署工具必须由非 root 账号运行,
IDP_CONTAINER_UID/GID必须与该部署用户一致;这样宿主生成的0400只读投影在原生 Linux 与 Docker Desktop 中都由同一数值 UID/GID 读取,不会出现只在 Mac 上偶然可用的权限假象。 - 拒绝符号链接、硬链接、路径逃逸、glob、重复变量、
export、命令展开和变量展开。 - 变量名疑似包含
PASSWORD、SECRET、TOKEN、API_KEY、PRIVATE_KEY或ACCESS_KEY时,只允许*_FILE。 - 配置、数据、备份、日志、运行时与恢复根必须两两分离,且不能位于 Git 仓库内。
- 上述运行根会先解析真实路径,并在每次写操作前重新拒绝符号链接、路径重叠、错误 Owner 和过宽权限;数据库子目录允许由容器内 PostgreSQL UID 持有。
- 容器只挂载按 Profile 和事实摘要生成的内容寻址不可变代次,不直接看到整个宿主机配置根。重复
doctor/config/verify会复用同一代次,不会替换正在挂载的目录;Config Dir 变化后verify会要求先执行switch/up,不会把新投影冒充已运行事实。 - 调用 Docker Compose 时会清除宿主进程中继承的其他
IDP_*变量,只保留已校验的IDP_CONFIG_DIR与生成目录;镜像、端口和数据路径不能绕过外部.env注入。 - 自动生成的密码和 Token 使用加密安全随机数;外部 Provider 凭据、TLS 私钥和 Registry 用户密码永不代填。
- Dyyto、Bench 与 Forge 发布只读取各自
components/<name>/.env声明的*_NPMRC_FILE;Registry scope、地址和 Token 必须一起放在组件专属的外部0600npmrc 中,禁止仓库内 npmrc、HOME回退或明文 Token 参数。
secrets/infrastructure/registry/htpasswd 是首次启动种子;实时文件位于 IDP_DATA_DIR/registry/auth/htpasswd。之后通过标准 npm adduser --registry http://127.0.0.1:4873 管理用户,Registry 允许匿名安装,但发布和撤销必须认证。
IDP_REGISTRY_PRIVATE_SCOPES 默认并强制至少包含 @aipt,@bench。生成的 Verdaccio 配置会为每个私有 Scope 建立高优先级规则且不包含 proxy,缺失的内部包不会查询 npmjs;其他公开包仍可按普通代理规则访问上游。新增公司私有 Scope 时只修改外部 .env,再执行 config init、doctor 和 switch/up,不得在模板中手改 Verdaccio YAML。
HTTP、TLS 与内网开放
初始 HTTP 配置:
IDP_HTTP_ENABLED=true
IDP_HTTP_BIND=127.0.0.1
IDP_TLS_ENABLED=false
IDP_NETWORK_POLICY_MODE=loopback-only默认安全边界是宿主机回环端口,Caddy 不使用容器内 remote_ip=127/8,因为 Docker Desktop NAT 后它看到的是桥接地址,会错误拒绝本机请求。
Edge 同时连接仅供后端服务通信的 internal 网络和只包含 Edge 的独立 Ingress bridge。后者用于可靠发布宿主端口,避免 Docker Engine 29 对“只连接 internal bridge”的容器保留 HostConfig.PortBindings 却不建立实际端口转发;PostgreSQL 与 Tech 仍只存在于 internal 网络。Edge 继续以非 root、只读根文件系统、cap_drop=ALL 和 no-new-privileges 运行,只恢复官方 Caddy 二进制执行所需的 NET_BIND_SERVICE。健康检查请求容器回环上的真实 /live,不再用“Caddyfile 语法有效”冒充服务可用。
需要供公司内网访问时,必须同时完成:
IDP_NETWORK_POLICY_MODE=host-firewall
IDP_HTTP_BIND=0.0.0.0
IDP_TLS_ENABLED=true
IDP_HTTPS_BIND=0.0.0.0
IDP_ALLOWED_CIDR=10.20.0.0/16
IDP_HOST_FIREWALL_EVIDENCE_FILE=trust/host-firewall-policy.txt将真实办公网/VPN 防火墙规则或变更单证据写入对应文件并配置证书后,doctor --require-configured 才会放行。IDP_ALLOWED_CIDR 是宿主机防火墙契约,不是假装由容器内 Caddy 执行的过滤器;全网 CIDR 会被拒绝。无 OIDC 的初始模式绝不能暴露到公网。Registry 当前是 HTTP 直连能力,强制保持回环监听;需要内网访问时必须另行放到 TLS 反向代理之后。
启用 TLS:
IDP_TLS_ENABLED=true
IDP_HTTPS_BIND=0.0.0.0
IDP_PUBLIC_HOST=idp.example.internal证书和私钥默认位于:
$IDP_CONFIG_DIR/certs/tls-certificate.pem
$IDP_CONFIG_DIR/secrets/infrastructure/edge/tls-private-key.pem当前轻量模式固定 IDP_IDENTITY_MODE=anonymous-private、IDP_OIDC_ENABLED=false,不部署 Keycloak。OIDC issuer、client、group claim、group mapping 和 client-secret 文件引用已经作为通用升级边界保留,但当前版本若把 OIDC 标记为启用会 fail-closed,不能用几项环境变量伪装成已接入身份执行面。Tech 匿名读取开放,所有 Operator 写接口必须携带 TECH_OPERATOR_TOKEN_FILE 中的 Bearer Token。受管部署固定 TECH_OPERATOR_LOOPBACK_ONLY=false,因为请求经 Edge 转发后 Tech 看到的是容器网地址,不能把 X-Forwarded-For 或伪造“回环来源”当授权;真正写门禁是强随机 Token。默认 HTTP 仍只绑定宿主回环,扩大到内网时必须同时启用 TLS 与宿主防火墙。引入企业 SSO 时优先复用公司 IdP 的标准 OIDC/OAuth2,不在此仓库自研认证协议。
Tech 运行合同
Tech 镜像必须消费组件投影入口 IDP_COMPONENT_CONFIG_DIR=/run/idp-config。该目录本身为 0700,包含 .env、config/ 以及相对于 .env 解析的 secrets/...;敏感投影为 0400,普通配置为 0444。部署端不会把组件子树冒充全局 IDP_CONFIG_DIR,也不会把完整宿主配置根挂入容器。
PostgreSQL 每次部署都会先运行一次非 root Bootstrap,再允许 Tech/Portal 启动。Bootstrap 只挂载当前不可变代次内的三个 0400 数据库 Secret,幂等收敛应用角色密码、最小角色属性、危险成员关系、数据库 Owner、PUBLIC 连接权限和 public schema 权限;长期运行的 PostgreSQL 容器只持有其自身启动所需的 superuser Secret。数据库密码与组件连接 URL 必须同步,doctor 会在切换前拒绝不一致的轮换状态。
私有 Git Source 的动态凭据使用 TECH_SOURCE_CREDENTIALS_MANIFEST_FILE=config/source-credentials.json。config init 创建的确定性初值是 {"schemaVersion":1,"files":[]},公共仓库无需伪造凭据即可启动。清单只能包含最多 200 个、唯一且字典序升序的安全 basename;实际源文件只允许位于 $IDP_CONFIG_DIR/components/tech/secrets/source-credentials/<basename>。渲染器只把清单列出的文件投影到容器同名专属子树,未列出的文件、固定 database/operator/OpenAI Secret、保留名、空文件、路径、软硬链接都会 fail-closed。源文件为 0600,运行投影为 0400。
正式运行端口固定为 TECH_BIND_HOST=0.0.0.0、TECH_PORT=3698。容器健康检查使用 /ready,外部验收同时检查 /knowledge/live 和 /knowledge/ready。P0 AI 只接入 Tech 已真实支持的 Embedding:显式设置 TECH_EMBEDDING_ENABLED=true 后,OPENAI_BASE_URL_FILE、OPENAI_API_KEY_FILE 和 OPENAI_EMBED_MODEL 才成为必填;关闭时不需要 Provider Secret。Chat、Image 和对象正文/附件存储目前没有执行面;唯一对象能力键固定为 TECH_OBJECT_STORAGE_MODE=none,不生成任何 S3/OSS endpoint 或 credential 伪配置。当前可恢复边界是 PostgreSQL 数据、Git Knowledge Release pins 与仓库外配置;真正引入对象存储时必须先补版本化 Binding、对象清单与恢复验收,再增加配置键并允许开启。
Flow 与 Portal 的真实数据源
Flow 默认使用 FLOW_MODE=snapshot:Dyyto PackageRelease Catalog 和 Bench Agent Environment 通过外部配置目录内的只读快照输入;Tech 通过 HTTP 读取,必要时可将 FLOW_TECH_REQUIRED=false 并提供经过校验的 Tech Context Bundle。Flow 是无状态编排层,不拥有 PostgreSQL,也不在这里配置 OpenAI Provider。
Portal 同样只把 Tech、Flow 当 HTTP 上游,把 Dyyto、Bench 当文件投影。PORTAL_FIXTURE_FALLBACK=false 是 private/production 强制默认;fixture fallback 只允许 IDP_ENVIRONMENT=development 显式开启,不能拿演示数据冒充生产事实。
推荐的无共享源码同步方式如下。Dyyto 只向 stdout 生成严格投影,由部署控制面校验摘要、保存 Preimage、原子分发到 Flow/Portal。Bench Snapshot 的严格顺序是 switch foundation → verify foundation → bindings sync foundation → Bench export environment → sources import bench:
dyyto catalog export --output - | idpctl sources import dyyto --stdin
idpctl switch foundation
idpctl verify foundation
idpctl bindings sync foundation
# 在Bench仓库根目录执行;benchctl是@bench/benchctl包提供的仓库CLI,不要求全局安装。
corepack pnpm --filter @bench/benchctl benchctl export environment \
--config-dir "$IDP_CONFIG_DIR" \
--environment private \
--output "$IDP_CONFIG_DIR/imports/bench-environment-snapshot.candidate.json"
idpctl sources import bench \
--file "$IDP_CONFIG_DIR/imports/bench-environment-snapshot.candidate.json"bindings sync 不从 .env 猜测“应该存在”的服务。它要求活动 Profile 为 active、Profile/服务集合与命令一致、活动状态的 configDigest 等于当前 doctor 摘要,并要求最近一次 verify 回执证明相同配置、渲染代次和全部服务健康。当前 foundation 会确定性生成:Tech 的 HTTP/TLS Edge Binding、Tech 容器内 PostgreSQL Binding,以及 Bench 消费的 npm Registry anonymous-read Binding。Registry 发布 Token 没有可靠事实来源,因此不会被伪造为 authToken。
受管文件只位于 $IDP_CONFIG_DIR/bindings/idp-deploy;bindings/identity 和用户自建 Binding 不会被改动。生成过程先在 $IDP_CONFIG_DIR/imports 暂存并写入摘要 Manifest,再做目录级发布;更新前将完整旧目录移动到 snapshots/binding-preimages。若受管 YAML、Manifest、文件集合、权限或 Owner 被人工修改,命令会 fail-closed,不覆盖修改。导入器随后再次检查严格字段、self-digest、排序/唯一性、Bench 的文件引用证据、宿主路径扫描以及 configuration 中不得内联 Secret;失败时不会留下部分更新。三个项目之间只交换版本化 JSON 合同,不读取彼此仓库。
把本地项目接入 Docker 开发工作台
项目源码只读挂载,应用配置分别位于仓库外。先初始化 candidate:
export IDP_CONFIG_DIR=/absolute/company/idp/config
export APP_CONFIG_DIR=/absolute/company/app/config
idpctl workbench projects init编辑 $IDP_CONFIG_DIR/workbench/projects.candidate.json。monorepo 中每个应用必须声明自己的 Config Dir:
{
"schemaVersion": 1,
"projects": [
{
"id": "apex",
"hostPath": "/absolute/path/to/sources/spaces/apex",
"configBindings": [
{ "relativePath": "apps/client" },
{ "relativePath": "apps/server" }
]
}
]
}APP_CONFIG_DIR 是业务配置总根;上例自动派生 apex/apps/client/local 和 apex/apps/server/local。各 Config Dir 应先由 app config-init --workspace-root <apex-root> 创建并由操作者填写 .env、secrets/ 和 certs/。随后生成不可变 Plan、应用并验证:
idpctl workbench projects plan \
--dyyto-root "$SOURCES_ROOT/spaces/dyyto" \
--file "$IDP_CONFIG_DIR/workbench/projects.candidate.json" \
--output "$IDP_CONFIG_DIR/plans/workbench-projects/local.json"
idpctl workbench projects apply \
--plan "$IDP_CONFIG_DIR/plans/workbench-projects/local.json"
idpctl workbench projects verify工作台进入 project-readonly 模式:允许登记项目和执行 Inspect、Integrations、Maintenance、运行态读取;不写项目 .env/.env.local,不执行 Upgrade、Apply、Install 或任意命令。配置状态来自项目内 config/application-config.json 与 .dyyto/application-config-binding.json,值只显示脱敏文本,Secret/证书只显示配置状态、摘要和安全元数据。
更新与回滚
正常更新继续使用同一个入口;不再手工改镜像 tag,也不再逐项执行 images lock/pull/up:
docker login idp-registry.cn-shanghai.cr.aliyuncs.com
./deploy.sh --config-dir /absolute/company/idp/config一键入口会自动生成并验证更新前备份。以下命令保留给独立恢复演练、事故处置或变更审计:
idpctl backup create core
idpctl backup verify <generation-id>
idpctl restore test <generation-id>
idpctl restore apply <generation-id>
idpctl restore verify <candidate-id>发布失败时脚本会自动恢复可证明未被并发修改的镜像配置、活动 Profile 和受管 Binding。数据库迁移必须由各应用使用 expand/contract 策略并维持向后兼容;不能只回滚镜像而假设 Schema 自动回退。若旧版本无法恢复健康,按错误中返回的 Generation ID 执行显式 restore apply、restore verify 和带完全相同候选 ID 的 restore promote --confirm。
备份与恢复
backup create <profile> 从 Profile 推导数据集:Portal 只备份 Backstage 数据库,Tech-only 只备份 Tech 数据库,Registry 只归档制品,Core/Full 包含全部 Core 数据库与 Registry;无状态 Flow 没有可备份数据集。pg_dump 与 pg_restore 都通过文件描述符流式传输,已覆盖 101 MiB 回归,不会把增长后的 Dump 整体放入 Node 输出缓冲区。Registry 仅在归档窗口短暂停顿。每个 generation 固化 Profile、预期数据集、大小、SHA-256 和 Manifest 摘要,并绑定到运行目录中的独立、不可覆盖、摘要串联回执。
包含 Tech 时,备份会先停止 Tech 写入入口,在同一停写窗口用镜像内正式命令 knowledge-service backup-boundary 导出严格的 tech.backup-boundary.v1,随后立即创建 Tech custom dump,再恢复服务。Generation 同时绑定边界文件摘要、边界事实摘要与 dump 摘要;边界覆盖 migration checksum、四类业务计数、active index revision、每个 Source 的 commit/treeDigest,并强制对象存储仍为 none。边界命令失败、输出字段漂移或摘要不一致都会使整个 staging 代次进入 failed,不会发布一个只有 dump 的“半安全”备份。
restore test 不覆盖生产数据库:它为每个 Dump 创建隔离临时数据库,验证非空表、对象 Owner 和应用角色连接权限,再检查 Registry 归档的路径与链接安全。Tech 数据库还会由同一 Tech 镜像连接隔离库重新导出边界,必须与备份事实摘要完全相等。生产 promote 会先只启动 PostgreSQL + Tech 完成同样核对,再恢复其他入口;不一致会自动切回 Preimage。该自动证据证明数据库内保存的 Git pin/treeDigest 一致,但不伪装成 Git 远端当前可达;远端重取、仓库权限和 treeDigest 重算仍须由企业 Git 网络内的独立验收证据完成,回执显式记录 external-evidence-required。
restore apply 使用锁定的 PostgreSQL 镜像把备份恢复到 IDP_RESTORE_DIR/candidates 下的全新目录,不接触生产数据;restore verify 再校验候选摘要和物理数据。候选创建后若当前 Profile 的配置摘要发生变化,切换会 fail-closed,必须基于新配置重新执行 restore apply。只有显式提供完全相同候选 ID 时才允许切换:
idpctl restore promote <candidate-id> --confirm <candidate-id>在 Tech-first 的 foundation 运行期,建议分别创建可独立切换的代次:backup create tech-only 保护 Tech 数据库,backup create registry 保护 npm 制品。即使活动 Profile 是 foundation,Tech 单库逻辑恢复也会使用当前活动 Profile 停启 Tech/Edge,Registry保持运行;它不会要求先退回 tech-only。backup create foundation 可用于同一时间窗的联合校验和隔离恢复演练,但因为它同时混合“单数据库逻辑切换”和“Registry目录切换”,当前不会伪装成原子生产切换;完整物理切换仍使用同时包含两个数据库的 core/full 代次。
切换先保存不可变 Plan。core/full 仍在同盘暂存区保留非目标数据,只替换完整 PostgreSQL 与 Registry 候选,并保留物理 Preimage;启动失败自动放回。portal/tech-only 单数据库候选则使用安全的逻辑路径:先把 Dump 恢复到新数据库并完成表、Owner、连接权限验收,短暂停止对应应用后以数据库重命名切换,保留 idp_preimage_* 数据库;新服务不健康时把新库改名隔离并自动切回 Preimage。它不会物理替换共享 PostgreSQL,也不会影响另一个数据库。Registry 候选可以独立切换且不会擦除 PostgreSQL 或 Edge 数据。成功后旧数据仍保留,必须在独立备份确认后再按企业变更流程清理。完整步骤见 docs/restore-runbook.md。
M4 原生首次验收
Intel 机器可使用 IDP_RUNTIME_PLATFORM=linux/amd64 完成功能、备份和恢复预验收,但不能代替 M4 原生证据。正式接收必须在目标 Mac M4 上设置 IDP_RUNTIME_PLATFORM=linux/arm64 并执行一次原生闭环。若 Profile 包含 Registry,先把仅用于验收的发布凭据写入 IDP_REGISTRY_ACCEPTANCE_NPMRC_FILE 指向的仓库外 0600 文件,然后运行:
idpctl accept mac-m4 core \
--confirm-restart company-idp-mac-01该命令拒绝非 darwin/arm64 宿主和非 ARM64 Linux Docker Engine,逐个检查已拉取镜像的平台,执行初始健康验证、真实备份校验、隔离恢复演练、私有 @aipt 临时包发布、Compose 冷停机/重启、重启后安装与清理,并写入摘要串联的验收回执。失败发生在停机后时会先尝试恢复原 Profile;验收凭据、临时 npm cache 和包工程都位于仓库外 Runtime Root。
外部配置根包含恢复数据库所需的密码和 Token,必须进入企业 Secret Manager 或加密离线备份;idp-deploy 不把它复制到普通数据备份中。
开发验证
npm test
npm run check
npm run lifecycle:check
npm run smoke:local
npm run test:integration测试覆盖配置幂等生成、Secret 防泄漏、路径逃逸/软硬链、网络暴露门禁、按 Profile 条件校验、AMD64/ARM64 双平台镜像锁定与旧锁迁移、运行时只读投影、全局互斥、摘要链回执、Compose 组合、101 MiB 流式数据、原子备份、篡改检测、隔离恢复、生产切换与回滚边界。
