@numa-tech/numa 1.13.4 → 1.14.0
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.
- package/README.md +140 -26
- package/dist/application-onboarding/client.d.ts +1 -0
- package/dist/application-onboarding/commands.d.ts +2 -0
- package/dist/application-onboarding/commands.js +41 -16
- package/dist/application-onboarding/commands.js.map +1 -1
- package/dist/application-onboarding/errors.js +1 -1
- package/dist/application-onboarding/errors.js.map +1 -1
- package/dist/application-onboarding/schemas.d.ts +8 -0
- package/dist/application-onboarding/schemas.js +4 -2
- package/dist/application-onboarding/schemas.js.map +1 -1
- package/dist/application-onboarding/scm-credentials.d.ts +5 -2
- package/dist/application-onboarding/scm-credentials.js +64 -13
- package/dist/application-onboarding/scm-credentials.js.map +1 -1
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.js +252 -15
- package/dist/command-catalog.js.map +1 -1
- package/dist/integration-bootstrap/client.d.ts +23 -0
- package/dist/integration-bootstrap/client.js +124 -0
- package/dist/integration-bootstrap/client.js.map +1 -0
- package/dist/integration-bootstrap/commands.d.ts +20 -0
- package/dist/integration-bootstrap/commands.js +129 -0
- package/dist/integration-bootstrap/commands.js.map +1 -0
- package/dist/integration-bootstrap/schemas.d.ts +422 -0
- package/dist/integration-bootstrap/schemas.js +216 -0
- package/dist/integration-bootstrap/schemas.js.map +1 -0
- package/dist/jenkins/commands.d.ts +10 -0
- package/dist/jenkins/commands.js +15 -0
- package/dist/jenkins/commands.js.map +1 -0
- package/dist/jenkins-jobs/client.d.ts +12 -12
- package/dist/jenkins-jobs/schemas.d.ts +96 -8
- package/dist/jenkins-jobs/schemas.js +2 -2
- package/dist/jenkins-jobs/schemas.js.map +1 -1
- package/dist/pipeline/client.d.ts +5 -0
- package/dist/pipeline/commands.js +2 -0
- package/dist/pipeline/commands.js.map +1 -1
- package/dist/pipeline/schemas.d.ts +6 -0
- package/dist/pipeline/schemas.js +2 -0
- package/dist/pipeline/schemas.js.map +1 -1
- package/dist/platform-build-job-replans/client.d.ts +283 -0
- package/dist/platform-build-job-replans/client.js +148 -0
- package/dist/platform-build-job-replans/client.js.map +1 -0
- package/dist/platform-build-job-replans/commands.d.ts +6 -0
- package/dist/platform-build-job-replans/commands.js +371 -0
- package/dist/platform-build-job-replans/commands.js.map +1 -0
- package/dist/platform-build-job-replans/schemas.d.ts +145 -0
- package/dist/platform-build-job-replans/schemas.js +150 -0
- package/dist/platform-build-job-replans/schemas.js.map +1 -0
- package/dist/platform-build-rollouts/client.d.ts +346 -0
- package/dist/platform-build-rollouts/client.js +153 -0
- package/dist/platform-build-rollouts/client.js.map +1 -0
- package/dist/platform-build-rollouts/commands.d.ts +98 -0
- package/dist/platform-build-rollouts/commands.js +465 -0
- package/dist/platform-build-rollouts/commands.js.map +1 -0
- package/dist/platform-build-rollouts/schemas.d.ts +348 -0
- package/dist/platform-build-rollouts/schemas.js +257 -0
- package/dist/platform-build-rollouts/schemas.js.map +1 -0
- package/dist/platform-builds/client.d.ts +147 -0
- package/dist/platform-builds/client.js +115 -0
- package/dist/platform-builds/client.js.map +1 -0
- package/dist/platform-builds/commands.d.ts +7 -0
- package/dist/platform-builds/commands.js +226 -0
- package/dist/platform-builds/commands.js.map +1 -0
- package/dist/platform-builds/schemas.d.ts +127 -0
- package/dist/platform-builds/schemas.js +66 -0
- package/dist/platform-builds/schemas.js.map +1 -0
- package/dist/publications/client.d.ts +30 -0
- package/dist/publications/client.js +6 -1
- package/dist/publications/client.js.map +1 -1
- package/dist/publications/commands.d.ts +2 -0
- package/dist/publications/commands.js +84 -5
- package/dist/publications/commands.js.map +1 -1
- package/dist/repositories/client.d.ts +6 -0
- package/dist/repositories/commands.d.ts +3 -1
- package/dist/repositories/commands.js +22 -8
- package/dist/repositories/commands.js.map +1 -1
- package/dist/repositories/errors.d.ts +2 -1
- package/dist/repositories/errors.js +4 -2
- package/dist/repositories/errors.js.map +1 -1
- package/dist/repositories/schemas.d.ts +32 -0
- package/dist/repositories/schemas.js +4 -0
- package/dist/repositories/schemas.js.map +1 -1
- package/package.json +4 -4
- package/skills/numa-create-application/SKILL.md +26 -13
- package/skills/numa-create-application/agents/openai.yaml +2 -2
- package/skills/numa-create-application/evals/evals.json +72 -12
- package/skills/numa-create-application/references/checklist.md +12 -5
- package/skills/numa-create-application/references/numa-cli.md +55 -13
- package/skills/numa-create-application/references/promote-workflows.md +63 -24
- package/skills/numa-create-application/scripts/inspect-project.mjs +1 -0
package/README.md
CHANGED
|
@@ -194,8 +194,9 @@ numa config \
|
|
|
194
194
|
| `numa registry approvals/router/audit` | 需登录 | 两人制发布、Router 健康/对账和追加式审计 |
|
|
195
195
|
| `numa registry tui` | 需登录 | 打开 namespace、Skills、MCP、审批、Router、审计全屏工作台 |
|
|
196
196
|
| `numa app capabilities/begin/onboard/publication/jenkins-binding/observer-scope/first-build/...` | 需登录 | 自述运行时能力,创建、接入并按独立 child gate Promote 应用 |
|
|
197
|
-
| `numa publication scan/plan/apply/status/events/...` | 公开扫描/需登录写入 | 把 clean Git HEAD 通过受控 bundle
|
|
197
|
+
| `numa publication scan/plan/apply/status/events/...` | 公开扫描/需登录写入 | 把 clean Git HEAD 通过受控 bundle 发布到受管仓库;plan 可按原 request ID 只读恢复 |
|
|
198
198
|
| `numa jenkins job plan/apply/status/events/...` | 需登录 | 创建/校验 Jenkins Multibranch Job,默认不扫描、不构建 |
|
|
199
|
+
| `numa pipeline platform-build trigger/resolve/status/log/stop` | 需登录 | 新应用 v2 immutable snapshot 构建;无任意参数,GitOps 写由平台 SCM CAS 完成 |
|
|
199
200
|
| `numa app options` | 需登录 | 查询应用归属所需的团队、系统、业务域和环境 ID |
|
|
200
201
|
| `numa app candidate list/inspect/preview/review/adopt` | 需登录 | 审查应用发现候选并确认收录,服务端执行最终管理员授权和审计 |
|
|
201
202
|
| `numa media capabilities` | 需登录 | 查询媒体 API、Provider 和版本能力 |
|
|
@@ -535,6 +536,29 @@ numa app first-build decide <session-no> --decision defer \
|
|
|
535
536
|
--idempotency-key defer-code-index-first-build --yes --json
|
|
536
537
|
```
|
|
537
538
|
|
|
539
|
+
onboarding v3 在 GitOps structural apply 完成后会于同一 session/task 内自动执行
|
|
540
|
+
server-internal `gitops-platform-writer-bootstrap/v2`,在 Observer 和 first-build 之前锁定并只读写
|
|
541
|
+
base release、exact overlay values、overlay kustomization 三个服务文件。这不是新 CLI
|
|
542
|
+
或独立 child plan;CLI 只通过原有 `app inspect <session-no> [--watch] [--after-sequence]`
|
|
543
|
+
读取 `GITOPS_V2_WRITER_BOOTSTRAP` 事件。只有 exact contract/identity/revision/digest 匹配的
|
|
544
|
+
成功事件才能继续;`PENDING` 只继续等待原 session,`UNKNOWN` 或 drift 均 fail closed。
|
|
545
|
+
该阶段不调用 v1 `legacy-image-migration`,不枚举、读取或改写 Secret,也不新建
|
|
546
|
+
Application、session、binding 或 target。
|
|
547
|
+
|
|
548
|
+
若事件进入 `UNKNOWN`,先只读检查原 session;普通 status/inspect 和 first-build 的未知结果恢复
|
|
549
|
+
都不会重启 bootstrap。只有服务端把同一内部步骤标记为可重入失败时,用户才显式调用既有的
|
|
550
|
+
通用会话恢复命令;服务端据此恢复原 run/key,不创建新的 bootstrap 请求或业务身份:
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
numa app inspect <session-no> --after-sequence <last-sequence> --json
|
|
554
|
+
numa app retry <session-no> --json
|
|
555
|
+
numa app inspect <session-no> --watch --after-sequence <last-sequence> --json
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
`app retry` 不接受 bootstrap、SCM、path、Secret、binding、target 或 first-build 参数;调用后仍须等到
|
|
559
|
+
同一 `GITOPS_V2_WRITER_BOOTSTRAP` 的 exact 成功证据。若状态仍为 `UNKNOWN` 或出现 drift,继续阻断
|
|
560
|
+
Observer/first-build,禁止重放 first-build POST、手工修改 SCM 或改用新 session/identity。
|
|
561
|
+
|
|
538
562
|
`app publication attach --json` 只返回 session/plan 标识、manifest 计数和 tree digest 摘要,不返回
|
|
539
563
|
完整 session draft/plan、manifest path、本地绝对路径或文件内容。若写响应在网关处变成结果未知,
|
|
540
564
|
CLI 会以原 `sessionNo/clientRequestId` 有界轮询固定的 `GET publication-plan/resolve`;只有 200
|
|
@@ -543,6 +567,19 @@ CLI 会以原 `sessionNo/clientRequestId` 有界轮询固定的 `GET publication
|
|
|
543
567
|
`app publication resolve` 重查;仍无确定结果时返回 `onboarding_publication_result_unknown`,不自动
|
|
544
568
|
重放 attach。
|
|
545
569
|
|
|
570
|
+
独立 `STANDALONE` Publication(不属于 onboarding parent)在 plan POST 的 500/504、连接中断或无效
|
|
571
|
+
2xx 后会自动用原 `clientRequestId` 有界调用同一只读 resolve API;POST 始终只发一次。恢复结果必须仍是
|
|
572
|
+
`STANDALONE` 且 `repositoryKey` 与请求一致,否则 fail closed:
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
numa publication plan create --source ./project --repository-key <repository-key> \
|
|
576
|
+
--commit-message 'feat: publish source' --client-request-id <stable-id> \
|
|
577
|
+
--idempotency-key <stable-id> --json
|
|
578
|
+
numa publication plan resolve --client-request-id <stable-id> --json
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
`PUBLICATION_PLAN_NOT_RESOLVED` 的 retryable 404 只表示可稍后继续 GET;不得重放 plan create。
|
|
582
|
+
|
|
546
583
|
v3 structural spec 只允许 MCI_FLUX_V1 结构字段,拒绝 image、仓库/分支/namespace/path、raw
|
|
547
584
|
Kubernetes Secret 和明文敏感环境变量。Job Control Plane 默认 `scanMode=NONE`;`INDEX_ONLY`
|
|
548
585
|
也必须通过服务端 NoTrigger 配置验证,不能等同于 build。
|
|
@@ -580,14 +617,20 @@ Application Onboarding 契约定义。
|
|
|
580
617
|
SCM 目录和连接诊断使用同一身份。仓库查询支持服务端 search/cursor 分页,返回稳定的
|
|
581
618
|
`externalId`、`defaultBranch`、`headRevision`;向导选中仓库后会把 `headRevision` 固定为
|
|
582
619
|
`expectedHead`。HTTP 429 会保留服务端 `Retry-After` 诊断,Provider 未安装(501)时 TUI
|
|
583
|
-
明确退回手工填写稳定标识。Codeup
|
|
584
|
-
|
|
620
|
+
明确退回手工填写稳定标识。Codeup 安全摘要分别显示 OpenAPI Personal AT readiness
|
|
621
|
+
`codeup_access_token_configured` 与 HTTPS clone credential readiness
|
|
622
|
+
`codeup_clone_credential_configured`,但只有
|
|
623
|
+
`codeup_credential_readiness_available=true` 时才解释这两个布尔值。availability 为 `false` 或字段
|
|
624
|
+
缺失时,即使旧响应显式返回 configured=`false`,也保持 `unknown`;只有 availability=`true` 且
|
|
625
|
+
configured=`false` 才是 `missing`。不能把 `capabilities.executable_mode` 当作 credential 证据。
|
|
626
|
+
含 `100755` 文件时只有 availability 与 clone configured 同时为 `true` 才能继续 Publication:
|
|
585
627
|
|
|
586
628
|
```bash
|
|
587
629
|
numa app scm list --provider codeup --json
|
|
588
630
|
numa app scm inspect codeup-main --repositories --search order --limit 50 --json
|
|
589
631
|
numa app scm inspect codeup-main --repositories --cursor '<next-cursor>' --limit 50 --json
|
|
590
632
|
numa app scm probe codeup-main --json
|
|
633
|
+
numa repository connection list --json
|
|
591
634
|
```
|
|
592
635
|
|
|
593
636
|
仓库生命周期也可以脱离应用入驻流程单独使用。先查询 Provider 返回的稳定 namespace
|
|
@@ -644,9 +687,9 @@ numa gitops service plan \
|
|
|
644
687
|
--spec gitops-service.json \
|
|
645
688
|
--json
|
|
646
689
|
|
|
647
|
-
#
|
|
690
|
+
# 仅旧 v1 应用使用:只用受管引用规划 legacy Jenkins image writer 迁移;不接受 YAML/path/image/secret
|
|
648
691
|
numa gitops service legacy-image-migration plan \
|
|
649
|
-
--application
|
|
692
|
+
--application legacy-order-service \
|
|
650
693
|
--target prd \
|
|
651
694
|
--profile MCI_FLUX_V1 \
|
|
652
695
|
--json
|
|
@@ -654,7 +697,7 @@ numa gitops service legacy-image-migration plan \
|
|
|
654
697
|
# 使用 plan 原样返回的 number/hash;结果不明时必须复用同一 Idempotency-Key
|
|
655
698
|
numa gitops service apply gplan_01 \
|
|
656
699
|
--plan-hash <64-hex> \
|
|
657
|
-
--idempotency-key
|
|
700
|
+
--idempotency-key legacy-order-prd-image-migration-apply-1 \
|
|
658
701
|
--yes --json
|
|
659
702
|
|
|
660
703
|
# status/events 同时接受 stable runNo 和数字 ID
|
|
@@ -680,7 +723,12 @@ spec 不得包含整个 `image`,也不得包含应用、环境、namespace、r
|
|
|
680
723
|
`GITOPS_IMAGE_REPOSITORY_UNRESOLVED` 阻断,不会猜测镜像地址。返回的 `canonicalSpecHash`、
|
|
681
724
|
`planHash`、`baseRevision` 和 `sideEffects` 是后续审阅的锁定证据。
|
|
682
725
|
|
|
683
|
-
`legacy-image-migration plan`
|
|
726
|
+
`legacy-image-migration plan` 只适用于明确保留 legacy/v1 writer 的旧应用,严格只提交
|
|
727
|
+
`applicationCode/targetKey/profileCode/profileVersion/serviceId`。新应用 v2 不调用该接口;它在
|
|
728
|
+
onboarding v3 GitOps structural apply 之后由服务端内部自动执行
|
|
729
|
+
`gitops-platform-writer-bootstrap/v2`,且只读写该服务的 base release、exact overlay values 和
|
|
730
|
+
overlay kustomization 三个受管文件。CLI 无 bootstrap 命令,只从原 session events 读取
|
|
731
|
+
`GITOPS_V2_WRITER_BOOTSTRAP`;不枚举或修改同一 overlay 的 sibling Secret。
|
|
684
732
|
路径、image pointers 和文件变更由服务端派生;CLI 只输出 `READY/BLOCKED`、plan number/hash、
|
|
685
733
|
changed file count、blocker/recovery、warnings 和 side effects,不输出 path/diff/pointer。`READY` 后复用
|
|
686
734
|
`gitops service apply`。该 plan API 没有 Idempotency-Key 或 resolve-by-key,因此响应不明时必须
|
|
@@ -691,49 +739,115 @@ fail closed,不自动重放;只有获得 plan number 后才可用 status/eve
|
|
|
691
739
|
`REVIEWED_CHANGE` 会进入 `WAITING_REVIEW` 并返回审查地址。apply 请求只包含 `planNumber`、
|
|
692
740
|
`planHash` 和 `Idempotency-Key`,不接受任意 repository/path/image 输入。
|
|
693
741
|
|
|
694
|
-
## Jenkins GitOps image writer rollout
|
|
742
|
+
## Jenkins GitOps image writer rollout v1
|
|
695
743
|
|
|
696
|
-
Jenkins rollout 管理位于 `numa jenkins gitops-rollout`。读取需 Jenkins reader;
|
|
697
|
-
只允许 `mci-devops-platform-ops-admin`。所有写入都要求稳定
|
|
698
|
-
|
|
744
|
+
旧 Jenkins rollout 管理位于 `numa jenkins gitops-rollout`。读取需 Jenkins reader;
|
|
745
|
+
plan/apply/readiness 只允许 `mci-devops-platform-ops-admin`。所有写入都要求稳定
|
|
746
|
+
`Idempotency-Key` 和 `--yes`,且保持 backend `jenkins-gitops-rollout/v1` 的 strict DTO 和行为。
|
|
747
|
+
该命令族不包含 automatic configure;新应用不应通过它隐式升级。
|
|
699
748
|
|
|
700
749
|
```bash
|
|
701
|
-
#
|
|
750
|
+
# 旧 v1 contract 固定为 gitops-image-delivery/v1
|
|
702
751
|
numa jenkins gitops-rollout plan enable-platform \
|
|
703
|
-
--application
|
|
752
|
+
--application legacy-order-service --instance numa \
|
|
704
753
|
--shared-library-revision 230e0f00444dfd1874e1ab3e624381341a0c31c5 \
|
|
705
|
-
--idempotency-key
|
|
754
|
+
--idempotency-key legacy-order-v1-rollout-plan-1 --yes --json
|
|
706
755
|
|
|
707
756
|
numa jenkins gitops-rollout plan get <plan-no> --json
|
|
708
757
|
|
|
709
758
|
# apply 只持久化 fail-closed rollout gate,不写 Jenkins 或触发 build
|
|
710
759
|
numa jenkins gitops-rollout apply \
|
|
711
760
|
--plan-no <plan-no> --plan-hash <64hex> \
|
|
712
|
-
--idempotency-key
|
|
761
|
+
--idempotency-key legacy-order-v1-rollout-apply-1 --yes --json
|
|
713
762
|
|
|
714
|
-
numa jenkins gitops-rollout list --application
|
|
763
|
+
numa jenkins gitops-rollout list --application legacy-order-service --instance numa --json
|
|
715
764
|
numa jenkins gitops-rollout get <rollout-no> --json
|
|
716
765
|
|
|
717
|
-
#
|
|
718
|
-
numa jenkins gitops-rollout readiness <rollout-no> \
|
|
719
|
-
--desired-mode
|
|
766
|
+
# 旧 v1 readiness 是人工证明,不是 live-read
|
|
767
|
+
numa jenkins gitops-rollout readiness <legacy-rollout-no> \
|
|
768
|
+
--desired-mode legacy --expected-version <version> \
|
|
720
769
|
--operator-action-reference CHG-20260824-001 \
|
|
721
|
-
--idempotency-key
|
|
770
|
+
--idempotency-key legacy-order-readiness-1 --yes --json
|
|
722
771
|
```
|
|
723
772
|
|
|
724
|
-
`readiness` 固定是 `MANUAL_OPERATOR_ATTESTED`,不是 Jenkins live-read。CLI 从当前
|
|
725
|
-
exact public tuple 和固定 credential reference names,不接受 secret value、raw XML、env map
|
|
726
|
-
credential value。响应不明时,apply 只有在 list 中发现 exact application/instance/plan mode
|
|
727
|
-
|
|
773
|
+
`readiness` 固定是 `MANUAL_OPERATOR_ATTESTED`,不是 Jenkins live-read。CLI 从当前
|
|
774
|
+
rollout 回传 exact public tuple 和固定 credential reference names,不接受 secret value、raw XML、env map
|
|
775
|
+
或 credential value。响应不明时,apply 只有在 list 中发现 exact application/instance/plan mode 且 durable
|
|
776
|
+
version 增长才恢复;readiness 只有 GET 同 rollout 显示 exact reference/mode/status/identity
|
|
728
777
|
且 version 增长才恢复。其余情况均返回 result unknown,不自动重放。
|
|
729
778
|
|
|
779
|
+
## Platform build rollout v2
|
|
780
|
+
|
|
781
|
+
新应用的 Jenkins 配置门禁位于独立 `numa jenkins platform-build-rollout`,与 v1
|
|
782
|
+
`gitops-rollout` 的 API、DTO、表和状态机分离。v2 只支持 `ENABLE_PLATFORM`/
|
|
783
|
+
`DISABLE_PLATFORM`,没有 manual readiness,不要求 Jenkins 持有 Flux Git credential。
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
numa jenkins platform-build-rollout plan enable-platform \
|
|
787
|
+
--application code-index --instance numa \
|
|
788
|
+
--shared-library-revision <approved-v2-shared-library-revision> \
|
|
789
|
+
--idempotency-key code-index-v2-rollout-plan-1 --yes --json
|
|
790
|
+
|
|
791
|
+
numa jenkins platform-build-rollout plan get <plan-no> --json
|
|
792
|
+
numa jenkins platform-build-rollout apply \
|
|
793
|
+
--plan-no <plan-no> --plan-hash <64hex> \
|
|
794
|
+
--idempotency-key code-index-v2-rollout-apply-1 --yes --json
|
|
795
|
+
numa jenkins platform-build-rollout list --application code-index --instance numa --json
|
|
796
|
+
numa jenkins platform-build-rollout get <rollout-no> --json
|
|
797
|
+
numa jenkins platform-build-rollout configure <rollout-no> \
|
|
798
|
+
--expected-version <version> \
|
|
799
|
+
--idempotency-key code-index-v2-auto-configure-1 --yes --json
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
`configure` 的 strict body 只有 `expectedVersion`,不接收 public tuple、env、XML、Groovy、
|
|
803
|
+
token、credential ID/value 或 operator attestation。服务端只有在返回 exact
|
|
804
|
+
`READY/JENKINS_API_VERIFIED/VERIFIED`、writer credential readiness、observed shared-library/source
|
|
805
|
+
revision 以及 Jenkinsfile/profile/configuration digest 时才放行。响应不明时 CLI 只 GET
|
|
806
|
+
同一 rollout,不重放 POST。
|
|
807
|
+
|
|
808
|
+
automatic configure 之前,Project Publication CAS 必须发布 exact
|
|
809
|
+
`@Library('mciShareLib@<approvedSharedLibraryRevision>') _`、唯一 `platformBuildEntry()` 和 strict
|
|
810
|
+
`.mci/platform-build.yaml`。生产 snapshot 执行服务端固定 wrapper,不加载应用 Jenkinsfile;
|
|
811
|
+
Jenkins 只 checkout 锁定源码并构建/push 镜像,Flux SCM CAS 由 DevOps 服务端执行。
|
|
812
|
+
|
|
813
|
+
## Platform build v2
|
|
814
|
+
|
|
815
|
+
新应用使用独立 `pipeline platform-build` 表面;旧 `pipeline build/builds/status/log/stop/retry` 的 v1
|
|
816
|
+
请求和响应保持不变。v2 不接受任意 Jenkins 参数,生产审批依据只保留在平台审计中。镜像构建完成后,
|
|
817
|
+
Jenkins 只提交一次 image intent;DevOps 服务端持有 Flux writer credential,并按锁定 contract/HEAD
|
|
818
|
+
执行 SCM CAS。运行态完成证据仍来自独立 Observer。
|
|
819
|
+
|
|
820
|
+
```bash
|
|
821
|
+
numa pipeline platform-build trigger code-index \
|
|
822
|
+
--tier production --branch master \
|
|
823
|
+
--idempotency-key code-index-prd-first-v2 \
|
|
824
|
+
--production-reason '新运维系统上线前首次生产构建与部署' \
|
|
825
|
+
--yes --wait --json
|
|
826
|
+
|
|
827
|
+
# trigger 响应未知时只读恢复,绝不重放 POST
|
|
828
|
+
numa pipeline platform-build resolve \
|
|
829
|
+
--client-request-id code-index-prd-first-v2 --json
|
|
830
|
+
numa pipeline platform-build status <request-id> --watch --json
|
|
831
|
+
numa pipeline platform-build log <request-id> --start 0 --json
|
|
832
|
+
|
|
833
|
+
# stop 同样只发送一次;未知后只读同一个 request
|
|
834
|
+
numa pipeline platform-build stop <request-id> \
|
|
835
|
+
--idempotency-key code-index-prd-stop-v2 \
|
|
836
|
+
--production-reason '停止异常的首次生产构建' \
|
|
837
|
+
--yes --json
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
首次 v2 build 的正式入口仍由原 onboarding session 的 first-build action 创建,独立命令用于恢复与
|
|
841
|
+
运维;不得新建第二 Application、Repository、session、binding 或 target。任何 result unknown 都必须
|
|
842
|
+
使用原 key/request 只读 resolve/status,不能换 key 重放。
|
|
843
|
+
|
|
730
844
|
SCM 管理接口位于 `/api/v1/admin/scm-connections`,最终权限始终由网关和后端按 canonical
|
|
731
845
|
Client Role 校验。metadata JSON 只允许 provider、URL、组织、auth type 以及服务端托管的
|
|
732
846
|
`aliyunAccountId`/`aliyunAssumeRoleId` 引用;Numa 不接收云 AK。CODEUP 必须引用
|
|
733
847
|
`aliyunAccountId`,没有 access token 时直接使用服务端 Aliyun identity,不写入空 credential。
|
|
734
848
|
Codeup Personal AT 只用于 OpenAPI,不能当作 HTTPS Git 密码;包含 `100755` 文件的 Publication
|
|
735
849
|
另需 Codeup 的 HTTPS clone username/password。GitHub App/PAT 和这三项 Codeup credential 均为
|
|
736
|
-
WRITE_ONLY
|
|
850
|
+
WRITE_ONLY,只能从隐藏终端提示、owner-only 文件或重定向 stdin 读取,禁止放在 argv、环境变量和 metadata
|
|
737
851
|
JSON 中,且不会出现在输出或错误中。安全响应只返回 credential readiness boolean:
|
|
738
852
|
|
|
739
853
|
```bash
|
|
@@ -741,7 +855,7 @@ numa app scm create --input codeup.json --json
|
|
|
741
855
|
chmod 600 github-app.private.json
|
|
742
856
|
numa app scm create --input github.json --credential-file github-app.private.json --json
|
|
743
857
|
numa app scm rotate github-main --revision 4 --credential-stdin --yes --json < github-pat.private.json
|
|
744
|
-
numa app scm rotate codeup-main --revision 5 --credential-
|
|
858
|
+
numa app scm rotate codeup-main --revision 5 --credential-prompt --yes --json
|
|
745
859
|
numa app scm disable old-codeup --revision 7 --yes --json
|
|
746
860
|
```
|
|
747
861
|
|
|
@@ -155,6 +155,7 @@ export declare class OnboardingClient implements OnboardingApi {
|
|
|
155
155
|
health: string;
|
|
156
156
|
capabilities: Record<string, boolean>;
|
|
157
157
|
credentialConfigured?: boolean | undefined;
|
|
158
|
+
codeupCredentialReadinessAvailable?: boolean | undefined;
|
|
158
159
|
codeupAccessTokenConfigured?: boolean | undefined;
|
|
159
160
|
codeupCloneCredentialConfigured?: boolean | undefined;
|
|
160
161
|
lastCheckedAt?: string | null | undefined;
|
|
@@ -48,6 +48,7 @@ export interface PublicationAttachmentRecoveryOptions {
|
|
|
48
48
|
delaysMs?: number[];
|
|
49
49
|
sleep?: (milliseconds: number) => Promise<void>;
|
|
50
50
|
}
|
|
51
|
+
export declare function canAttachPublicationPlan(inspection: OnboardingInspection): boolean;
|
|
51
52
|
export type OnboardingRecoveryAction = "cancel" | "retry" | "resume" | "reassess";
|
|
52
53
|
export type ApplicationCatalogOptionType = "team" | "system" | "business-domain" | "environment";
|
|
53
54
|
export declare function publicOnboardingEvent(event: OnboardingEvent): OnboardingEvent;
|
|
@@ -56,6 +57,7 @@ export declare function parseOnboardingMode(value: string): OnboardingMode;
|
|
|
56
57
|
export declare function parseApplicationCatalogOptionType(value: string): ApplicationCatalogOptionType;
|
|
57
58
|
export declare function resolveScmConnection(client: Pick<OnboardingApi, "listScmConnections">, code: string): Promise<ScmConnection>;
|
|
58
59
|
export declare function scmCredentialUpdate(version: number, authType: ScmAuthType, credential: ScmCredentialBundle): ScmCredentialUpdate;
|
|
60
|
+
export declare function scmConnectionLine(connection: ScmConnection): string;
|
|
59
61
|
export declare function readOnboardingSpec(path: string): Promise<OnboardingSpec>;
|
|
60
62
|
export declare function executeOnboardingSpec(client: OnboardingApi, spec: OnboardingSpec, options?: {
|
|
61
63
|
mode?: OnboardingMode;
|
|
@@ -24,6 +24,20 @@ const STATE_SUMMARIES = {
|
|
|
24
24
|
FAILED: "服务端执行失败;请依据事件中的 errorCode 和 recoveryAction 恢复",
|
|
25
25
|
CANCELLED: "服务端已取消尚未开始的步骤;既有外部资源未回滚"
|
|
26
26
|
};
|
|
27
|
+
export function canAttachPublicationPlan(inspection) {
|
|
28
|
+
const { session } = inspection;
|
|
29
|
+
if (session.state !== "WAITING_EXTERNAL" || !session.planHash)
|
|
30
|
+
return false;
|
|
31
|
+
if (session.currentStep === "ATTACH_PUBLICATION_PLAN")
|
|
32
|
+
return true;
|
|
33
|
+
if (session.currentStep !== "EXECUTION")
|
|
34
|
+
return false;
|
|
35
|
+
const latest = inspection.events.at(-1);
|
|
36
|
+
return latest?.eventType === "WAITING_EXTERNAL"
|
|
37
|
+
&& latest.stepCode === "ATTACH_PUBLICATION_PLAN"
|
|
38
|
+
&& latest.stepState === "WAITING"
|
|
39
|
+
&& latest.output?.planHash === session.planHash;
|
|
40
|
+
}
|
|
27
41
|
function addExamples(command, examples, notes = []) {
|
|
28
42
|
const noteSection = notes.length
|
|
29
43
|
? `\n说明:\n${notes.map((item) => ` - ${item}`).join("\n")}\n`
|
|
@@ -187,14 +201,17 @@ export function scmCredentialUpdate(version, authType, credential) {
|
|
|
187
201
|
return { version, githubPat: credential };
|
|
188
202
|
return { version, codeup: credential };
|
|
189
203
|
}
|
|
190
|
-
function
|
|
204
|
+
function readiness(value, available) {
|
|
205
|
+
if (available !== true || value == null)
|
|
206
|
+
return "unknown";
|
|
207
|
+
return value ? "ready" : "missing";
|
|
208
|
+
}
|
|
209
|
+
export function scmConnectionLine(connection) {
|
|
191
210
|
const enabled = Object.entries(connection.capabilities).filter(([, value]) => value).map(([key]) => key);
|
|
192
|
-
const
|
|
193
|
-
? `\tcodeup-clone:${connection.codeupCloneCredentialConfigured
|
|
194
|
-
? "unknown"
|
|
195
|
-
: connection.codeupCloneCredentialConfigured ? "ready" : "missing"}`
|
|
211
|
+
const codeupReadiness = connection.provider === "CODEUP"
|
|
212
|
+
? `\tcodeup-at:${readiness(connection.codeupAccessTokenConfigured, connection.codeupCredentialReadinessAvailable)}\tcodeup-clone:${readiness(connection.codeupCloneCredentialConfigured, connection.codeupCredentialReadinessAvailable)}`
|
|
196
213
|
: "";
|
|
197
|
-
return `${connection.code}\t${connection.provider}\t${connection.health}\t${connection.organizationKey}\t${enabled.join(",") || "no-capabilities"}${
|
|
214
|
+
return `${connection.code}\t${connection.provider}\t${connection.health}\t${connection.organizationKey}\t${enabled.join(",") || "no-capabilities"}${codeupReadiness}`;
|
|
198
215
|
}
|
|
199
216
|
function repositoryLine(repository) {
|
|
200
217
|
return `${repository.externalId}\t${repository.fullName ?? repository.name}\t${repository.defaultBranch ?? "-"}\t${repository.headRevision ?? "-"}${repository.archived ? "\tARCHIVED" : ""}`;
|
|
@@ -649,10 +666,10 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
649
666
|
安全边界:
|
|
650
667
|
普通诊断只显示 code、provider、organization、health 和 capability。
|
|
651
668
|
live probe 与连接变更由服务端校验平台管理员权限和乐观锁 version。
|
|
652
|
-
provider credential
|
|
669
|
+
provider credential 只能来自隐藏终端提示、权限受限文件或重定向 stdin;禁止通过 argv、环境变量或普通 JSON 输出传递。
|
|
653
670
|
Codeup 云 AK/Role 只能引用已有 aliyunAccountId/aliyunAssumeRoleId,Numa 不读取或保存云 AK。
|
|
654
671
|
Codeup accessToken 只用于 OpenAPI;含 100755 文件的 Publication 另需 HTTPS cloneUsername/clonePassword。
|
|
655
|
-
|
|
672
|
+
三者只从隐藏终端提示、chmod 600 文件或重定向 stdin 写入;未提供时使用服务端 Aliyun identity,不提交空 credential bundle。
|
|
656
673
|
`);
|
|
657
674
|
addExamples(scm.command("list")
|
|
658
675
|
.description("列出当前用户可见的安全 SCM 连接摘要")
|
|
@@ -793,6 +810,7 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
793
810
|
.requiredOption("--input <file>", "无 secret 的连接 metadata JSON")
|
|
794
811
|
.option("--credential-file <file>", "仅 owner 可读(chmod 600)的 provider credential JSON")
|
|
795
812
|
.option("--credential-stdin", "从重定向 stdin 读取 provider credential JSON")
|
|
813
|
+
.option("--credential-prompt", "在交互终端隐藏输入 provider credential")
|
|
796
814
|
.action(async (options, command) => {
|
|
797
815
|
const onboarding = client();
|
|
798
816
|
const input = await readScmAdminConnectionInput(options.input);
|
|
@@ -808,7 +826,7 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
808
826
|
await output(command, { ok: true, connection }, `${connection.code}\t${connection.status}\tversion:${connection.version}\tcredential:${connection.credentialConfigured ? "configured" : "missing"}\tcodeup-at:${connection.codeupAccessTokenConfigured ? "ready" : "missing"}\tcodeup-clone:${connection.codeupCloneCredentialConfigured ? "ready" : "missing"}`);
|
|
809
827
|
}), [
|
|
810
828
|
"numa app scm create --input github.json --credential-file github-app.private.json --json",
|
|
811
|
-
"numa app scm create --input codeup.json --json"
|
|
829
|
+
"numa app scm create --input codeup.json --credential-prompt --json"
|
|
812
830
|
]);
|
|
813
831
|
addExamples(scm.command("update <code>")
|
|
814
832
|
.description("平台管理员按 version 更新连接 metadata;身份字段变更可能使已有 plan 失效")
|
|
@@ -833,11 +851,12 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
833
851
|
.requiredOption("--revision <number>", "当前乐观锁 version")
|
|
834
852
|
.option("--credential-file <file>", "仅 owner 可读(chmod 600)的 provider credential JSON")
|
|
835
853
|
.option("--credential-stdin", "从重定向 stdin 读取 provider credential JSON")
|
|
854
|
+
.option("--credential-prompt", "在交互终端隐藏输入 provider credential")
|
|
836
855
|
.option("--yes", "确认凭据轮换并使旧 plan 失效")
|
|
837
856
|
.action(async (code, options, command) => {
|
|
838
857
|
requireConfirmation(options.yes, "SCM credential rotation");
|
|
839
|
-
if (!options.credentialFile && !options.credentialStdin) {
|
|
840
|
-
throw new OnboardingError("SCM credential rotation requires --credential-file or --credential-stdin.", "onboarding_scm_credential_source_invalid");
|
|
858
|
+
if (!options.credentialFile && !options.credentialStdin && !options.credentialPrompt) {
|
|
859
|
+
throw new OnboardingError("SCM credential rotation requires --credential-prompt, --credential-file, or --credential-stdin.", "onboarding_scm_credential_source_invalid");
|
|
841
860
|
}
|
|
842
861
|
const onboarding = client();
|
|
843
862
|
const version = revision(options.revision);
|
|
@@ -851,7 +870,7 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
851
870
|
await output(command, { ok: true, connection }, `${connection.code}\tcredential:configured\tversion:${connection.version}`);
|
|
852
871
|
}), [
|
|
853
872
|
"numa app scm rotate github-main --revision 4 --credential-file github-app.private.json --yes --json",
|
|
854
|
-
"numa app scm rotate codeup-main --revision 2 --credential-
|
|
873
|
+
"numa app scm rotate codeup-main --revision 2 --credential-prompt --yes --json"
|
|
855
874
|
]);
|
|
856
875
|
addExamples(scm.command("disable <code>")
|
|
857
876
|
.description("平台管理员软禁用连接;服务端会阻止仍被非终态会话使用的连接")
|
|
@@ -961,9 +980,15 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
961
980
|
throw new OnboardingError("idempotency-key must exactly match client-request-id for publication attachment.", "onboarding_input_invalid");
|
|
962
981
|
}
|
|
963
982
|
const onboarding = client();
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
983
|
+
const inspection = await inspectOnboardingSession(onboarding, sessionNo);
|
|
984
|
+
const session = inspection.session;
|
|
985
|
+
if (!canAttachPublicationPlan(inspection)) {
|
|
986
|
+
throw new OnboardingError("Publication attachment requires the same parent session to have durable WAITING_EXTERNAL evidence for ATTACH_PUBLICATION_PLAN.", "onboarding_publication_session_invalid", undefined, undefined, false, {
|
|
987
|
+
sessionNo: session.sessionNo,
|
|
988
|
+
state: session.state,
|
|
989
|
+
currentStep: session.currentStep ?? null,
|
|
990
|
+
lastSequence: inspection.lastSequence
|
|
991
|
+
});
|
|
967
992
|
}
|
|
968
993
|
const source = await scanPublication(options.source);
|
|
969
994
|
const input = parsedActionInput(OnboardingPublicationPlanActionRequestSchema, {
|
|
@@ -1180,7 +1205,7 @@ export function registerApplicationOnboardingCommands(program, dependencies = {}
|
|
|
1180
1205
|
"numa app tui --session 8d15ee89-43f0-4378-a7aa-51f09c5b42fc"
|
|
1181
1206
|
]);
|
|
1182
1207
|
addExamples(app.command("retry <session-no>")
|
|
1183
|
-
.description("
|
|
1208
|
+
.description("显式请求服务端恢复同一会话中可重入的失败步骤")
|
|
1184
1209
|
.action(async (sessionNo, _options, command) => {
|
|
1185
1210
|
const inspection = await executeOnboardingAction(client(), sessionNo, "retry");
|
|
1186
1211
|
await output(command, { ok: true, ...inspection }, executionText(inspection.session, inspection.events));
|