# PJ2026-01060308 CI/CD YAML目标治理 ## 修改历史 | 版本 | 对应 commit id | 更新日期 | 变更说明 | | --- | --- | --- | --- | 当前正文仍在规格治理草稿中;未定稿前不新增版本号,不为单次编辑追加 `待提交` 版本。 ## 正文 ## PJ2026-01060308 CI/CD YAML目标治理需求规格 ## 1. 文档控制 | 字段 | 内容 | | --- | --- | | 编号 | PJ2026-01060308 | | 短名 | YAML目标治理 | | 层级 | L3 子课题 | | 状态 | 已生效 | | 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) | | 上级规格 | [PJ2026-010603 YAML运维](PJ2026-010603-yaml-first-ops.md) | | 关联规格 | [PJ2026-010601 发布流水](PJ2026-010601-controlled-release.md)、[PJ2026-010602 源码同步](PJ2026-010602-source-sync.md)、[PJ2026-01060307 控制面模块化](PJ2026-01060307-control-plane-modularity.md)、[PJ2026-010604 公开入口](PJ2026-010604-public-entry.md)、[PJ2026-010605 运维监控](PJ2026-010605-observability-monitoring.md) | | 实现引用版本 | draft-2026-06-25-cicd-yaml-targets; draft-2026-07-01-cicd-source-snapshot | | 规格治理索引 | [规格治理](spec-governance.md) | 本文采用 ISO/IEC/IEEE 29148 需求规格模板的项目裁剪版:正文只保留 CI/CD、YAML-first 和平台运维控制面中 target、lane、Secret、public exposure、PipelineRun/Argo/git-mirror 与公共 ops primitive 的稳定治理口径。 ## 2. 目的和范围 ### 2.1 目的 YAML目标治理负责把 CI、deploy、artifact-registry、HWLAB node/lane、AgentRun、platform-infra、Secret 分发和 public exposure 中的运行目标事实收敛到 owning YAML 或显式参数,使新增 node/lane/target 时不需要发布 TypeScript 代码来改变默认目标、namespace、route、registry endpoint 或 SecretRef。 本规格建立在控制面模块化完成后的领域目录边界上。代码可以保留 legacy adapter、测试夹具、错误消息和帮助示例中的历史目标名,但主路径不得继续通过隐藏默认值把 `G14`、`D601`、`v02`、`v03`、namespace、route、registry endpoint 或工作目录写死在解析逻辑中。 ### 2.2 范围内 - `config/hwlab-node-lanes.yaml`、`config/agentrun.yaml`、`config/platform-infra/*.yaml`、`config/secrets-distribution.yaml`、`config/cicd/targets.yaml` 和 `config/artifact-registry.yaml` 的 target/lane/configRef/sourceRef 职责。 - `scripts/src/ops/` 中的 configRef、target resolver、Secret redaction、public exposure、K8s/CI-CD 和 bounded output 公共原语。 - `ci`、`deploy`、`artifact-registry`、`hwlab g14`、`hwlab nodes`、`agentrun`、`platform-infra observability` 和 `secrets` CLI 对目标来源、配置引用图和脱敏状态的解释输出。 - hardcode inventory 的分类:`remove-code-default`、`keep-domain-special`、`legacy-adapter`、`test-fixture` 和 `help-example`。 ### 2.3 范围外 - 不把所有配置合并成单一超级 YAML。 - 不删除必要的 legacy 安全阻断;legacy 入口必须隔离并在输出中标注。 - 不把运行面 Secret、pod env、日志或数据库状态反向写成本地配置真相。 - 不绕过 UniDesk 受控 CLI 使用原生 `kubectl`、`argo`、`tkn`、`curl` 或临时 shell 作为正式控制入口。 - 不为业务策略数值新增合同测试、硬编码范围或 schema 数值限制。 ## 3. 术语表 | 术语 | 定义 | | --- | --- | | target | YAML 中描述部署目标、运行节点、route、kubeRoute、namespace、workspace、registry、public URL 或 CI/CD 参数的对象。 | | lane | YAML 中描述一条 runtime 或 control-plane 运行线的对象,通常包含 node、source truth、runtime namespace、gitops、CI、Secret 和 publicExposure。 | | configRef | `path/to/file.yaml#object.path` 形式的跨 YAML 引用,解析器只校验引用存在性、类型和摘要,不把合并结果写成第二真相。 | | sourceRef | Secret 来源声明。输出只能显示来源标识、key 名、presence、fingerprint、字节数和 `valuesPrinted=false`。 | | source snapshot | CI/CD 触发时由 k8s 托管 git-mirror 解析出的不可变源码快照,至少包含 repository、branch、selectedCommit、stageRef、mirrorCommit、objectPresent、resolver job 和 YAML 来源。 | | host workspace | operator host 或目标节点上的固定源码 checkout。正式 CI/CD 只能把它作为开发便利或显式 legacy/debug adapter,不得作为发布 source truth。 | | hidden default | 代码在未显式参数或未读取 YAML 时自动选择固定目标、namespace、route、registry、lane 或工作目录。 | | legacy adapter | 为历史入口保留的隔离兼容路径。它可以拒绝 mutation 或提示替代命令,但不得污染主 runtime lane 解析。 | | ops primitive | 跨领域复用的配置引用、目标解析、Secret redaction、K8s apply/status、public exposure 和 bounded output helper。 | ## 4. 系统边界和接口 | 边界项 | 内容 | | --- | --- | | 外部使用者 | 平台维护者、发布操作人员、AgentRun/HWLAB lane 运维者、自动化任务和后续代码维护者。 | | 外部输入 | CLI 参数、YAML 配置、configRef/sourceRef、node/lane/target、desired-state manifest、Git commit 和运行面只读状态。 | | 受控资源 | target resolver、配置引用图、CI/CD manifest 渲染、Secret 同步摘要、public exposure 渲染、PipelineRun/Argo/git-mirror 状态和 CLI 输出。 | | 外部输出 | 有界 plan/status/dry-run、配置来源路径、resolved target、redacted Secret evidence、drill-down 命令和 legacy adapter 提示。 | | 用户接口 | `bun scripts/cli.ts ci ...`、`artifact-registry ...`、`deploy ...`、`hwlab ...`、`agentrun ...`、`platform-infra observability ...` 和 `secrets ...`。 | | 系统边界 | 本规格定义配置如何成为运行目标真相;不定义业务能力语义、不替代发布/源码/公开入口/监控规格,也不让运行面状态成为配置来源。 | ## 5. 内部分工与架构 ### 5.1 配置引用图 ```mermaid flowchart LR CICD[config/cicd/targets.yaml] --> OpsTarget[ops/targets.ts] Artifact[config/artifact-registry.yaml] --> OpsTarget Hwlab[config/hwlab-node-lanes.yaml] --> OpsTarget AgentRun[config/agentrun.yaml] --> OpsTarget Observability[config/platform-infra/observability.yaml] --> ConfigRef[ops/config-refs.ts] Secrets[config/secrets-distribution.yaml] --> OpsSecret[ops/secrets.ts] ConfigRef --> Hwlab ConfigRef --> AgentRun OpsTarget --> DomainCLI[domain CLI plan/status/dry-run] OpsSecret --> DomainCLI DomainCLI --> Runtime[controlled runtime or bounded output] ``` ### 5.2 target/lane 解析数据流 ```mermaid flowchart TD Args[explicit --target/--node/--lane] --> Select[selection] Defaults[YAML defaults] --> Select Select --> Resolver[ops target resolver] Resolver --> Validate[shape and reference validation] Validate --> Plan[resolved target summary] Plan --> Domain[CI/deploy/artifact/HWLAB/AgentRun/platform-infra] Domain --> Output[bounded summary + drill-down] ``` 命令行或 issue 已明确 node/lane/target 时,resolver 只校验和解释该目标,不得用全局 default 覆盖。未显式传入目标时,resolver 可以读取 domain YAML default,并在输出中说明默认来源路径。 ### 5.3 Secret sourceRef 同步链路 ```mermaid sequenceDiagram participant YAML as owning YAML participant CLI as controlled CLI participant Source as local sourceRef participant Runtime as runtime Secret YAML->>CLI: sourceRef + sourceKey + targetKey CLI->>Source: inspect presence and fingerprint Source-->>CLI: presence/fingerprint only CLI-->>CLI: valuesPrinted=false CLI->>Runtime: sync only when --confirm Runtime-->>CLI: object/key presence CLI-->>YAML: no reverse write-back ``` 缺少 sourceRef、targetKey、providerCredential 或 tool credential 时,CLI 必须暴露 YAML/AipodSpec binding 缺口,不得通过复制其他 lane Secret、手工创建 legacy Secret 或 patch runtime namespace 规避。 ### 5.4 publicExposure/Caddy/FRPC 链路 ```mermaid flowchart LR PublicYaml[publicExposure YAML] --> PublicHelper[ops/public-exposure.ts] PublicHelper --> Frpc[FRPC Secret/render] PublicHelper --> Caddy[PK01 Caddy managed block] PublicHelper --> Probe[HTTPS public health probe] Probe --> Summary[public URL + diagnostic endpoint summary] ``` 正式用户入口来自 YAML 中的 public URL 和 publicExposure;FRP remote port、Caddy backend、本地 service DNS、direct port 或历史 nip.io 域名只能作为实现细节、诊断入口或 legacy 对照。 ### 5.5 CI PipelineRun/Argo/git-mirror 状态链路 ```mermaid sequenceDiagram participant CLI participant Target as YAML target participant Mirror as git-mirror participant Tekton participant Argo participant Runtime CLI->>Target: resolve CI/CD target CLI->>Mirror: read source authority Mirror-->>CLI: refs and source summary CLI->>Tekton: PipelineRun status or read-only plan Tekton-->>CLI: PipelineRun/TaskRun bounded summary CLI->>Argo: Application sync/health status Argo-->>Runtime: desired runtime state Runtime-->>CLI: readiness/public probe summary ``` 状态输出必须区分 PR merge commit、current source head、PipelineRun、Argo revision、git-mirror pendingFlush 和 runtime readiness;不得只用一个当前 head 推断所有阶段完成。 ### 5.6 k8s source snapshot 链路 ```mermaid sequenceDiagram participant CLI participant Target as YAML target participant Resolver as k8s git-mirror resolver participant Mirror as git-mirror cache participant Tekton CLI->>Target: resolve node/lane/sourceAuthority CLI->>Resolver: read selected commit and calculate plan Resolver->>Mirror: read selected commit and object presence Mirror-->>Resolver: selectedCommit + objectPresent Resolver-->>CLI: env reuse + build scope CLI->>PaC: manual webhook after plan review Resolver->>Mirror: create immutable stageRef PaC->>Tekton: create PipelineRun with sourceSnapshot Tekton->>Mirror: fetch/checkout immutable stageRef or snapshot artifact ``` 正式 CI/CD 的源码身份以 source snapshot 为准。只读 `plan` 不得同步 mirror、创建 snapshot 或修改运行面;手动 `trigger` 在完成当前 plan 审阅后才可创建本轮不可变 snapshot。`trigger-current`、image publish、GitOps render 和 closeout 不得再从 operator host 的 dirty/stale worktree、当前 branch tip 或 GitHub direct fetch 推导本轮 source identity。upstream fetch 只允许发生在受控 k8s git-mirror resolver/sync 组件内;PipelineRun 只消费 node-local mirror 的不可变 stageRef、PVC 或 bundle artifact。 ## 6. 原子需求 ### 6.1 OPS-TARGET-REQ-001 YAML target 真相 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-001 | 目标真相 | PJ2026-01060308 YAML目标治理 | [YAML运维](PJ2026-010603-yaml-first-ops.md) | CI/CD、deploy、artifact-registry、HWLAB node/lane、AgentRun 和 platform-infra 的 target、lane、namespace、route、workspace、registry endpoint、public URL、SecretRef、gitops path 和 CI/CD 参数必须来自 owning YAML 或显式参数。 代码不得在主路径中新增隐藏默认 `G14`、`D601`、`v02`、`v03`、namespace、route、registry endpoint 或工作目录。缺少配置时应报出 YAML 路径、字段名和下一步配置入口。 ### 6.2 OPS-TARGET-REQ-002 configRef 解析 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-002 | 配置引用 | PJ2026-01060308 YAML目标治理 | [公共原语](PJ2026-010603-yaml-first-ops.md#66-ops-yaml-req-006-公共-ops-primitive) | 跨 YAML 目标事实必须通过 `path/to/file.yaml#object.path` configRef 表达。configRef parser 只负责读取、校验存在性、生成摘要 hash、展示引用链和暴露缺失字段;不得把解析后的大对象写回另一个 YAML 成为第二真相。 `platform-infra observability` 的 serviceConnection 不得复制 HWLAB/AgentRun 的 node/lane/namespace 事实,必须通过 configRef 指向对应 lane 配置,并在 `plan/status --full` 中展示解析链。 ### 6.3 OPS-TARGET-REQ-003 公共 resolver 和 domain 注入默认 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-003 | resolver | PJ2026-01060308 YAML目标治理 | [控制面模块化](PJ2026-01060307-control-plane-modularity.md) | 公共 option parser 不允许内置 domain target 默认。公共 parser 可以返回 `targetId: null`,由调用 domain 把 YAML default 注入并输出 default 来源路径。`ciTarget()`、deploy provider resolver、artifact-registry options 和 platform-infra common options 都必须遵循该规则。 ### 6.4 OPS-TARGET-REQ-004 Secret 与 credential 脱敏一致性 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-004 | Secret脱敏 | PJ2026-01060308 YAML目标治理 | [用户管理](PJ2026-0105-user-management.md)、[Agent编排](PJ2026-0102-agent-orchestration.md) | Secret plan/status 只允许输出对象名、key 名、sourceRef、targetKey、presence、fingerprint、字节数、缺失项和 `valuesPrinted=false`。AgentRun provider credential、tool credential、HWLAB bootstrap Secret、platform-infra Secret 和通用 `secrets` 命令必须使用同一类 redacted sourceRef/fingerprint 语义。 ### 6.5 OPS-TARGET-REQ-005 legacy adapter 隔离 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-005 | legacy隔离 | PJ2026-01060308 YAML目标治理 | [发布流水](PJ2026-010601-controlled-release.md) | D601 maintenance deploy、G14 DEV/PROD retirement、v02-only runtime migration、Code Queue compat path 等历史入口可以保留为 legacy adapter,但必须在代码和输出中标注原因、替代命令和是否允许 mutation。legacy adapter 不得成为主 runtime lane 的 fallback,也不得补齐缺失 YAML/Secret。 ### 6.6 OPS-TARGET-REQ-006 hardcode inventory 与验收 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-006 | inventory | PJ2026-01060308 YAML目标治理 | [平台运维](PJ2026-0106-platform-ops.md) | 每轮治理必须维护 hardcode inventory,并把命中分类为 `remove-code-default`、`keep-domain-special`、`legacy-adapter`、`test-fixture` 或 `help-example`。代码中保留的目标名必须属于后四类之一;`remove-code-default` 必须迁移到 YAML 或公共 helper。 验收至少覆盖 `ci plan/status --target `、`artifact-registry plan/status --target `、`deploy apply --dry-run` 目标来源说明、`hwlab nodes control-plane status --node --lane ` 的 YAML-declared lane、`platform-infra observability plan/status --full` 的 configRef 解析链和 `secrets status --config ... --full` 的脱敏输出。 ### 6.7 OPS-TARGET-REQ-007 source snapshot 与 host worktree 禁用 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-007 | 源码快照 | PJ2026-01060308 YAML目标治理 | [源码同步](PJ2026-010602-source-sync.md)、[发布流水](PJ2026-010601-controlled-release.md) | CI/CD source authority 必须由 owning YAML 声明。主路径应支持 `sourceAuthority.mode=gitMirrorSnapshot` 或等价字段,使受控 CLI 通过 k8s git-mirror resolver 选择本轮 `selectedCommit` 并创建不可变 snapshot/stageRef。`sourceAuthority.allowHostGit=false` 时,正式 `trigger-current`、image publish、GitOps render 和 closeout 不得执行 operator host `git ls-remote`、`git fetch`、`git clone`、`git rev-parse HEAD` 或读写固定 host workspace。 PipelineRun source step 不得以 mutable `refs/heads/` 作为本轮源码身份。它只能从 source snapshot 的 `stageRef`、commit-pinned mirror ref、PVC 或 bundle artifact checkout;若对象缺失,应返回 `source-snapshot-missing`,并输出受控 `git-mirror sync/ensure-snapshot` 下一步,不得回退到 GitHub direct clone、host workspace repair 或第二套 source resolver。 status/closeout 必须同时展示 selected snapshot、PipelineRun snapshot、latest mirror head、GitOps revision 和 runtime provenance。branch 在发布过程中前进只能标记为 `latest-drift` 或 `superseded`,不得把 selected commit 的成功发布误判为本轮失败。 ### 6.11 OPS-TARGET-REQ-011 L2/L3手动触发配置 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-011 | 手动触发 | PJ2026-01060308 YAML目标治理 | [发布流水](PJ2026-010601-controlled-release.md)、[NC01 CI资源治理](PJ2026-01060107-nc01-ci-resource-governance.md) | CI/CD owning YAML 必须为 L2/L3 target 声明 `deliveryTrigger.mode=manual-plan-confirm` 和 `deliveryTrigger.mechanism=pac-webhook`。这些字段是发布触发方式的唯一真相;PaC webhook 接收端保留,Gitea 自动 hook 必须移除。代码、环境变量、Repository annotation 和 consumer 私有配置不得恢复自动 push、PR merge、branch update、poll 或 follow 发送行为。 只读 `plan` 必须从 YAML 和精确 source commit 解析 env reuse、待构建镜像、rollout 服务、全部受影响服务、范围基线和新增范围。发现新增范围时必须先修复配置或 planner 后重新 plan,不得使用强制参数越过。 受控手动 `trigger` 必须同时接收 target、consumer 或 lane、精确 source commit 和 pipeline intent,并向 PaC 发送 webhook;CLI 不得直接创建 PipelineRun。输入、YAML、env identity 或构建/rollout 范围变化后必须重新 plan。PR merge 后不自动 trigger,L0/L1 操作也不得调用该 mutation。 ### 6.8 OPS-TARGET-REQ-008 k3s server 重启门禁非阻塞 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-008 | k3s重启 | PJ2026-01060308 YAML目标治理 | [平台运维](PJ2026-0106-platform-ops.md)、[控制面模块化](PJ2026-01060307-control-plane-modularity.md) | k3s server 受控重启不得以派生凭据文件与 datastore 的 mtime 或 freshness 预判阻断 YAML-first 变更。入口应在停止服务后备份派生 `server/cred/passwd`,并以 `blocking=false` warning 披露;只有真实启停、 节点就绪或期望状态收敛失败才可使 apply 失败。不得重新引入凭据新旧 preflight、CI gate 或人工确认门禁。 ### 6.9 OPS-TARGET-REQ-009 CI 工具镜像默认能力 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-009 | 工具镜像能力 | PJ2026-01060308 YAML目标治理 | [发布流水](PJ2026-010601-controlled-release.md)、[平台运维](PJ2026-0106-platform-ops.md) | - CI tools image 必须默认包含 `kubectl`; - `kubectl` 必须由 owning YAML 声明的 Dockerfile 在镜像构建阶段安装和自检; - 使用 tools image 的有界 CI helper、cleanup 和 bootstrap 可以调用镜像内的 `kubectl`; - 禁止在 PipelineRun、Pod 或 Job 启动后临时安装 `kubectl`; - 该默认能力只属于 CI tools image,不得隐式扩大为产品业务镜像或长期 controller 的运行时依赖。 ### 6.10 OPS-TARGET-REQ-010 发布观测证据适用性 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | | OPS-TARGET-REQ-010 | 观测证据适用性 | PJ2026-01060308 YAML目标治理 | [发布流水](PJ2026-010601-controlled-release.md)、[运维监控](PJ2026-010605-observability-monitoring.md) | PaC consumer 必须通过 owning YAML 的 `deliveryObservation.runtimeEvidence` 声明发布观测是否需要 workload 证据。 - `required` consumer 必须观察到与 source commit 精确匹配且 ready 的 workload; - `not-applicable` 只适用于配置或控制面交付,没有独立业务 workload 的 consumer; - `not-applicable` consumer 仍必须满足 source commit 匹配、PipelineRun 成功和 Argo `Synced/Healthy`; - 非核心字段缺失时可以回退到 `required`,但必须输出配置路径、回退值、原因和 `blocking=false` warning; - 观测模式不得改变 PipelineRun、GitOps、Argo 或 runtime authority,也不得新增第二状态源。 ## 7. 过程控制 本规格的执行 issue 为 [#911](https://github.com/pikasTech/unidesk/issues/911)。源码文件头部应标注 `SPEC: PJ2026-01060308 cicd-yaml-targets draft-2026-06-25-cicd-yaml-targets`;自动生成文件、纯配置、锁文件和无法承载注释头的二进制产物可例外。 首轮 hardcode inventory: | 命中 | 分类 | 治理动作 | | --- | --- | --- | | `ciTarget()`、`d601ProviderId`、CI pipeline manifest、node label、host/root/workspace | remove-code-default | 迁入 `config/cicd/targets.yaml`,CI resolver 读取 YAML。 | | `artifact-registry` 默认 D601、`127.0.0.1:5000`、runtime image、storageDir | remove-code-default | 迁入 `config/artifact-registry.yaml`。 | | `deploy` artifact consumer provider 默认 D601 | remove-code-default | 从 artifact-registry YAML default 解析;compat path 显式 legacy。 | | `HwlabRuntimeLane = "v02" | "v03"` 和 `isSupportedLaneId()` | remove-code-default | lane id 改为 YAML 声明 string,新增 lane 不要求改 TypeScript union。 | | `platform-infra observability` 复制 `targetNode/lane/namespace` | remove-code-default | 改为 serviceConnection configRef 并输出解析链。 | | D601 maintenance deploy、Code Queue compat path、v02 runtime migration | legacy-adapter | 保留安全阻断和替代命令,不作为主路径默认。 | | 帮助示例、错误消息、历史说明中的 G14/D601/v02/v03 | help-example | 允许保留,必要时补 `configTruth` 或 legacy 标注。 |