npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 down

2. 工作区 / 业务应用 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 --json

up 是正式 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 必须一起放在组件专属的外部 0600 npmrc 中,禁止仓库内 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 流式数据、原子备份、篡改检测、隔离恢复、生产切换与回滚边界。