@numa-tech/numa 1.13.2 → 1.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,126 @@
1
+ # 应用入驻确认清单
2
+
3
+ ## 目录
4
+
5
+ - [状态模型](#状态模型)
6
+ - [完整字段](#完整字段)
7
+ - [草案格式](#草案格式)
8
+ - [最终确认](#最终确认)
9
+
10
+ ## 状态模型
11
+
12
+ 每项记录 `value`、`state`、`confidence`、`evidence`、`requiredBefore`:
13
+
14
+ - `OBSERVED`:权威事实;
15
+ - `INFERRED`:推荐值,等待确认;
16
+ - `CONFIRMED`:用户确认;
17
+ - `UNRESOLVED`:阻止 plan/apply;
18
+ - `DEFERRED`:当前能力未提供,不得声称已配置。
19
+
20
+ `requiredBefore` 使用 `PLAN`、`APPLY`、`FIRST_DEPLOY` 或 `FUTURE_DATABASE_PROVISION`。
21
+
22
+ ## 完整字段
23
+
24
+ ### 目标和身份
25
+
26
+ - Numa version、profile ID、API origin、tenant、目标环境级别;
27
+ - runtime command catalog、`app capabilities` 与各 child capability 状态;
28
+ - 当前用户 subject/username/email;
29
+ - 平台角色、团队成员关系及最低所需成员级别;
30
+ - 操作范围:仅 plan、创建应用/仓库/流水线、是否触发 build/deploy。
31
+
32
+ ### 应用归属
33
+
34
+ - application code、name、description/status;
35
+ - teamId/team code、成员资格证据;
36
+ - systemId/system code;
37
+ - business-domain ID/code;
38
+ - owner/maintainer 联系边界。
39
+
40
+ ### 项目和代码库
41
+
42
+ - 本地目录、技术语言/框架、构建系统;
43
+ - Git dirty 状态、branch、HEAD、remote;
44
+ - source state:REMOTE_TRACKED/LOCAL_HISTORY_WITHOUT_REMOTE/REMOTE_WITHOUT_UPSTREAM/DIRTY_WORKTREE/UNVERSIONED_DIRECTORY;
45
+ - mode:NEW/EXISTING;repoMode:STANDALONE/ADD_MODULE;
46
+ - SCM connection/provider/organization;
47
+ - repository namespace/name/externalId/defaultBranch/expectedHead/visibility;
48
+ - 模板 code/revision、技术栈 code、模板参数;
49
+ - 缺仓库时的创建、首次提交和推送策略。
50
+ - publication manifest/version/digest、文件数/总字节、排除项、plan/run/idempotency key;
51
+ - executable tracked file count;Codeup HTTPS clone credential readiness(只记录 boolean);
52
+
53
+ ### 构建和流水线
54
+
55
+ - MCI build-flow、APP_NAME、APP_HOME、agent label、Node/JDK/Python version;
56
+ - PORT=8080、启动入口、健康检查;
57
+ - Jenkinsfile/Dockerfile 策略;
58
+ - jenkinsRequired、tiers、trigger branch、manual/webhook;
59
+ - build parameters(仅非敏感)、Sonar、artifact/image name;
60
+ - 是否只创建流水线,是否触发 build/deploy。
61
+ - Jenkins Job plan/run/config digest、inventory generation、binding confirmation;
62
+
63
+ ### 环境和运行位置
64
+
65
+ - defaultEnvironmentId/env code/tier;
66
+ - clusterId/name、region、tenant/network zone、architecture;
67
+ - Kubernetes namespace、replicas、resource profile;
68
+ - GitOps target/profile/service plan、binding、Observer scope 与 live evidence;
69
+ - ingress/domain、service port、readiness/liveness;
70
+ - 与数据库/外部依赖的网络可达性。
71
+
72
+ ### 数据库
73
+
74
+ - needed、engine/version、shared/dedicated;
75
+ - instanceId/code/name、environment/region/network;
76
+ - database name、schema、owner role;
77
+ - HA/replicas/storage、backup/retention;
78
+ - migration tool/owner;
79
+ - secret injection mechanism(只记录引用方式,不记录 secret);
80
+ - capability:AVAILABLE 或 `DEFERRED`。
81
+
82
+ ### 治理和恢复
83
+
84
+ - onboarding sessionNo/revision/planHash/idempotency key;
85
+ - Repository、Publication、Jenkins、GitOps、Observer 各 child plan/run 和 last event sequence;
86
+ - 预期外部副作用;
87
+ - 生产审批需求;
88
+ - blocking warnings、恢复动作和回滚边界。
89
+ - 写响应是否由原响应确认或由写前 cursor 之后、精确匹配本次 intent 的新持久证据恢复;既有状态不得标为 `recovered_from_status`。publication attach 必须记录原 sessionNo/clientRequestId、resolve 200 same-session binding/replayed=true,或 retryable 404 待恢复状态;禁止的 port-forward/tunnel 旁路。
90
+
91
+ ## 草案格式
92
+
93
+ 先输出紧凑表格:
94
+
95
+ | 类别 | 参数 | 建议/事实 | 状态 | 置信度与证据 |
96
+ |---|---|---|---|---|
97
+ | 应用 | code | `order-service` | INFERRED | HIGH:Jenkins APP_NAME |
98
+ | 归属 | teamId | `12 / payments` | UNRESOLVED | MEDIUM:同系统应用多数归属 |
99
+ | 环境 | envId | `2 / dev1` | INFERRED | HIGH:唯一 active DEVELOP 环境 |
100
+ | 数据库 | instanceId | — | DEFERRED | 数据库 CLI 尚未提供 |
101
+
102
+ 表格后列出:
103
+
104
+ 1. 可直接采用的观察值;
105
+ 2. 推荐决策及原因;
106
+ 3. 本轮要问的问题;
107
+ 4. 当前 blockers;
108
+ 5. 未来能力待办。
109
+
110
+ ## 最终确认
111
+
112
+ 执行前用以下顺序展示:
113
+
114
+ 1. **身份与目标**:谁、在哪个 profile/tenant、操作哪个环境;
115
+ 2. **应用归属**:code/name/team/system/domain;
116
+ 3. **代码库**:provider/connection/repo/branch/HEAD,以及是否创建和推送;
117
+ 本地无 remote 时另列 publication manifest digest、bundle 边界和是否需要人工桥接;
118
+ 4. **技术与构建**:stack/template/build-flow/8080/health;
119
+ 5. **部署位置**:envId/cluster/namespace/tier;
120
+ 6. **数据库**:engine/instance/database/schema,明确 AVAILABLE 或 DEFERRED;
121
+ 7. **将发生的写操作**:逐项编号;
122
+ 8. **不会发生的操作**:默认包括 build、production deploy 和 secret 写入;
123
+ 9. **恢复信息**:session/idempotency key/结果未知处理;
124
+ 10. **未决告警**:必须为空才允许 apply;`DEFERRED` 项需明确不影响本次 apply。
125
+
126
+ 最后只提供“确认执行(推荐,仅在清单无 blocker 时)”和“返回修改”两类选择。用户确认后仍要做一次只读漂移检查。
@@ -0,0 +1,69 @@
1
+ # 参数推断规则
2
+
3
+ ## 目录
4
+
5
+ - [证据优先级](#证据优先级)
6
+ - [应用和团队](#应用和团队)
7
+ - [代码库](#代码库)
8
+ - [技术栈](#技术栈)
9
+ - [环境和集群](#环境和集群)
10
+ - [数据库](#数据库)
11
+
12
+ ## 证据优先级
13
+
14
+ 按以下顺序使用证据:平台权威 API > 已提交仓库配置 > Git remote/HEAD > 用户明确描述 > 命名约定。冲突时展示冲突,不自动选低优先级值。
15
+
16
+ 置信度建议:唯一权威映射为 HIGH;两个独立证据一致为 MEDIUM/HIGH;仅名称相似为 LOW。LOW 值必须询问。
17
+
18
+ ## 应用和团队
19
+
20
+ - 应用 code 优先取已存在 catalog code,其次 Jenkins `APP_NAME`,再取 remote 仓库 slug,最后取根 package/project 名。
21
+ - code 使用小写 kebab-case;不要静默改动已部署镜像名或稳定 API 标识。
22
+ - 应用团队代表业务/运维责任,不等同于 Codeup group、Keycloak group 或 Kubernetes namespace。
23
+ - 团队候选依次参考:已有同系统应用、CODEOWNERS/maintainer、仓库 namespace、package scope、当前用户团队成员关系。
24
+ - 只推荐当前用户至少具有平台要求成员级别的团队。成员关系无法证明时必须询问或停止。
25
+ - systemId 优先复用同一产品族的系统;business domain 只提供背景,不能替代 systemId。
26
+
27
+ ## 代码库
28
+
29
+ - 已有 remote 且平台 SCM 能返回同一仓库时使用 `EXISTING`,固定 `externalId`、default branch 和 `expectedHead`。
30
+ - remote 不存在但平台有同名仓库时,先确认是否接管;不得只凭名字认领。
31
+ - 没有代码库时,从应用 code 推断 repository name,从已确认团队/系统推断 namespace;检查名称冲突和 SCM create capability。
32
+ - 已有 clean Git HEAD 但 remote 列表为空时分类为 `LOCAL_HISTORY_WITHOUT_REMOTE`。它不是受管模板 NEW:先锁定同 application code 的私有 Repository CREATE plan(Codeup 使用受管 README 初始化),再创建 schemaVersion=3 parent,并通过 session-scoped Publication child 发布现有 tree;继续同一 session,不转成第二个 ATTACH_EXISTING。
33
+ - Jenkins `APP_NAME`、线上镜像/HelmRelease 名称和目录名冲突时,优先稳定运行身份;目录名只作为低优先级线索。不得因此创建两个远端仓库。
34
+ - 新仓库优先私有、默认分支 `main`,除非组织标准或现有项目明确使用其他分支。
35
+ - 模板为空或 SCM 没有 CREATE capability 时,不绕过 Numa 直接造目录记录。给出缺少模板、连接、权限或仓库的前置清单。
36
+ - 工作区不干净、无 commit 或 HEAD 与远端不一致时,不创建基于该 HEAD 的流水线。
37
+ - publication capability 不可用时标记 `MANUAL_BRIDGE`,不要把普通 `git push` 伪装成平台自动化。人工桥接必须单独确认并读回 remote HEAD。
38
+
39
+ ## 技术栈
40
+
41
+ - 从构建文件、依赖和产物识别实际框架,再与 `numa` 返回的 technology stack 匹配。
42
+ - 不把通用 Fastify/Express 项目伪装成 NestJS,也不把 Vite SPA 伪装成 Next.js。
43
+ - 没有精确 stack 时显示实际检测结果和最接近候选,要求用户确认平台映射或先注册 stack。
44
+ - 创建前检查 MCI 构建标准:Jenkins `buildEntry()`、APP_NAME、构建节点、8080/PORT、启动入口和 Dockerfile 保留理由。
45
+
46
+ ## 环境和集群
47
+
48
+ - envId 只能来自 Numa/platform 权威环境列表,不能从 `dev1`、`stg1`、`prod` 字符串自行构造 ID。
49
+ - 未明确要求生产时优先推荐可用的 DEVELOP 环境;不得默认生产。
50
+ - 集群优先选择 envId 显式绑定的 active/ready 集群;其次匹配 tenant、region、网络区和 workload class。
51
+ - 同一 env 有多个集群时比较容量、架构、合规标签、数据库网络可达性和现有同系统应用分布,并询问用户。
52
+ - 一等 cluster CLI 不存在时,通过已批准的只读 API收集候选;没有权威数据时标记 `DEFERRED`,不要编造 clusterId。
53
+ - namespace 默认候选为应用 code,但必须检查平台命名策略和冲突。
54
+
55
+ ## 数据库
56
+
57
+ 先判断是否需要持久化:
58
+
59
+ - 没有 ORM/driver/migration/config 信号时推荐 `NONE`。
60
+ - `pg`、PostgreSQL URL、Drizzle/Postgres migration 等信号推荐 PostgreSQL。
61
+ - `mysql2`/MariaDB 信号推荐 MySQL;Mongo driver/Mongoose 推荐 MongoDB;SQLite 只默认用于本地开发,不能自动当作生产数据库。
62
+
63
+ 数据库清单至少包含:engine、version、shared/dedicated、instanceId、database name、schema、owner、environment、region/network、HA、backup/retention、migration owner、secret injection。不得推断密码或连接串。
64
+
65
+ - PostgreSQL shared instance 推荐独立 database role 和独立 schema;schema 候选为应用 code 转 snake_case,限制在 63 bytes 内。不要默认使用 `public`。
66
+ - PostgreSQL dedicated database 可让 database name 与应用 code 的 snake_case 一致,但 database 和 schema 仍分别确认。
67
+ - MySQL 的 schema 与 database 通常同义,在清单中明确标注。
68
+ - instanceId 必须来自平台数据库 inventory。当前 CLI 无该能力时标记 `DEFERRED`,同时保留期望 engine/schema/环境供以后升级。
69
+ - 数据库选择必须与目标 env/cluster 网络可达性一致。先确认 env/cluster,再最终选择 instance。
@@ -0,0 +1,216 @@
1
+ # Numa CLI 执行契约
2
+
3
+ ## 目录
4
+
5
+ - [命令解析](#命令解析)
6
+ - [只读发现](#只读发现)
7
+ - [安全输出](#安全输出)
8
+ - [入驻执行](#入驻执行)
9
+ - [恢复规则](#恢复规则)
10
+
11
+ ## 命令解析
12
+
13
+ 优先使用 PATH 中的 `numa`。缺失时建议用户安装 launcher,或用以下临时入口执行公开诊断:
14
+
15
+ ```bash
16
+ npx -y --prefer-online --registry=https://registry.npmjs.org/ @numa-tech/numa@latest --version
17
+ ```
18
+
19
+ 不要硬编码本地 Numa 源码路径。先执行 `numa commands --json`,以运行时命令目录为准;CLI 增加一等 cluster/database 命令后优先使用新命令。
20
+
21
+ ## 只读发现
22
+
23
+ 按需执行:
24
+
25
+ ```bash
26
+ numa --version
27
+ numa auth status --json
28
+ numa config --show --json
29
+ numa profile --json
30
+ numa commands --json
31
+ numa app capabilities --json
32
+ numa app options team --json
33
+ numa app options system --json
34
+ numa app options business-domain --json
35
+ numa app options environment --json
36
+ numa repository connection list --json
37
+ numa repository capabilities --connection <code> --consumer application-onboarding --json
38
+ numa repository namespace list --connection <code> --json
39
+ numa repository remote list --connection <code> --search <name> --json
40
+ numa app list --json
41
+ numa pipeline list --app <application-code> --json
42
+ ```
43
+
44
+ 兼容期仍可只读使用 `numa app scm`,但仓库生命周期必须使用顶层 Repository Control Plane:
45
+
46
+ ```bash
47
+ numa repository remote list --connection <connection-code> --search <repository-name> --json
48
+ ```
49
+
50
+ 团队选项可见不等于当前用户具有 `MEMBER+`。通过运行时 command catalog 找团队成员查询能力;缺失时用批准的只读平台 API,并把无法证明的成员资格标记为 `UNRESOLVED`。
51
+
52
+ ## 安全输出
53
+
54
+ `numa request --json` 可能包含响应 headers。永远在命令输出到工具日志前做字段 allowlist;不要输出 `.response.headers`:
55
+
56
+ ```bash
57
+ set -o pipefail
58
+ numa request /approved/read-only/path --json |
59
+ jq 'if .ok then {ok, status: .response.status, body: .response.body} else {ok, error} end'
60
+ ```
61
+
62
+ 对 body 继续裁剪到本次决策需要的字段。禁止显示 token cache、`set-cookie`、Authorization、credential、password、secret、private key、完整 connection string。
63
+
64
+ `app publication attach --json` 的安全契约只包含 session/plan 标识、state、tree/manifest 计数、
65
+ digest、幂等键和恢复证据;不得输出完整 session draft/plan、manifest path、`sourceRoot`、
66
+ `contentBase64` 或 provider payload。
67
+
68
+ attach 的 POST 返回 500/504、连接中断或 2xx body 无法解析时,CLI 必须用原值有界轮询精确只读
69
+ resolve endpoint;手工恢复命令为:
70
+
71
+ ```bash
72
+ numa app publication resolve <session-no> --client-request-id <original-id> --json
73
+ ```
74
+
75
+ 该命令不上传 bundle、不重放 attach。200 必须是同一 session 的 `APPLICATION_ONBOARDING` binding
76
+ 且 `replayed=true`;retryable 404 `ONBOARDING_PUBLICATION_PLAN_NOT_RESOLVED` 表示可稍后重查,不能
77
+ 改用新 key 或新 session。
78
+
79
+ ## Repository Control Plane
80
+
81
+ 缺少远端仓库且计划由 Application Onboarding 消费时,先幂等创建空 session,再发现 namespace/capability 和创建不可变计划:
82
+
83
+ ```bash
84
+ numa app begin --mode new \
85
+ --idempotency-key begin-order-service --yes --json
86
+ numa repository capabilities \
87
+ --connection codeup-main --consumer application-onboarding --json
88
+ numa repository namespace list \
89
+ --connection codeup-main --search 'numa/framework' --json
90
+ numa repository remote list \
91
+ --connection codeup-main --search order-service --json
92
+ numa repository plan create \
93
+ --connection codeup-main --namespace 123 --name order-service \
94
+ --visibility private --initialization readme \
95
+ --consumer application-onboarding --consumer-ref <begin返回的session-no> \
96
+ --owner-team-id 12 --json
97
+ numa repository plan get <plan-no> --json
98
+ numa repository create \
99
+ --plan-no <plan-no> --plan-hash <64-hex> \
100
+ --client-request-id <stable-key> --idempotency-key <same-key> \
101
+ --yes --json
102
+ ```
103
+
104
+ Repository `create` 只负责远端生命周期和 catalog 一致性,不会隐式读取或推送本地目录。Codeup 的本地历史发布使用 `README` 初始化,随后由 Publication CAS 精确替换 tree;不要创建空仓后直接 Git push。
105
+
106
+ 独立仓库发布可使用顶层 `publication scan/plan/apply/status/events`。Application Onboarding 不得把这种 `STANDALONE/JWT` plan 冒充 child;必须在 parent 等待 `ATTACH_PUBLICATION_PLAN` 后调用:
107
+
108
+ ```bash
109
+ numa app publication attach <session-no> \
110
+ --source <clean-git-root> \
111
+ --commit-message 'feat: publish existing project' \
112
+ --client-request-id <stable-child-key> \
113
+ --idempotency-key <same-key> --yes --json
114
+ ```
115
+
116
+ CLI 只从 clean Git HEAD 构造受限 bundle,输出不回显文件内容或本地绝对路径。命令不存在时按 promote workflow 标记 `MANUAL_BRIDGE`,不能把普通 Git 推送写成平台功能。
117
+
118
+ ## 入驻执行
119
+
120
+ 普通接入可使用 schemaVersion 2;创建并 promote 已有本地项目必须使用 schemaVersion 3,把 Publication、Jenkins Job、GitOps、Observer 和首次 build 拆成独立 gate:
121
+
122
+ ```json
123
+ {
124
+ "schemaVersion": 3,
125
+ "mode": "NEW",
126
+ "catalogStrategy": "CREATE_NEW",
127
+ "application": {
128
+ "code": "order-service",
129
+ "name": "Order Service",
130
+ "teamId": 12,
131
+ "systemId": 7,
132
+ "defaultEnvironmentId": 2
133
+ },
134
+ "repositoryStrategy": "CREATE_NEW",
135
+ "repositoryPlanRef": {
136
+ "planNo": "rplan_...",
137
+ "planHash": "64-lowercase-hex"
138
+ },
139
+ "projectStrategy": "PUBLISH_PROJECT",
140
+ "technology": {
141
+ "stackCode": "java-mci",
142
+ "templateCode": "java-mci-standalone",
143
+ "repoMode": "STANDALONE",
144
+ "parameters": {}
145
+ },
146
+ "delivery": {
147
+ "jenkinsRequired": true,
148
+ "gitopsRequired": true,
149
+ "nacosRequired": false,
150
+ "tiers": ["DEVELOP"],
151
+ "jenkins": {
152
+ "operation": "CREATE_MULTIBRANCH",
153
+ "instanceCode": "primary",
154
+ "parentFullName": "mci/develop",
155
+ "jobName": "order-service",
156
+ "tier": "DEVELOP",
157
+ "defaultBranch": "main",
158
+ "jenkinsfilePath": "Jenkinsfile",
159
+ "scanMode": "NONE"
160
+ },
161
+ "targetKey": "develop",
162
+ "profileCode": "MCI_FLUX_V1",
163
+ "profileVersion": "1",
164
+ "structuralSpec": { "workloadKind": "SPRING", "service": { "port": 8080 } },
165
+ "observerScopeIntent": {
166
+ "kustomizationNamespace": "flux-system",
167
+ "kustomizationName": "develop",
168
+ "helmReleaseNamespace": "develop",
169
+ "helmReleaseName": "order-service",
170
+ "workloadNamespace": "develop",
171
+ "workloadKind": "Deployment",
172
+ "workloadName": "order-service"
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ `CREATE_NEW` 使用 `repositoryPlanRef {planNo,planHash}`;`ATTACH_EXISTING` 使用 `repositoryRef {repositoryKey,expectedHead}`。已有本地源码但无 remote 时,先锁 Repository plan,再创建 v3 parent;不要用受管模板覆盖本地项目,也不要另建第二个 `ATTACH_EXISTING` session。
179
+
180
+ `PUBLISH_PROJECT` 必须接续 `app begin` 创建的同一会话并始终先 plan:
181
+
182
+ ```bash
183
+ numa app onboard --session <session-no> --spec <spec-file> --plan --json
184
+ numa app apply <session-no> --idempotency-key <stable-key> --json
185
+ numa app inspect <session-no> --watch --after-sequence <last-sequence> --json
186
+ numa app publication attach <session-no> --source <git-root> --commit-message <message> --client-request-id <key> --idempotency-key <key> --yes --json
187
+ numa app jenkins-binding confirm <session-no> --binding-id <id> --expected-version <version> --idempotency-key <key> --yes --json
188
+ numa app observer-scope configure <session-no> --service-binding-id <id> --kustomization-namespace <ns> --kustomization-name <name> --helm-release-namespace <ns> --helm-release-name <name> --workload-namespace <ns> --workload-kind <kind> --workload-name <name> --expected-version <version> --idempotency-key <key> --yes --json
189
+ numa app first-build decide <session-no> --decision defer --idempotency-key <key> --yes --json
190
+ numa pipeline inspect <application-code> --json
191
+ ```
192
+
193
+ Jenkins Job Control Plane 使用 `numa jenkins job plan .../apply/status/events`;默认 `scanMode=NONE`,`INDEX_ONLY` 也必须由服务端 NoTrigger 验证。`app jenkins-binding confirm` 只确认关系,不触发 build。首次 build 必须单独执行 `app first-build decide --decision trigger`;生产场景切换到 `numa-jenkins-deployment` 并提供真实审批证据。
194
+
195
+ 不要把数据库密码、SCM token 或其他 secret 放进 spec、delivery.parameters 或 build parameters。
196
+
197
+ ## 恢复规则
198
+
199
+ - 保存 `sessionNo`、`revision`、`planHash`、idempotency key、last sequence。
200
+ - 网络失败或结果未知时先使用正常 profile HTTPS 网关执行下面的只读恢复;同一次提交只复用原 idempotency key:
201
+
202
+ ```bash
203
+ numa repository status --client-request-id <original-id> --json
204
+ numa publication status --client-request-id <original-id> --json
205
+ numa jenkins job status --client-request-id <original-id> --json
206
+ numa app publication resolve <session-no> --client-request-id <original-id> --json
207
+ numa app inspect <session-no> --after-sequence <last-sequence> --json
208
+ ```
209
+
210
+ CLI 只有在写前 event cursor 之后观察到与本次 planHash/精确 intent 匹配的新持久事件时,才可能返回 `recovered_from_status=true`;既有 `WAITING_EXTERNAL` 或旧输出字段不能作为恢复证据。Repository、Publication、Jenkins 的 resolved run 还必须匹配请求 planNo 和响应中可用的稳定 workload identity。
211
+ - HTTP 2xx 后客户端 schema 解析失败不代表服务端失败。先 list/get 核实资源,禁止直接重放 POST。
212
+ - `WAITING_EXTERNAL` 使用 `resume`;可重入失败使用 `retry`;HEAD 移动使用 `reassess`。按服务端 recovery action 选择,不自行跳步骤。
213
+ - 生产 `pipeline build`、stop、retry 需要独立审批 ID 或具体 production reason;本 skill 默认只创建/核验流水线。
214
+ - 不启动或遗留 `kubectl port-forward`、SSH tunnel 或后台代理来绕过网关;只读恢复仍失败时报告 profile/API origin、request ID 和上述恢复命令,等待平台恢复。
215
+
216
+ 命令块必须是可复制的真实 shell:续行只使用行尾反斜杠,禁止字面 diff `+`/`-` 前缀。
@@ -0,0 +1,105 @@
1
+ # 应用创建与 Promote 工作流
2
+
3
+ ## 目录
4
+
5
+ - [能力自述](#能力自述)
6
+ - [源码状态路由](#源码状态路由)
7
+ - [完整父状态机](#完整父状态机)
8
+ - [安全与恢复](#安全与恢复)
9
+ - [验收](#验收)
10
+
11
+ ## 能力自述
12
+
13
+ 每次开始时基于运行时 command catalog 和 capability API 输出以下矩阵,不能依赖 skill 编写时的版本记忆:
14
+
15
+ | 能力 | 证明方式 | 不可用时 |
16
+ |---|---|---|
17
+ | Repository plan/run | `repository capabilities` 与命令目录 | 停止仓库写入 |
18
+ | Project Publication | 服务端规范 action `PLAN_PUBLICATION`,并由 command catalog 证明 `publication`、`app publication attach/resolve` 本地命令存在;`resolve` 不是独立服务端 action | 标记 `MANUAL_BRIDGE`,请求独立授权 |
19
+ | Jenkins Job plan/run | job plan/provision/status 命令 | `WAITING_EXTERNAL`,不得直接调用 Jenkins |
20
+ | Application onboarding | v2/v3 capabilities 与 plan | 不创建 Application |
21
+ | GitOps plan/apply | target/profile/service 命令 | 保留已完成 child,停止部署 |
22
+ | Observer scope/evidence | binding/scope/evidence read API | 不把 target 或 Application 声称为 ACTIVE |
23
+ | Pipeline deploy | confirmed binding 与生产审批 | 不触发 build |
24
+
25
+ 能力自述必须说明:当前 skill 可以安全完成哪些步骤、哪些步骤需要管理员、哪些步骤会触发外部写入,以及这次默认不会执行什么。
26
+ Application onboarding 以 `numa app capabilities --json` 的服务端动作自述为准,并与
27
+ `numa commands --json` 交叉验证;命令存在而服务端返回 501 时标记 `UNAVAILABLE`。
28
+
29
+ ## 源码状态路由
30
+
31
+ ### REMOTE_TRACKED
32
+
33
+ 1. 解析 remote 到平台 connection/repository。
34
+ 2. 读取 provider externalId、default branch 和 remote HEAD。
35
+ 3. 要求本地 clean HEAD 与远端目标 HEAD 一致。
36
+ 4. 生成 `USE_EXISTING`/`REGISTER_EXISTING` plan 或直接使用受管 repositoryRef。
37
+
38
+ ### LOCAL_HISTORY_WITHOUT_REMOTE
39
+
40
+ 适用于已有提交历史、clean HEAD、无任何 remote 的项目:
41
+
42
+ 1. 从 Jenkins `APP_NAME`、包名和目录名推断 application code;冲突时停止确认。
43
+ 2. 查询 SCM connection、namespace、同名 remote、CREATE capability 和初始化限制。
44
+ 3. 生成 Repository `CREATE` plan。仓库名默认等于稳定 application code,visibility 默认 PRIVATE。初始化方式必须来自 provider capability:Codeup 无空仓安全首次提交能力时使用受管 `README` 初始化,再由 publication CAS 更新同一 `README.md` 并创建其余清单文件;不得先建空仓再绕过控制平面推送。
45
+ 4. 本地只读生成受限 publication manifest;manifest 锁定 source HEAD、mode、文件数量、总字节、每文件 digest 和整体 digest,不包含内容或凭据。若包含 `100755` 且 provider=Codeup,安全连接摘要必须证明 `codeupCloneCredentialConfigured=true`;否则以 `PUBLICATION_EXECUTABLE_MODE_UNSUPPORTED` 停止,不能把 Personal AT 当 HTTPS Git 密码。
46
+ 5. 用 `app begin` 取得 session 后,在同一 session 创建 schemaVersion=3 onboarding parent plan;固定 `mode=NEW`、catalog/repository=`CREATE_NEW`、project=`PUBLISH_PROJECT`,并引用绑定该 session 的 Repository plan/ref。Repository child 完成后 parent 停在 `WAITING_EXTERNAL / ATTACH_PUBLICATION_PLAN`,此时才用 `app publication attach` 上传受控 bundle;服务端把 child consumer 固定为 `APPLICATION_ONBOARDING/<sessionNo>`,验证 parent planHash 和同一 manifest digest。客户端不能自报 consumer、remote URL、branch 或 provider credential。
47
+ 6. 远端创建或提交结果未知时复用同一 idempotency key,通过 run/events reconcile;不能直接重放成第二个仓库或第二次提交。
48
+ 7. 读回 remote HEAD/tree evidence 后继续同一个 onboarding session;不得另建 `ATTACH_EXISTING` 会话,也不得把独立 `STANDALONE` publication plan 附着到 parent。
49
+
50
+ 若 publication API 尚未发布,仍生成完整计划并标记 `MANUAL_BRIDGE`。只有用户单独确认后才能使用本机 Git 身份推送;推送前后必须验证 remote URL、branch、HEAD,且不得把 credential 写入命令、remote URL 或日志。人工桥接不是 skill 的默认路径,也不能被报告成平台闭环。
51
+
52
+ ### DIRTY_WORKTREE / UNVERSIONED_DIRECTORY
53
+
54
+ - dirty 时只列出变更数量,不读取敏感文件;停止 apply,让用户决定提交范围。
55
+ - 非 Git 目录只能选择受管模板 NEW,或先由用户建立明确版本历史;不要自动 `git init`/commit。
56
+
57
+ ## 完整父状态机
58
+
59
+ ```text
60
+ DISCOVER_AND_CLASSIFY
61
+ BEGIN_APPLICATION_SESSION
62
+ PLAN_REPOSITORY
63
+ PLAN_APPLICATION_V3
64
+ RUN_APPLICATION_PARENT
65
+ RUN_REPOSITORY_CHILD
66
+ WAIT_ATTACH_PUBLICATION_PLAN
67
+ ATTACH_PROJECT_PUBLICATION_PLAN
68
+ RUN_PROJECT_PUBLICATION_CHILD
69
+ VERIFY_REMOTE_HEAD
70
+ PLAN_JENKINS_JOB
71
+ RUN_JENKINS_JOB_NO_BUILD
72
+ SYNC_INVENTORY_AND_CONFIRM_BINDING
73
+ PLAN_GITOPS_STRUCTURE
74
+ WAIT_AUTHENTICATED_GITOPS_APPLY
75
+ CONFIGURE_OBSERVER_SCOPE
76
+ WAIT_FLUX_OBSERVER_ATTESTATION
77
+ WAIT_EXPLICIT_FIRST_BUILD
78
+ COMPLETED
79
+ ```
80
+
81
+ 已部署应用可采用 `ATTACH_APPLICATION`,但必须验证团队、repository、Jenkins 与运行态身份一致。Candidate adopt 不得创建一个与 onboarding reservation 冲突的第二个 Application。
82
+
83
+ Jenkins Job 创建、配置和 `INDEX_ONLY` scan 必须验证不会触发 build;默认 `scanMode=NONE`。首次 build 是独立 promote 决策:`DEFER` 永不触发且 parent 保持 `WAITING_EXTERNAL`,`TRIGGER` 必须使用 confirmed binding。生产 build 转入 `numa-jenkins-deployment`,要求真实审批依据。
84
+
85
+ ## 安全与恢复
86
+
87
+ - CLI 从不接受 SCM/Jenkins credential 参数;凭据由平台引用。
88
+ - publication 拒绝 `.git`、凭据文件、Secret、symlink、socket/device、绝对/父路径和超限 bundle。
89
+ - Codeup Personal AT 只证明 OpenAPI 能力;包含 `100755` 的 tree 还要求平台已托管独立 HTTPS clone username/password。只读检查安全 readiness boolean,缺失时以 `PUBLICATION_EXECUTABLE_MODE_UNSUPPORTED` 停止,不把 AT 当 Git password。
90
+ - 每个 child 保存 plan/hash、run number、idempotency key、last event sequence;onboarding publication child 只能通过 session-scoped bridge 创建。
91
+ - HTTP 2xx 后 schema 解析失败属于结果未知;先 list/status/get,不能直接重放。
92
+ - 普通 profile HTTPS 网关失败时,Repository/standalone Publication/Jenkins 先按原 clientRequestId 查 `status`,普通 session action 先 `app inspect`;publication attach 必须先按原 `sessionNo/clientRequestId` 执行 `app publication resolve`。其 retryable 404 只能稍后重查,禁止自动重放 attach;不要启动或遗留 port-forward/tunnel 旁路。
93
+ - session action 的自动恢复必须以写前 event cursor 为基线,只接受 cursor 之后与本次 planHash/精确 intent 匹配的新持久事件;既有 `WAITING_EXTERNAL` 或旧 observer/build/binding 字段不是本次写成功的证据。child run resolve 必须至少匹配请求 planNo,并校验响应中可用的 repository/workload identity。
94
+ - Jenkins scan 不等于 build;观察到意外 build 时停止父流程并报告。
95
+ - GitOps target 只有 topology validation 时保持 DRAFT;Jenkins attestation 最多推进 VERIFYING,只有独立 Flux Observer evidence 能推进 ACTIVE。
96
+
97
+ ## 验收
98
+
99
+ - 远端仓库唯一,默认分支、visibility、owner team 与确认一致。
100
+ - remote commit/tree 与 publication manifest evidence 一致。
101
+ - Application 只创建/接管一个,Repository 关系正确。
102
+ - Multibranch Job 配置 digest 与计划一致,未意外触发 build。
103
+ - Jenkins binding 为 CONFIRMED,目标 branch 可构建。
104
+ - GitOps service binding 和 exact Observer scope 存在;configRevision 与 observedRevision 一致后才 ACTIVE。
105
+ - 未经独立生产授权不得触发 build;触发后必须以 Jenkins 终态和 Flux/Observer evidence 验收。