@aopslabs/aops 0.3.10 → 0.3.12

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.
Files changed (37) hide show
  1. package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/aops-cli.md +17 -0
  2. package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/aops-system.md +24 -0
  3. package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/manifest.json +7 -7
  4. package/agent-assets-release/agent-assets/inventory.json +5 -5
  5. package/agent-assets-release/agent-assets/projection.json +1 -1
  6. package/agent-assets-release/agent-assets-release.json +38 -38
  7. package/agent-assets-release/agent-assets-release.sigstore.json +22 -25
  8. package/assets/agent-assets/core/user-guides/aops-cli.md +17 -0
  9. package/assets/agent-assets/core/user-guides/aops-system.md +24 -0
  10. package/dist/commands/doc.js +12 -4
  11. package/dist/commands/global-update.js +512 -0
  12. package/dist/lib/agent-assets/native-fs.js +2 -2
  13. package/dist/main.js +2 -0
  14. package/native/manifest.json +1 -1
  15. package/native/qualifications/win32-x64.json +1 -1
  16. package/native/tui/darwin-arm64/aops-tui +0 -0
  17. package/native/tui/win32-x64/aops-tui.exe +0 -0
  18. package/package.json +5 -4
  19. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/SKILL.md +0 -0
  20. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/agentspace/SKILL.md +0 -0
  21. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/aops-cli-core/SKILL.md +0 -0
  22. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/chatv3/SKILL.md +0 -0
  23. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/collaborative-work/SKILL.md +0 -0
  24. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/discuss/SKILL.md +0 -0
  25. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/docman/SKILL.md +0 -0
  26. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/mission/SKILL.md +0 -0
  27. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/projectman/SKILL.md +0 -0
  28. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/sys/SKILL.md +0 -0
  29. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/view/SKILL.md +0 -0
  30. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/references/working-disciplines/SKILL.md +0 -0
  31. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/agent-assets.md +0 -0
  32. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/agentspace.md +0 -0
  33. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/chatv3.md +0 -0
  34. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/docman.md +0 -0
  35. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/projectman.md +0 -0
  36. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/sys.md +0 -0
  37. /package/agent-assets-release/agent-assets/core/{070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5 → ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff}/files/user-guides/working-disciplines.md +0 -0
@@ -50,6 +50,23 @@ aops auth login --target <target-name>
50
50
  aops auth status --target <target-name>
51
51
  ```
52
52
 
53
+ ### 2.3 Guarded global npm update
54
+
55
+ Use the TUI Update page for Check, Prepare, and confirmed Apply. For headless
56
+ operation:
57
+
58
+ ```bash
59
+ aops update check --json
60
+ aops update prepare --json
61
+ aops update apply --plan <update-plan.json> --confirm <sha256-plan-id> --json
62
+ ```
63
+
64
+ Prepare is non-mutating and retains exact candidate and rollback tarballs.
65
+ Apply stops Cockpit before Server, installs the public closure as one global
66
+ CLI with its exact nested Server, repeatedly checks loopback health, and
67
+ automatically restores the prior exact closure on failure. It does not publish
68
+ packages or create source-control releases.
69
+
53
70
  ## 3 `init`
54
71
 
55
72
  ### 3.1 Overview
@@ -36,6 +36,30 @@ logs and Ctrl+C cleanup. The Cockpit launcher starts only its independent
36
36
  background process. Both call package-relative Node entrypoints and never
37
37
  carry database secrets in the script or argv.
38
38
 
39
+ ## Guarded global update
40
+
41
+ The bundled Rust TUI has an Update page for an already installed npm-based
42
+ AOPS system. Its Check action is read-only. Prepare downloads and verifies the
43
+ exact public candidate and restore tarballs and writes a plan without changing
44
+ services or packages. Apply requires that exact plan, briefly stops Cockpit
45
+ and Server, installs one global `@aopslabs/aops` CLI with its exact nested
46
+ Server dependency, and repeatedly verifies direct Server, Cockpit, and
47
+ Cockpit-proxy health. Failure automatically restores the prior exact versions,
48
+ package layout, and services.
49
+
50
+ The same lifecycle is available headlessly:
51
+
52
+ ```text
53
+ aops update check --json
54
+ aops update prepare --json
55
+ aops update apply --plan <update-plan.json> --confirm <sha256-plan-id> --json
56
+ ```
57
+
58
+ All metadata and tarball reads are pinned to the public npm registry. A legacy
59
+ top-level Server dedupe is treated as a repairable package-layout issue. The
60
+ updater does not publish packages, create tags/releases, or replace the normal
61
+ candidate acceptance and independent review gates.
62
+
39
63
  ## Capability discovery
40
64
 
41
65
  Start with the relevant CLI family help. When a server has custom or newer domains, query its live catalog:
@@ -73,14 +73,14 @@
73
73
  "sha256": "18924d928b659eb80a7736a104b56b9693cffe91cc4499e739a2a67a0922c519"
74
74
  },
75
75
  {
76
- "byteLength": 50749,
76
+ "byteLength": 51366,
77
77
  "path": "user-guides/aops-cli.md",
78
- "sha256": "a132c0a8c3ff6fe12991f559c5a1f33b32d70790f0b53d0e4ab4fbe101cd7e2d"
78
+ "sha256": "bcf09a9246da2854ef7d3a057688fccd8c5c06613f41044d3d8bc556e623bac8"
79
79
  },
80
80
  {
81
- "byteLength": 3609,
81
+ "byteLength": 4675,
82
82
  "path": "user-guides/aops-system.md",
83
- "sha256": "d7a3294cfdd6291d30c57baa033f22627f1a0a590545f2e1195f9b988bf55c5f"
83
+ "sha256": "3e001003b36c6cc392e8998b1399ac36558438b49a7cfe1a6b482edfdbf44bb7"
84
84
  },
85
85
  {
86
86
  "byteLength": 4789,
@@ -109,7 +109,7 @@
109
109
  }
110
110
  ],
111
111
  "name": "aops",
112
- "packageSha256": "070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5",
112
+ "packageSha256": "ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff",
113
113
  "provenance": {
114
114
  "expectedDigestSource": "signed-release-manifest",
115
115
  "reference": "aops-platform-agent-assets:core",
@@ -117,6 +117,6 @@
117
117
  },
118
118
  "schemaVersion": 1,
119
119
  "standard": "aops-community-core-v1",
120
- "version": "0.3.10",
121
- "versionId": "community-core-0.3.10"
120
+ "version": "0.3.12",
121
+ "versionId": "community-core-0.3.12"
122
122
  }
@@ -6,12 +6,12 @@
6
6
  },
7
7
  "core": {
8
8
  "entryFile": "SKILL.md",
9
- "manifestRef": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/manifest.json",
9
+ "manifestRef": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/manifest.json",
10
10
  "name": "aops",
11
11
  "optional": false,
12
- "packageSha256": "070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5",
13
- "version": "0.3.10",
14
- "versionId": "community-core-0.3.10"
12
+ "packageSha256": "ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff",
13
+ "version": "0.3.12",
14
+ "versionId": "community-core-0.3.12"
15
15
  },
16
16
  "gateway": {
17
17
  "byteLength": 621,
@@ -22,7 +22,7 @@
22
22
  "kind": "aops-community-agent-assets-inventory-v1",
23
23
  "schemaVersion": 1,
24
24
  "source": {
25
- "commit": "ae3d08728aab34b9870fe827866c5b3f9d43f29e",
25
+ "commit": "4c0de59827ef0b3ff1494d4626eac56736da88ee",
26
26
  "repository": "git+https://github.com/eeemzs/aops-platform",
27
27
  "root": "apps/aops-cli/assets/agent-assets"
28
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "catalogPackageSha256": [],
3
- "corePackageSha256": "070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5",
3
+ "corePackageSha256": "ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff",
4
4
  "gatewayRef": "agent-assets/gateway/aops/SKILL.md",
5
5
  "kind": "aops-community-agent-assets-projection-v1",
6
6
  "root": "agent-assets",
@@ -7,123 +7,123 @@
7
7
  },
8
8
  "core": {
9
9
  "entryFile": "SKILL.md",
10
- "manifestRef": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/manifest.json",
10
+ "manifestRef": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/manifest.json",
11
11
  "name": "aops",
12
12
  "optional": false,
13
- "packageSha256": "070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5",
14
- "version": "0.3.10",
15
- "versionId": "community-core-0.3.10"
13
+ "packageSha256": "ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff",
14
+ "version": "0.3.12",
15
+ "versionId": "community-core-0.3.12"
16
16
  },
17
17
  "files": [
18
18
  {
19
19
  "byteLength": 2738,
20
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/SKILL.md",
20
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/SKILL.md",
21
21
  "sha256": "44f8e0ffe807195d6890719e1350a630d159ee74f219001d9393d1d9a8d4818b"
22
22
  },
23
23
  {
24
24
  "byteLength": 2681,
25
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/agentspace/SKILL.md",
25
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/agentspace/SKILL.md",
26
26
  "sha256": "08e33ef035c41beead342202a1f07af4391b1e4ed62cea9a4d79b43e966c7c0f"
27
27
  },
28
28
  {
29
29
  "byteLength": 3804,
30
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/aops-cli-core/SKILL.md",
30
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/aops-cli-core/SKILL.md",
31
31
  "sha256": "a645a2f50bc35b2033d05bad770b2f0a53e3f162b95f00dfd493ba718c062433"
32
32
  },
33
33
  {
34
34
  "byteLength": 2341,
35
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/chatv3/SKILL.md",
35
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/chatv3/SKILL.md",
36
36
  "sha256": "0f45d8fe418f740456e7f448ce472a7f0784a7cd5b01fe4cbc81439ded3c7931"
37
37
  },
38
38
  {
39
39
  "byteLength": 2869,
40
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/collaborative-work/SKILL.md",
40
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/collaborative-work/SKILL.md",
41
41
  "sha256": "f4d2af3c384368b1adb1308f2c3731b17e6b4074e4ebdfc8c8f061ba2bb01a67"
42
42
  },
43
43
  {
44
44
  "byteLength": 2386,
45
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/discuss/SKILL.md",
45
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/discuss/SKILL.md",
46
46
  "sha256": "03cd2bde90b590b4ce6a370a6d17d1aaabbb6693fee47c29e0e45848b3d7f8d6"
47
47
  },
48
48
  {
49
49
  "byteLength": 2736,
50
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/docman/SKILL.md",
50
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/docman/SKILL.md",
51
51
  "sha256": "cf48bfa4d94a97a0d2805d5d9dd7a7d0f7430adaf36b9b2fc685465c42cd8cd7"
52
52
  },
53
53
  {
54
54
  "byteLength": 1910,
55
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/mission/SKILL.md",
55
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/mission/SKILL.md",
56
56
  "sha256": "f4ce9c60c3d12ba45e9eaba0069ed9d8936438a15e0ae1974fa8b15a17ae67a1"
57
57
  },
58
58
  {
59
59
  "byteLength": 3167,
60
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/projectman/SKILL.md",
60
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/projectman/SKILL.md",
61
61
  "sha256": "2ff36573d7bf85b2212d1c819bb692cbdfb49f4ea77fdd95d0a263c4007c31b0"
62
62
  },
63
63
  {
64
64
  "byteLength": 1621,
65
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/sys/SKILL.md",
65
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/sys/SKILL.md",
66
66
  "sha256": "89cb838aafed26874a0fbc121078435a2ec27bf2901527a51515833e63b1dff4"
67
67
  },
68
68
  {
69
69
  "byteLength": 1865,
70
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/view/SKILL.md",
70
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/view/SKILL.md",
71
71
  "sha256": "644603a17444374025acf52975dc5df04e1412d69965b210a28b6b5ed203c90b"
72
72
  },
73
73
  {
74
74
  "byteLength": 3093,
75
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/references/working-disciplines/SKILL.md",
75
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/references/working-disciplines/SKILL.md",
76
76
  "sha256": "406c7215917ff68e22c221847c72af9c38dc9ddab6cb0a4beaedd46038bda08d"
77
77
  },
78
78
  {
79
79
  "byteLength": 3333,
80
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/agent-assets.md",
80
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/agent-assets.md",
81
81
  "sha256": "12ef09138579d9bfc75a33d51c78bc50d8b34556eb6070af64a8c03d93927f05"
82
82
  },
83
83
  {
84
84
  "byteLength": 7702,
85
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/agentspace.md",
85
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/agentspace.md",
86
86
  "sha256": "18924d928b659eb80a7736a104b56b9693cffe91cc4499e739a2a67a0922c519"
87
87
  },
88
88
  {
89
- "byteLength": 50749,
90
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/aops-cli.md",
91
- "sha256": "a132c0a8c3ff6fe12991f559c5a1f33b32d70790f0b53d0e4ab4fbe101cd7e2d"
89
+ "byteLength": 51366,
90
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/aops-cli.md",
91
+ "sha256": "bcf09a9246da2854ef7d3a057688fccd8c5c06613f41044d3d8bc556e623bac8"
92
92
  },
93
93
  {
94
- "byteLength": 3609,
95
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/aops-system.md",
96
- "sha256": "d7a3294cfdd6291d30c57baa033f22627f1a0a590545f2e1195f9b988bf55c5f"
94
+ "byteLength": 4675,
95
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/aops-system.md",
96
+ "sha256": "3e001003b36c6cc392e8998b1399ac36558438b49a7cfe1a6b482edfdbf44bb7"
97
97
  },
98
98
  {
99
99
  "byteLength": 4789,
100
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/chatv3.md",
100
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/chatv3.md",
101
101
  "sha256": "d27aaf35d84bcfb6c00f67b170f80f7dc4879fdf8d439fbaf131ed615a8eb9d6"
102
102
  },
103
103
  {
104
104
  "byteLength": 5838,
105
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/docman.md",
105
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/docman.md",
106
106
  "sha256": "0e434b7bf043260038d12062b1adc5cbf4ba0adf918c9fdf879262dc50bd779c"
107
107
  },
108
108
  {
109
109
  "byteLength": 6660,
110
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/projectman.md",
110
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/projectman.md",
111
111
  "sha256": "23289f31414c9d753f348efb6b5c1e58fe1ff217b6c730d6443279e6052a0509"
112
112
  },
113
113
  {
114
114
  "byteLength": 3432,
115
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/sys.md",
115
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/sys.md",
116
116
  "sha256": "3959f5c044314be14f368529edffd7adb80bb475b659397c6f4bbec8086c5f28"
117
117
  },
118
118
  {
119
119
  "byteLength": 27262,
120
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/files/user-guides/working-disciplines.md",
120
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/files/user-guides/working-disciplines.md",
121
121
  "sha256": "c440185924c91755008ce9977c1ab3128994973038e610fe04cad392b14af79b"
122
122
  },
123
123
  {
124
124
  "byteLength": 3978,
125
- "ref": "agent-assets/core/070b0d3126c645890845791b67157fdd9f43a482fda66583e84fb159b30689a5/manifest.json",
126
- "sha256": "5c1448a4dd26ad41a7455070da26b60b6de4f6223f9bcc13b63ee385dfa61afa"
125
+ "ref": "agent-assets/core/ec1a663c171f7b847980a06dc84ce045493880f8a71d9d2e992d9bcaa31407ff/manifest.json",
126
+ "sha256": "6a328805ad7d840594f6f171e94071b0f931404ab86dfb9fc37f93815dfb6675"
127
127
  },
128
128
  {
129
129
  "byteLength": 621,
@@ -133,12 +133,12 @@
133
133
  {
134
134
  "byteLength": 926,
135
135
  "ref": "agent-assets/inventory.json",
136
- "sha256": "f5eb6847501dd2050f6b318030c9d67dabba9875f6f8209a3c2c2076823c8504"
136
+ "sha256": "b6ce24a65a42831fa037617838762688a11a7c01efcb86470e1ade2d0672a260"
137
137
  },
138
138
  {
139
139
  "byteLength": 281,
140
140
  "ref": "agent-assets/projection.json",
141
- "sha256": "29650b3d65c551044186dfb966e8b578c102fcfebdbff4b94ec3204adca4c2b2"
141
+ "sha256": "fc0b5930ba8d5ec145e442b90274b9d9608d6081f2c39c5ed730a3aa0896e1ab"
142
142
  }
143
143
  ],
144
144
  "gateway": {
@@ -149,16 +149,16 @@
149
149
  },
150
150
  "inventory": {
151
151
  "ref": "agent-assets/inventory.json",
152
- "sha256": "f5eb6847501dd2050f6b318030c9d67dabba9875f6f8209a3c2c2076823c8504"
152
+ "sha256": "b6ce24a65a42831fa037617838762688a11a7c01efcb86470e1ade2d0672a260"
153
153
  },
154
154
  "kind": "aops-community-agent-assets-release-v1",
155
155
  "projection": {
156
156
  "ref": "agent-assets/projection.json",
157
- "sha256": "29650b3d65c551044186dfb966e8b578c102fcfebdbff4b94ec3204adca4c2b2"
157
+ "sha256": "fc0b5930ba8d5ec145e442b90274b9d9608d6081f2c39c5ed730a3aa0896e1ab"
158
158
  },
159
159
  "root": "agent-assets",
160
160
  "schemaVersion": 1,
161
- "setSha256": "8e591bdee7b640a4810dbc1b8c16895dcc8e042b254c01c54ebebf9c15dd9d61"
161
+ "setSha256": "0c165103307fece47df0776bc1bdd45898317769904cc46d4bd809afe0737027"
162
162
  },
163
163
  "evidence": {
164
164
  "signature": {
@@ -166,10 +166,10 @@
166
166
  }
167
167
  },
168
168
  "kind": "aops-community-agent-assets-bundle-v1",
169
- "releaseVersion": "0.3.10",
169
+ "releaseVersion": "0.3.12",
170
170
  "schemaVersion": 1,
171
171
  "source": {
172
- "commit": "ae3d08728aab34b9870fe827866c5b3f9d43f29e",
172
+ "commit": "4c0de59827ef0b3ff1494d4626eac56736da88ee",
173
173
  "repository": "git+https://github.com/eeemzs/aops-platform",
174
174
  "root": "apps/aops-cli/assets/agent-assets"
175
175
  }
@@ -4,13 +4,13 @@
4
4
  "x509CertificateChain": {
5
5
  "certificates": [
6
6
  {
7
- "rawBytes": "MIIHczCCBvqgAwIBAgIUYkoqqa5fnZGiAWmZRvKviFglkQQwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwODEwMTAwMTQyWhcNMjYwODEwMTAxMTQyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6wl6qFr75yz8/RWqmA/pc29cQJslWAXnqqTYXBog6FLgyMAoKDhDtPAHRjnVECI/nMINJJ70r9SuiKX3mrlui6OCBhkwggYVMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUbTM1u4FwXqYLE8xgfG/CV9bNjlIwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wdAYDVR0RAQH/BGowaIZmaHR0cHM6Ly9naXRodWIuY29tL2VlZW16cy9hb3BzLXBsYXRmb3JtLy5naXRodWIvd29ya2Zsb3dzL3NpZ24tcHVibGljLWFnZW50LWFzc2V0cy55bWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoYWUzZDA4NzI4YWFiMzRiOTg3MGZlODI3ODY2YzViM2Y5ZDQzZjI5ZTAxBgorBgEEAYO/MAEEBCNTaWduIGV4YWN0IHB1YmxpYyBBT1BTIGFnZW50IGFzc2V0czAiBgorBgEEAYO/MAEFBBRlZWVtenMvYW9wcy1wbGF0Zm9ybTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMHYGCisGAQQBg78wAQkEaAxmaHR0cHM6Ly9naXRodWIuY29tL2VlZW16cy9hb3BzLXBsYXRmb3JtLy5naXRodWIvd29ya2Zsb3dzL3NpZ24tcHVibGljLWFnZW50LWFzc2V0cy55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoYWUzZDA4NzI4YWFiMzRiOTg3MGZlODI3ODY2YzViM2Y5ZDQzZjI5ZTAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwNwYKKwYBBAGDvzABDAQpDCdodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0wOAYKKwYBBAGDvzABDQQqDChhZTNkMDg3MjhhYWIzNGI5ODcwZmU4Mjc4NjZjNWIzZjlkNDNmMjllMB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTMxNjI1NTAyNjApBgorBgEEAYO/MAEQBBsMGWh0dHBzOi8vZ2l0aHViLmNvbS9lZWVtenMwGQYKKwYBBAGDvzABEQQLDAkxMDkzMTA3NzQwdgYKKwYBBAGDvzABEgRoDGZodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0vLmdpdGh1Yi93b3JrZmxvd3Mvc2lnbi1wdWJsaWMtYWdlbnQtYXNzZXRzLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABEwQqDChhZTNkMDg3MjhhYWIzNGI5ODcwZmU4Mjc4NjZjNWIzZjlkNDNmMjllMCEGCisGAQQBg78wARQEEwwRd29ya2Zsb3dfZGlzcGF0Y2gwWwYKKwYBBAGDvzABFQRNDEtodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0vYWN0aW9ucy9ydW5zLzMxMzc3MjIxODI2L2F0dGVtcHRzLzEwFwYKKwYBBAGDvzABFgQJDAdwcml2YXRlMFIGCisGAQQBg78wARgERAxCcmVwbzplZWVtenNAMTA5MzEwNzc0L2FvcHMtcGxhdGZvcm1AMTMxNjI1NTAyNjpyZWY6cmVmcy9oZWFkcy9tYWluMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGf6x716wAABAMARzBFAiEAhBMWF5wTCNsKiFiL6u9O5JH9oDCHYAPKGnkNql7tv5cCIAbjL2DugZLcYHVNNxqMZXKqquZ1BzC848d5249lL+KTMAoGCCqGSM49BAMDA2cAMGQCMAdr/0PM0oBQ/CnPT3RgtHGHQKFged2fFXC/OfVCtGrI7LvGZbddcpmqnnvdomxZlgIwZdze+aMF31xBV8HhUgsVaY4Q36PEJCAem1EKxbS9VjzEMGD1lauskwxUUiDnkGCB"
7
+ "rawBytes": "MIIHdDCCBvmgAwIBAgIUXrQzPMVetpkdZSixwh5umfdJXEAwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwODEyMTM0MzQyWhcNMjYwODEyMTM1MzQyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDvyc5UC0pXGyRRA3kbmGpjHBb+cy6R69q/yhZiWrDTarTXZOyPb+ql6bAUL8OS7Wr83TPaW4giyFMq3AqjAZ+qOCBhgwggYUMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU19WlvqpVfo2MigdIwOHoNHSAnF4wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wdAYDVR0RAQH/BGowaIZmaHR0cHM6Ly9naXRodWIuY29tL2VlZW16cy9hb3BzLXBsYXRmb3JtLy5naXRodWIvd29ya2Zsb3dzL3NpZ24tcHVibGljLWFnZW50LWFzc2V0cy55bWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoNGMwZGU1OTgyN2VmMGIzZmYxNDk0ZDQ2MjZlYWM1NjczNmRhODhlZTAxBgorBgEEAYO/MAEEBCNTaWduIGV4YWN0IHB1YmxpYyBBT1BTIGFnZW50IGFzc2V0czAiBgorBgEEAYO/MAEFBBRlZWVtenMvYW9wcy1wbGF0Zm9ybTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMHYGCisGAQQBg78wAQkEaAxmaHR0cHM6Ly9naXRodWIuY29tL2VlZW16cy9hb3BzLXBsYXRmb3JtLy5naXRodWIvd29ya2Zsb3dzL3NpZ24tcHVibGljLWFnZW50LWFzc2V0cy55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoNGMwZGU1OTgyN2VmMGIzZmYxNDk0ZDQ2MjZlYWM1NjczNmRhODhlZTAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwNwYKKwYBBAGDvzABDAQpDCdodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0wOAYKKwYBBAGDvzABDQQqDCg0YzBkZTU5ODI3ZWYwYjNmZjE0OTRkNDYyNmVhYzU2NzM2ZGE4OGVlMB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTMxNjI1NTAyNjApBgorBgEEAYO/MAEQBBsMGWh0dHBzOi8vZ2l0aHViLmNvbS9lZWVtenMwGQYKKwYBBAGDvzABEQQLDAkxMDkzMTA3NzQwdgYKKwYBBAGDvzABEgRoDGZodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0vLmdpdGh1Yi93b3JrZmxvd3Mvc2lnbi1wdWJsaWMtYWdlbnQtYXNzZXRzLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABEwQqDCg0YzBkZTU5ODI3ZWYwYjNmZjE0OTRkNDYyNmVhYzU2NzM2ZGE4OGVlMCEGCisGAQQBg78wARQEEwwRd29ya2Zsb3dfZGlzcGF0Y2gwWwYKKwYBBAGDvzABFQRNDEtodHRwczovL2dpdGh1Yi5jb20vZWVlbXpzL2FvcHMtcGxhdGZvcm0vYWN0aW9ucy9ydW5zLzMxNjAyODIwNzY3L2F0dGVtcHRzLzEwFwYKKwYBBAGDvzABFgQJDAdwcml2YXRlMFIGCisGAQQBg78wARgERAxCcmVwbzplZWVtenNAMTA5MzEwNzc0L2FvcHMtcGxhdGZvcm1AMTMxNjI1NTAyNjpyZWY6cmVmcy9oZWFkcy9tYWluMIGJBgorBgEEAdZ5AgQCBHsEeQB3AHUA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGf9jbrxgAABAMARjBEAiAyBaAFHC+j1WTHQguv4bjVTu7npctL3HMaGSX+cte86gIgHz0hdhVgGIdBbxo5if2XKqJp3JPz0QP53VqxWYyXnrYwCgYIKoZIzj0EAwMDaQAwZgIxAKOxcj0bOrUbdyXtTCOMz9+Ma5bHFeIu628CTA2aIt+qwSGCZ0TN3/S/xZB1CPQcIgIxALgr1YU6w2Kboae38nJTi6h8qfXzFBhzVqWO8LZ7zZ0NOEmaHgXHFpm5EDGR730s1w=="
8
8
  }
9
9
  ]
10
10
  },
11
11
  "tlogEntries": [
12
12
  {
13
- "logIndex": "2406480104",
13
+ "logIndex": "2437161535",
14
14
  "logId": {
15
15
  "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
16
16
  },
@@ -18,37 +18,34 @@
18
18
  "kind": "hashedrekord",
19
19
  "version": "0.0.1"
20
20
  },
21
- "integratedTime": "1786356103",
21
+ "integratedTime": "1786542222",
22
22
  "inclusionPromise": {
23
- "signedEntryTimestamp": "MEUCICWnwCwlu/MO/61SzDN/oO74NcYpS6dpnrHwlVRN1zepAiEAyHv3tcLHvqjbzN/RHtpMnFuwbF+VaPeAgIZwu8vu2JQ="
23
+ "signedEntryTimestamp": "MEUCIAUh1+bAxa2z3KpO0PjffzVqgXNWeHFhpwInuAshs5NJAiEA7ambQloRTz91/zDrBOZ+eSOM4q0Jjcx6a3gdS/fTELM="
24
24
  },
25
25
  "inclusionProof": {
26
- "logIndex": "2284575842",
27
- "rootHash": "NZihJ1CvHqsgu25crzujDGoE6pW+K8JV63Wmadn8Px8=",
28
- "treeSize": "2284575845",
26
+ "logIndex": "2315257273",
27
+ "rootHash": "TySTIZXLwpzt56M+HaQ6fuYSHmk2b60wYUyV1dC9fPY=",
28
+ "treeSize": "2315257285",
29
29
  "hashes": [
30
- "LGaRvRnshOvMWU8gB+uGwypz0vuVyNrT9X56ekw2aCs=",
31
- "Dqyr4/1h+5rxqxLjUj2Bv1DvcOsqNKUWlXDvx6S+zzM=",
32
- "jglRqdFaBoDS64P+zq8gGo7H32qXogqA3NjK1wuDhLQ=",
33
- "wv6k0Ym9MAbJP5Drdc3axW+9i4LDWenwFQyXKUOEl6g=",
34
- "TMQPqazZ7sYlZUI/tAFaLQc8BWu3RdgPIQHLi3xanNk=",
35
- "WOTsDBv15i472cNxjAcdf8d9Ax8CArNqPCCQbisvFX4=",
36
- "HKUG9hurT8FxxlPDfG9Lreoe6lzWRlZ1FY2X8pzwqA0=",
37
- "94K2ew5OiSTQn3xqgAWenWtrOccq+tGw8RJ8Ss0b1tQ=",
38
- "YKliNYFFQcpi99NsN0PdO1fQkWYxWjGcwrtWfHXoLSE=",
39
- "xMSvje4sx7HB3y2S7jDvsG+nWGPg9QcAKW5FeT/wmeg=",
40
- "SWTTg1DaWeILCHxA7wAAJqSMxf5DJvU5XDkUNvHEcSA=",
41
- "wwzFbcNP5CjCUxHD4mQteXouD4JHbRdEAeehTXB585g=",
42
- "KAVXV2qq7v6uOWGc/dYf+pgvRpg+jZv3yG8S2+qD240=",
43
- "F5PBVWQCbIhoAF9XPRREQx0SJ9KTE+sRR28mtYPulvA=",
30
+ "dap5Q3G17cwuYYNbO/lr+KHJEiaHu+VR7L4SQhI6tvk=",
31
+ "enwl+fW0tgxGVBGbcl/Z4oiEXqJh8+FrWlA6tFIHE5E=",
32
+ "RgApDIxYR2JY9sHxgYWTJ2gVutXxwZg7EVFsdzN4Ixo=",
33
+ "rB1BZe/ngGTXwgW2Nbnn6OgZG59IN9MPS8E1/KRCOwE=",
34
+ "kRcGHzUM4n7JaKREC83bbHMFIxBEJ0ZehUv9SCVGRuQ=",
35
+ "b0G4bcQSZU/RXBYHCLVH7n5zj2UZFXIFSo1mrRnqYlI=",
36
+ "QTgGZta3nzIdiXPbilI4PLXwDV0X2GER6RT5yMjaLlo=",
37
+ "4iVgO4rYG8sWYuspC/I2iRqQShQKCauJhOf+GKtDfjk=",
38
+ "TnE3vPpNKxk7NgyiNeQoCnyPdaT3giToGhtKIxQ2uGY=",
39
+ "4UN/euia0P9HWMFaSCc4aYjC932x4o5XJww44WN3CGM=",
40
+ "mYkFdqU5C9m3w88wTn9l6UpYo+PI93c232s+vBiBEpM=",
44
41
  "ygTG08vB2EEmJQPXRvF5H06Tlac72AkODENK7PhCPkw=",
45
42
  "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="
46
43
  ],
47
44
  "checkpoint": {
48
- "envelope": "rekor.sigstore.dev - 1193050959916656506\n2284575845\nNZihJ1CvHqsgu25crzujDGoE6pW+K8JV63Wmadn8Px8=\n\n— rekor.sigstore.dev wNI9ajBGAiEAkINZwrrFNf6XBwcBITrA/vFhC1qVRmqwY0UlLatt93MCIQDDZlS8KVrs5t0GScyE36rR/44+5K+sMdfqMd3Q+ub9yw==\n"
45
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n2315257285\nTySTIZXLwpzt56M+HaQ6fuYSHmk2b60wYUyV1dC9fPY=\n\n— rekor.sigstore.dev wNI9ajBFAiEAloapWt3Dttq/SNB8Zp3ODHlGB25PfuBgAED2Lu83IoUCIFdzRP3Bb8KdFi4JxlCrYnJFTWZQlsWBd734x3lJAQ7s\n"
49
46
  }
50
47
  },
51
- "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3NDMwZmYzNzkwYzVhY2I1NTQyMjJhOGQ3OGUzOGM5OGI5ZDRjM2I5MDliYjUxMWU3N2Y5ZWUyMTQzNmUyN2M5In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNFZndrcW1wcjBFS2IzN3k5VEZaczVkZ0RjZCtzUVB0cFVGelpQa3RrMDZBSWhBTnBBMW1iMkRmdTNtWHVmei9qVk9NTjE1bVF5STJXRm5DR3huNGszTUF2KyIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaGpla05EUW5aeFowRjNTVUpCWjBsVldXdHZjWEZoTldadVdrZHBRVmR0V2xKMlMzWnBSbWRzYTFGUmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlFUlhkTlZFRjNUVlJSZVZkb1kwNU5hbGwzVDBSRmQwMVVRWGhOVkZGNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVUyZDJ3MmNVWnlOelY1ZWpndlVsZHhiVUV2Y0dNeU9XTlJTbk5zVjBGWWJuRnhWRmtLV0VKdlp6WkdUR2Q1VFVGdlMwUm9SSFJRUVVoU2FtNVdSVU5KTDI1TlNVNUtTamN3Y2psVGRXbExXRE50Y214MWFUWlBRMEpvYTNkbloxbFdUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZpVkUweENuVTBSbmRZY1ZsTVJUaDRaMlpITDBOV09XSk9hbXhKZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJSQldVUldVakJTUVZGSUwwSkhiM2RoU1ZwdFlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKV2JGcFhNVFpqZVRsb1lqTkNlZ3BNV0VKeldWaFNiV0l6U25STWVUVnVZVmhTYjJSWFNYWmtNamw1WVRKYWMySXpaSHBNTTA1d1dqSTBkR05JVm1saVIyeHFURmRHYmxwWE5UQk1WMFo2Q21NeVZqQmplVFUxWWxkNFFXTnRWbTFqZVRsdldsZEdhMk41T1hSWlYyeDFUVVJyUjBOcGMwZEJVVkZDWnpjNGQwRlJSVVZMTW1nd1pFaENlazlwT0hZS1pFYzVjbHBYTkhWWlYwNHdZVmM1ZFdONU5XNWhXRkp2WkZkS01XTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNTSGRaUzB0M1dVSkNRVWRFZG5wQlFncEJaMUZTWkRJNWVXRXlXbk5pTTJSbVdrZHNlbU5IUmpCWk1tZDNUbWRaUzB0M1dVSkNRVWRFZG5wQlFrRjNVVzlaVjFWNldrUkJORTU2U1RSWlYwWnBDazE2VW1sUFZHY3pUVWRhYkU5RVNUTlBSRmt5V1hwV2FVMHlXVFZhUkZGNldtcEpOVnBVUVhoQ1oyOXlRbWRGUlVGWlR5OU5RVVZGUWtOT1ZHRlhaSFVLU1VkV05GbFhUakJKU0VJeFdXMTRjRmw1UWtKVU1VSlVTVWRHYmxwWE5UQkpSMFo2WXpKV01HTjZRV2xDWjI5eVFtZEZSVUZaVHk5TlFVVkdRa0pTYkFwYVYxWjBaVzVOZGxsWE9YZGplVEYzWWtkR01GcHRPWGxpVkVGa1FtZHZja0puUlVWQldVOHZUVUZGUjBKQk9YbGFWMXA2VERKb2JGbFhVbnBNTWpGb0NtRlhOSGRQZDFsTFMzZFpRa0pCUjBSMmVrRkNRMEZSZEVSRGRHOWtTRkozWTNwdmRrd3pVblpoTWxaMVRHMUdhbVJIYkhaaWJrMTFXakpzTUdGSVZta0taRmhPYkdOdFRuWmlibEpzWW01UmRWa3lPWFJOU0ZsSFEybHpSMEZSVVVKbk56aDNRVkZyUldGQmVHMWhTRkl3WTBoTk5reDVPVzVoV0ZKdlpGZEpkUXBaTWpsMFRESldiRnBYTVRaamVUbG9Zak5DZWt4WVFuTlpXRkp0WWpOS2RFeDVOVzVoV0ZKdlpGZEpkbVF5T1hsaE1scHpZak5rZWt3elRuQmFNalIwQ21OSVZtbGlSMnhxVEZkR2JscFhOVEJNVjBaNll6SldNR041TlRWaVYzaEJZMjFXYldONU9XOWFWMFpyWTNrNWRGbFhiSFZOUkdkSFEybHpSMEZSVVVJS1p6YzRkMEZSYjBWTFozZHZXVmRWZWxwRVFUUk9la2swV1ZkR2FVMTZVbWxQVkdjelRVZGFiRTlFU1ROUFJGa3lXWHBXYVUweVdUVmFSRkY2V21wSk5RcGFWRUZrUW1kdmNrSm5SVVZCV1U4dlRVRkZURUpCT0UxRVYyUndaRWRvTVZscE1XOWlNMDR3V2xkUmQwNTNXVXRMZDFsQ1FrRkhSSFo2UVVKRVFWRndDa1JEWkc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFphVjFac1lsaHdla3d5Um5aalNFMTBZMGQ0YUdSSFduWmpiVEIzVDBGWlMwdDNXVUlLUWtGSFJIWjZRVUpFVVZGeFJFTm9hRnBVVG10TlJHY3pUV3BvYUZsWFNYcE9SMGsxVDBSamQxcHRWVFJOYW1NMFRtcGFhazVYU1hwYWFteHJUa1JPYlFwTmFteHNUVUk0UjBOcGMwZEJVVkZDWnpjNGQwRlJORVZGVVhkUVkyMVdiV041T1c5YVYwWnJZM2s1ZEZsWGJIVk5RbTlIUTJselIwRlJVVUpuTnpoM0NrRlJPRVZFUVhkTFRWUk5lRTVxU1RGT1ZFRjVUbXBCY0VKbmIzSkNaMFZGUVZsUEwwMUJSVkZDUW5OTlIxZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZta0tURzFPZG1KVE9XeGFWMVowWlc1TmQwZFJXVXRMZDFsQ1FrRkhSSFo2UVVKRlVWRk1SRUZyZUUxRWEzcE5WRUV6VG5wUmQyUm5XVXRMZDFsQ1FrRkhSQXAyZWtGQ1JXZFNiMFJIV205a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFphVjFac1lsaHdla3d5Um5aalNFMTBZMGQ0YUdSSFduWmpiVEIyQ2t4dFpIQmtSMmd4V1drNU0ySXpTbkphYlhoMlpETk5kbU15Ykc1aWFURjNaRmRLYzJGWFRYUlpWMlJzWW01UmRGbFlUbnBhV0ZKNlRHNXNkR0pGUW5rS1dsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JYZFJjVVJEYUdoYVZFNXJUVVJuTTAxcWFHaFpWMGw2VGtkSk5RcFBSR04zV20xVk5FMXFZelJPYWxwcVRsZEplbHBxYkd0T1JFNXRUV3BzYkUxRFJVZERhWE5IUVZGUlFtYzNPSGRCVWxGRlJYZDNVbVF5T1hsaE1scHpDbUl6WkdaYVIyeDZZMGRHTUZreVozZFhkMWxMUzNkWlFrSkJSMFIyZWtGQ1JsRlNUa1JGZEc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFlLV2xkV2JHSlljSHBNTWtaMlkwaE5kR05IZUdoa1IxcDJZMjB3ZGxsWFRqQmhWemwxWTNrNWVXUlhOWHBNZWsxNFRYcGpNMDFxU1hoUFJFa3lUREpHTUFwa1IxWjBZMGhTZWt4NlJYZEdkMWxMUzNkWlFrSkJSMFIyZWtGQ1JtZFJTa1JCWkhkamJXd3lXVmhTYkUxR1NVZERhWE5IUVZGUlFtYzNPSGRCVW1kRkNsSkJlRU5qYlZaM1lucHdiRnBYVm5SbGJrNUJUVlJCTlUxNlJYZE9lbU13VERKR2RtTklUWFJqUjNob1pFZGFkbU50TVVGTlZFMTRUbXBKTVU1VVFYa0tUbXB3ZVZwWFdUWmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFKUjB0Q1oyOXlRbWRGUlVGa1dqVkJaMUZEUWtoM1JXVm5RalJCU0ZsQk0xUXdkd3BoYzJKSVJWUktha2RTTkdOdFYyTXpRWEZLUzFoeWFtVlFTek12YURSd2VXZERPSEEzYnpSQlFVRkhaalo0TnpFMmQwRkJRa0ZOUVZKNlFrWkJhVVZCQ21oQ1RWZEdOWGRVUTA1elMybEdhVXcyZFRsUE5VcElPVzlFUTBoWlFWQkxSMjVyVG5Gc04zUjJOV05EU1VGaWFrd3lSSFZuV2t4aldVaFdUazU0Y1UwS1dsaExjWEYxV2pGQ2VrTTRORGhrTlRJME9XeE1LMHRVVFVGdlIwTkRjVWRUVFRRNVFrRk5SRUV5WTBGTlIxRkRUVUZrY2k4d1VFMHdiMEpSTDBOdVVBcFVNMUpuZEVoSFNGRkxSbWRsWkRKbVJsaERMMDltVmtOMFIzSkpOMHgyUjFwaVpHUmpjRzF4Ym01MlpHOXRlRnBzWjBsM1dtUjZaU3RoVFVZek1YaENDbFk0U0doVlozTldZVmswVVRNMlVFVktRMEZsYlRGRlMzaGlVemxXYW5wRlRVZEVNV3hoZFhOcmQzaFZWV2xFYm10SFEwSUtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0ifX19fQ=="
48
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI5MmM3MzdhZjVkYmI0NzUxOWYzYzFlNjljNDJiNTgzMDBlMDc0YWQ0NjY5YmQyZmM1NDEyNTA5Y2Y4OWVkMGIwIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJRlAxREFQQlJwTUNvZnBmeC9CSmRlcC96WWRqVG5ncWgzRmc1K3lEWWZUcEFpRUEyaTlpNERvYUxnU1dPY0FTRUZkVnJ5THorUktJVEFtY205Y1VQSHFJUmdvPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaGtSRU5EUW5adFowRjNTVUpCWjBsVldISlJlbEJOVm1WMGNHdGtXbE5wZUhkb05YVnRabVJLV0VWQmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlFUlhsTlZFMHdUWHBSZVZkb1kwNU5hbGwzVDBSRmVVMVVUVEZOZWxGNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFZG5sak5WVkRNSEJZUjNsU1VrRXphMkp0UjNCcVNFSmlLMk41TmxJMk9YRXZlV2dLV21sWGNrUlVZWEpVV0ZwUGVWQmlLM0ZzTm1KQlZVdzRUMU0zVjNJNE0xUlFZVmMwWjJsNVJrMXhNMEZ4YWtGYUszRlBRMEpvWjNkbloxbFZUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlV4T1Zkc0NuWnhjRlptYnpKTmFXZGtTWGRQU0c5T1NGTkJia1kwZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJSQldVUldVakJTUVZGSUwwSkhiM2RoU1ZwdFlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKV2JGcFhNVFpqZVRsb1lqTkNlZ3BNV0VKeldWaFNiV0l6U25STWVUVnVZVmhTYjJSWFNYWmtNamw1WVRKYWMySXpaSHBNTTA1d1dqSTBkR05JVm1saVIyeHFURmRHYmxwWE5UQk1WMFo2Q21NeVZqQmplVFUxWWxkNFFXTnRWbTFqZVRsdldsZEdhMk41T1hSWlYyeDFUVVJyUjBOcGMwZEJVVkZDWnpjNGQwRlJSVVZMTW1nd1pFaENlazlwT0hZS1pFYzVjbHBYTkhWWlYwNHdZVmM1ZFdONU5XNWhXRkp2WkZkS01XTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNTSGRaUzB0M1dVSkNRVWRFZG5wQlFncEJaMUZTWkRJNWVXRXlXbk5pTTJSbVdrZHNlbU5IUmpCWk1tZDNUbWRaUzB0M1dVSkNRVWRFZG5wQlFrRjNVVzlPUjAxM1drZFZNVTlVWjNsT01sWnRDazFIU1hwYWJWbDRUa1JyTUZwRVVUSk5hbHBzV1ZkTk1VNXFZM3BPYlZKb1QwUm9iRnBVUVhoQ1oyOXlRbWRGUlVGWlR5OU5RVVZGUWtOT1ZHRlhaSFVLU1VkV05GbFhUakJKU0VJeFdXMTRjRmw1UWtKVU1VSlVTVWRHYmxwWE5UQkpSMFo2WXpKV01HTjZRV2xDWjI5eVFtZEZSVUZaVHk5TlFVVkdRa0pTYkFwYVYxWjBaVzVOZGxsWE9YZGplVEYzWWtkR01GcHRPWGxpVkVGa1FtZHZja0puUlVWQldVOHZUVUZGUjBKQk9YbGFWMXA2VERKb2JGbFhVbnBNTWpGb0NtRlhOSGRQZDFsTFMzZFpRa0pCUjBSMmVrRkNRMEZSZEVSRGRHOWtTRkozWTNwdmRrd3pVblpoTWxaMVRHMUdhbVJIYkhaaWJrMTFXakpzTUdGSVZta0taRmhPYkdOdFRuWmlibEpzWW01UmRWa3lPWFJOU0ZsSFEybHpSMEZSVVVKbk56aDNRVkZyUldGQmVHMWhTRkl3WTBoTk5reDVPVzVoV0ZKdlpGZEpkUXBaTWpsMFRESldiRnBYTVRaamVUbG9Zak5DZWt4WVFuTlpXRkp0WWpOS2RFeDVOVzVoV0ZKdlpGZEpkbVF5T1hsaE1scHpZak5rZWt3elRuQmFNalIwQ21OSVZtbGlSMnhxVEZkR2JscFhOVEJNVjBaNll6SldNR041TlRWaVYzaEJZMjFXYldONU9XOWFWMFpyWTNrNWRGbFhiSFZOUkdkSFEybHpSMEZSVVVJS1p6YzRkMEZSYjBWTFozZHZUa2ROZDFwSFZURlBWR2Q1VGpKV2JVMUhTWHBhYlZsNFRrUnJNRnBFVVRKTmFscHNXVmROTVU1cVkzcE9iVkpvVDBSb2JBcGFWRUZrUW1kdmNrSm5SVVZCV1U4dlRVRkZURUpCT0UxRVYyUndaRWRvTVZscE1XOWlNMDR3V2xkUmQwNTNXVXRMZDFsQ1FrRkhSSFo2UVVKRVFWRndDa1JEWkc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFphVjFac1lsaHdla3d5Um5aalNFMTBZMGQ0YUdSSFduWmpiVEIzVDBGWlMwdDNXVUlLUWtGSFJIWjZRVUpFVVZGeFJFTm5NRmw2UW10YVZGVTFUMFJKTTFwWFdYZFphazV0V21wRk1FOVVVbXRPUkZsNVRtMVdhRmw2VlRKT2VrMHlXa2RGTkFwUFIxWnNUVUk0UjBOcGMwZEJVVkZDWnpjNGQwRlJORVZGVVhkUVkyMVdiV041T1c5YVYwWnJZM2s1ZEZsWGJIVk5RbTlIUTJselIwRlJVVUpuTnpoM0NrRlJPRVZFUVhkTFRWUk5lRTVxU1RGT1ZFRjVUbXBCY0VKbmIzSkNaMFZGUVZsUEwwMUJSVkZDUW5OTlIxZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZta0tURzFPZG1KVE9XeGFWMVowWlc1TmQwZFJXVXRMZDFsQ1FrRkhSSFo2UVVKRlVWRk1SRUZyZUUxRWEzcE5WRUV6VG5wUmQyUm5XVXRMZDFsQ1FrRkhSQXAyZWtGQ1JXZFNiMFJIV205a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFphVjFac1lsaHdla3d5Um5aalNFMTBZMGQ0YUdSSFduWmpiVEIyQ2t4dFpIQmtSMmd4V1drNU0ySXpTbkphYlhoMlpETk5kbU15Ykc1aWFURjNaRmRLYzJGWFRYUlpWMlJzWW01UmRGbFlUbnBhV0ZKNlRHNXNkR0pGUW5rS1dsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JYZFJjVVJEWnpCWmVrSnJXbFJWTlU5RVNUTmFWMWwzV1dwT2JRcGFha1V3VDFSU2EwNUVXWGxPYlZab1dYcFZNazU2VFRKYVIwVTBUMGRXYkUxRFJVZERhWE5IUVZGUlFtYzNPSGRCVWxGRlJYZDNVbVF5T1hsaE1scHpDbUl6WkdaYVIyeDZZMGRHTUZreVozZFhkMWxMUzNkWlFrSkJSMFIyZWtGQ1JsRlNUa1JGZEc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFlLV2xkV2JHSlljSHBNTWtaMlkwaE5kR05IZUdoa1IxcDJZMjB3ZGxsWFRqQmhWemwxWTNrNWVXUlhOWHBNZWsxNFRtcEJlVTlFU1hkT2Vsa3pUREpHTUFwa1IxWjBZMGhTZWt4NlJYZEdkMWxMUzNkWlFrSkJSMFIyZWtGQ1JtZFJTa1JCWkhkamJXd3lXVmhTYkUxR1NVZERhWE5IUVZGUlFtYzNPSGRCVW1kRkNsSkJlRU5qYlZaM1lucHdiRnBYVm5SbGJrNUJUVlJCTlUxNlJYZE9lbU13VERKR2RtTklUWFJqUjNob1pFZGFkbU50TVVGTlZFMTRUbXBKTVU1VVFYa0tUbXB3ZVZwWFdUWmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFKUjBwQ1oyOXlRbWRGUlVGa1dqVkJaMUZEUWtoelJXVlJRak5CU0ZWQk0xUXdkd3BoYzJKSVJWUktha2RTTkdOdFYyTXpRWEZLUzFoeWFtVlFTek12YURSd2VXZERPSEEzYnpSQlFVRkhaamxxWW5KNFowRkJRa0ZOUVZKcVFrVkJhVUY1Q2tKaFFVWklReXRxTVZkVVNGRm5kWFkwWW1wV1ZIVTNibkJqZEV3elNFMWhSMU5ZSzJOMFpUZzJaMGxuU0hvd2FHUm9WbWRIU1dSQ1luaHZOV2xtTWxnS1MzRktjRE5LVUhvd1VWQTFNMVp4ZUZkWmVWaHVjbGwzUTJkWlNVdHZXa2w2YWpCRlFYZE5SR0ZSUVhkYVowbDRRVXRQZUdOcU1HSlBjbFZpWkhsWWRBcFVRMDlOZWprclRXRTFZa2hHWlVsMU5qSTRRMVJCTW1GSmRDdHhkMU5IUTFvd1ZFNHpMMU12ZUZwQ01VTlFVV05KWjBsNFFVeG5jakZaVlRaM01rdGlDbTloWlRNNGJrcFVhVFpvT0hGbVdIcEdRbWg2Vm5GWFR6aE1XamQ2V2pCT1QwVnRZVWhuV0VoR2NHMDFSVVJIVWpjek1ITXhkejA5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLIn19fX0="
52
49
  }
53
50
  ],
54
51
  "timestampVerificationData": {}
@@ -56,8 +53,8 @@
56
53
  "messageSignature": {
57
54
  "messageDigest": {
58
55
  "algorithm": "SHA2_256",
59
- "digest": "dDD/N5DFrLVUIiqNeOOMmLnUw7kJu1Eed/nuIUNuJ8k="
56
+ "digest": "ksc3r127R1GfPB5pxCtYMA4HStRmm9L8VBJQnPie0LA="
60
57
  },
61
- "signature": "MEYCIQCEfwkqmpr0EKb37y9TFZs5dgDcd+sQPtpUFzZPktk06AIhANpA1mb2Dfu3mXufz/jVOMN15mQyI2WFnCGxn4k3MAv+"
58
+ "signature": "MEUCIFP1DAPBRpMCofpfx/BJdep/zYdjTngqh3Fg5+yDYfTpAiEA2i9i4DoaLgSWOcASEFdVryLz+RKITAmcm9cUPHqIRgo="
62
59
  }
63
60
  }
@@ -50,6 +50,23 @@ aops auth login --target <target-name>
50
50
  aops auth status --target <target-name>
51
51
  ```
52
52
 
53
+ ### 2.3 Guarded global npm update
54
+
55
+ Use the TUI Update page for Check, Prepare, and confirmed Apply. For headless
56
+ operation:
57
+
58
+ ```bash
59
+ aops update check --json
60
+ aops update prepare --json
61
+ aops update apply --plan <update-plan.json> --confirm <sha256-plan-id> --json
62
+ ```
63
+
64
+ Prepare is non-mutating and retains exact candidate and rollback tarballs.
65
+ Apply stops Cockpit before Server, installs the public closure as one global
66
+ CLI with its exact nested Server, repeatedly checks loopback health, and
67
+ automatically restores the prior exact closure on failure. It does not publish
68
+ packages or create source-control releases.
69
+
53
70
  ## 3 `init`
54
71
 
55
72
  ### 3.1 Overview
@@ -36,6 +36,30 @@ logs and Ctrl+C cleanup. The Cockpit launcher starts only its independent
36
36
  background process. Both call package-relative Node entrypoints and never
37
37
  carry database secrets in the script or argv.
38
38
 
39
+ ## Guarded global update
40
+
41
+ The bundled Rust TUI has an Update page for an already installed npm-based
42
+ AOPS system. Its Check action is read-only. Prepare downloads and verifies the
43
+ exact public candidate and restore tarballs and writes a plan without changing
44
+ services or packages. Apply requires that exact plan, briefly stops Cockpit
45
+ and Server, installs one global `@aopslabs/aops` CLI with its exact nested
46
+ Server dependency, and repeatedly verifies direct Server, Cockpit, and
47
+ Cockpit-proxy health. Failure automatically restores the prior exact versions,
48
+ package layout, and services.
49
+
50
+ The same lifecycle is available headlessly:
51
+
52
+ ```text
53
+ aops update check --json
54
+ aops update prepare --json
55
+ aops update apply --plan <update-plan.json> --confirm <sha256-plan-id> --json
56
+ ```
57
+
58
+ All metadata and tarball reads are pinned to the public npm registry. A legacy
59
+ top-level Server dedupe is treated as a repairable package-layout issue. The
60
+ updater does not publish packages, create tags/releases, or replace the normal
61
+ candidate acceptance and independent review gates.
62
+
39
63
  ## Capability discovery
40
64
 
41
65
  Start with the relevant CLI family help. When a server has custom or newer domains, query its live catalog:
@@ -2221,6 +2221,17 @@ export function resolveDocImportToolId(dryRun) {
2221
2221
  ? 'docman.document-version.import-headings.plan'
2222
2222
  : 'docman.document-version.import-headings';
2223
2223
  }
2224
+ export function buildDocImportInvokeInput(documentVersionId, input) {
2225
+ if (typeof input.documentVersionId === 'string'
2226
+ && input.documentVersionId.trim().length > 0
2227
+ && input.documentVersionId !== documentVersionId) {
2228
+ throw new Error('doc_import_document_version_id_conflict');
2229
+ }
2230
+ return compactPayload({
2231
+ ...input,
2232
+ documentVersionId,
2233
+ });
2234
+ }
2224
2235
  export async function runDocImportMarkdown(options = {}) {
2225
2236
  try {
2226
2237
  if (options.fromMarkdown !== true) {
@@ -2280,10 +2291,7 @@ export async function runDocImportMarkdown(options = {}) {
2280
2291
  'Run the command with --dry-run --json to inspect result.baselineGuard, add --guard-target for the intended heading, or use --confirm only after reviewing the full-import delta.');
2281
2292
  }
2282
2293
  const toolId = resolveDocImportToolId(dryRun);
2283
- const invokeInput = compactPayload({
2284
- pathParams: { id: documentVersionId },
2285
- body: input,
2286
- });
2294
+ const invokeInput = buildDocImportInvokeInput(documentVersionId, input);
2287
2295
  const result = dryRun
2288
2296
  ? await invokeDocHostedTool(apiState, options, resolvedContext, toolId, invokeInput)
2289
2297
  : await (async () => {
@@ -0,0 +1,512 @@
1
+ import assert from 'node:assert/strict';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { createHash } from 'node:crypto';
4
+ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, writeFileSync, } from 'node:fs';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { compareCanonicalText } from '@aopslabs/artifact-trust-contracts';
8
+ import { Command } from 'commander';
9
+ const CHECK_CONTRACT = 'aops.global-update-check/v1';
10
+ const PLAN_CONTRACT = 'aops.global-update-plan/v1';
11
+ const RESULT_CONTRACT = 'aops.global-update-result/v1';
12
+ const PUBLIC_REGISTRY = 'https://registry.npmjs.org';
13
+ const EXACT_STABLE_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u;
14
+ const PLAN_ID = /^sha256:[a-f0-9]{64}$/u;
15
+ const SHA256 = /^[a-f0-9]{64}$/u;
16
+ const SHA512_INTEGRITY = /^sha512-[A-Za-z0-9+/]+={0,2}$/u;
17
+ const PACKAGE_NAMES = ['@aopslabs/aops', '@aopslabs/aops-server'];
18
+ const HEALTH_SAMPLES = 4;
19
+ const HEALTH_INTERVAL_MS = 3_000;
20
+ function cleanEnvironment() {
21
+ return {
22
+ ...process.env,
23
+ NPM_TOKEN: '',
24
+ NODE_AUTH_TOKEN: '',
25
+ GH_TOKEN: '',
26
+ GITHUB_TOKEN: '',
27
+ NPM_CONFIG_REGISTRY: PUBLIC_REGISTRY,
28
+ NPM_CONFIG_USERCONFIG: os.devNull,
29
+ npm_config_registry: PUBLIC_REGISTRY,
30
+ npm_config_userconfig: os.devNull,
31
+ };
32
+ }
33
+ function defaultRunner(command, args, cwd = process.cwd()) {
34
+ const result = spawnSync(command, args, {
35
+ cwd,
36
+ encoding: 'utf8',
37
+ shell: false,
38
+ windowsHide: true,
39
+ maxBuffer: 32 * 1024 * 1024,
40
+ env: cleanEnvironment(),
41
+ });
42
+ if (result.error)
43
+ throw result.error;
44
+ assert.equal(result.status, 0, `${command} ${args.join(' ')} failed\n${result.stdout}\n${result.stderr}`);
45
+ return result.stdout;
46
+ }
47
+ function npmCommand() {
48
+ return process.platform === 'win32' ? 'npm.cmd' : 'npm';
49
+ }
50
+ export function publicNpmArgs(args) {
51
+ return [
52
+ ...args,
53
+ `--registry=${PUBLIC_REGISTRY}`,
54
+ `--@aopslabs:registry=${PUBLIC_REGISTRY}`,
55
+ `--userconfig=${os.devNull}`,
56
+ ];
57
+ }
58
+ function parseJson(value, label) {
59
+ try {
60
+ return JSON.parse(value);
61
+ }
62
+ catch {
63
+ throw new Error(`${label}_invalid_json`);
64
+ }
65
+ }
66
+ function exactVersion(value, label) {
67
+ if (typeof value !== 'string')
68
+ throw new Error(`${label} must be a string`);
69
+ assert.match(value, EXACT_STABLE_VERSION, `${label} must be an exact stable version`);
70
+ return value;
71
+ }
72
+ export function compareStableVersions(left, right) {
73
+ const leftParts = exactVersion(left, 'left version').split('.').map(Number);
74
+ const rightParts = exactVersion(right, 'right version').split('.').map(Number);
75
+ for (let index = 0; index < 3; index += 1) {
76
+ if (leftParts[index] !== rightParts[index])
77
+ return leftParts[index] - rightParts[index];
78
+ }
79
+ return 0;
80
+ }
81
+ function sha256(file) {
82
+ return createHash('sha256').update(readFileSync(file)).digest('hex');
83
+ }
84
+ function plainDirectory(candidate, label) {
85
+ const absolute = path.resolve(candidate);
86
+ const stat = lstatSync(absolute);
87
+ assert.equal(stat.isDirectory() && !stat.isSymbolicLink(), true, `${label} must be a plain directory`);
88
+ return realpathSync.native(absolute);
89
+ }
90
+ function plainFile(candidate, label) {
91
+ const absolute = path.resolve(candidate);
92
+ const stat = lstatSync(absolute);
93
+ assert.equal(stat.isFile() && !stat.isSymbolicLink(), true, `${label} must be a plain file`);
94
+ return realpathSync.native(absolute);
95
+ }
96
+ function ensureWithin(parent, candidate, label) {
97
+ const relative = path.relative(parent, candidate);
98
+ assert.equal(Boolean(relative) && !relative.startsWith('..') && !path.isAbsolute(relative), true, `${label} must stay inside ${parent}`);
99
+ return candidate;
100
+ }
101
+ function packageManifest(packageRoot, expectedName) {
102
+ const manifestPath = plainFile(path.join(packageRoot, 'package.json'), `${expectedName} manifest`);
103
+ const manifest = parseJson(readFileSync(manifestPath, 'utf8'), `${expectedName}_manifest`);
104
+ assert.equal(manifest.name, expectedName, `${expectedName} package identity mismatch`);
105
+ exactVersion(manifest.version, `${expectedName} version`);
106
+ return manifest;
107
+ }
108
+ function inspectGlobalInstall(run) {
109
+ const npm = npmCommand();
110
+ const globalPrefix = plainDirectory(run(npm, ['prefix', '--global']).trim(), 'global npm prefix');
111
+ const globalRoot = plainDirectory(run(npm, ['root', '--global']).trim(), 'global npm root');
112
+ ensureWithin(globalPrefix, globalRoot, 'global npm root');
113
+ const cliRoot = path.join(globalRoot, '@aopslabs', 'aops');
114
+ const cli = packageManifest(cliRoot, '@aopslabs/aops');
115
+ const nestedServerRoot = path.join(cliRoot, 'node_modules', '@aopslabs', 'aops-server');
116
+ const dependencies = cli.dependencies;
117
+ const exactServerDependency = exactVersion(dependencies?.['@aopslabs/aops-server'], 'installed CLI Server dependency');
118
+ const topLevelServerRoot = path.join(globalRoot, '@aopslabs', 'aops-server');
119
+ const nestedServer = existsSync(path.join(nestedServerRoot, 'package.json'));
120
+ const topLevelServer = existsSync(path.join(topLevelServerRoot, 'package.json'));
121
+ assert.equal(nestedServer || topLevelServer, true, 'global AOPS Server package was not found');
122
+ for (const [serverRoot, placement] of [
123
+ [nestedServerRoot, 'nested'],
124
+ [topLevelServerRoot, 'top-level'],
125
+ ]) {
126
+ if (!existsSync(path.join(serverRoot, 'package.json')))
127
+ continue;
128
+ const server = packageManifest(serverRoot, '@aopslabs/aops-server');
129
+ assert.equal(exactVersion(server.version, `installed ${placement} Server version`), exactServerDependency, `installed ${placement} Server does not match the CLI exact dependency`);
130
+ }
131
+ const cliPath = plainFile(path.join(cliRoot, 'dist', 'main.js'), 'global AOPS CLI entrypoint');
132
+ return {
133
+ globalPrefix,
134
+ globalRoot,
135
+ cliPath,
136
+ packages: {
137
+ cli: exactVersion(cli.version, 'installed CLI version'),
138
+ server: exactServerDependency,
139
+ },
140
+ topology: { nestedServer, topLevelServer },
141
+ };
142
+ }
143
+ function npmViewString(run, selector, field) {
144
+ const value = parseJson(run(npmCommand(), publicNpmArgs(['view', selector, field, '--json'])).trim(), `npm_view_${field}`);
145
+ if (typeof value !== 'string')
146
+ throw new Error(`${selector} ${field} must be a string`);
147
+ return value;
148
+ }
149
+ function availableClosure(run) {
150
+ const cli = exactVersion(npmViewString(run, '@aopslabs/aops', 'dist-tags.latest'), 'latest CLI version');
151
+ const server = exactVersion(npmViewString(run, `@aopslabs/aops@${cli}`, 'dependencies.@aopslabs/aops-server'), 'CLI Server dependency');
152
+ return { cli, server };
153
+ }
154
+ export function inspectGlobalUpdate(run = defaultRunner) {
155
+ const installation = inspectGlobalInstall(run);
156
+ const installed = installation.packages;
157
+ const available = availableClosure(run);
158
+ assert.equal(compareStableVersions(available.cli, installed.cli) >= 0, true, 'public npm latest must not downgrade the installed CLI');
159
+ const cliVersionDelta = compareStableVersions(available.cli, installed.cli);
160
+ const cliUpdateAvailable = cliVersionDelta > 0;
161
+ const updateAvailable = cliUpdateAvailable ||
162
+ !installation.topology.nestedServer ||
163
+ installation.topology.topLevelServer;
164
+ assert.equal(compareStableVersions(available.server, installed.server) >= 0 || cliUpdateAvailable, true, 'latest CLI closure would unexpectedly downgrade the installed Server without a CLI update');
165
+ return {
166
+ schemaVersion: 1,
167
+ contract: CHECK_CONTRACT,
168
+ status: updateAvailable ? 'update-available' : 'current',
169
+ installed,
170
+ available,
171
+ updateAvailable,
172
+ installedTopology: installation.topology,
173
+ registry: PUBLIC_REGISTRY,
174
+ };
175
+ }
176
+ function runInstalledJson(run, cliPath, args) {
177
+ return parseJson(run(process.execPath, [cliPath, ...args]).trim(), args.join('_'));
178
+ }
179
+ function serviceSnapshot(run, cliPath) {
180
+ return {
181
+ server: runInstalledJson(run, cliPath, ['server', 'status', '--json']),
182
+ cockpit: runInstalledJson(run, cliPath, ['cockpit', 'status', '--json']),
183
+ };
184
+ }
185
+ function assertHealthyServices(services) {
186
+ assert.equal(services.server.runtimeState, 'running', 'AOPS Server must be running before update');
187
+ assert.equal(services.server.liveness?.health, 'healthy', 'AOPS Server must be healthy before update');
188
+ assert.equal(services.cockpit.runtimeState, 'running', 'AOPS Cockpit must be running before update');
189
+ assert.equal(services.cockpit.health, 'healthy', 'AOPS Cockpit must be healthy before update');
190
+ }
191
+ function packRegistryPackage(run, destination, name, version) {
192
+ const packed = parseJson(run(npmCommand(), publicNpmArgs([
193
+ 'pack',
194
+ `${name}@${version}`,
195
+ '--ignore-scripts',
196
+ '--json',
197
+ '--pack-destination',
198
+ destination,
199
+ ])), 'npm_pack');
200
+ assert.equal(packed.length, 1, `${name}@${version} must produce one tarball`);
201
+ assert.equal(packed[0].name, name);
202
+ assert.equal(packed[0].version, version);
203
+ const registryIntegrity = npmViewString(run, `${name}@${version}`, 'dist.integrity');
204
+ assert.equal(packed[0].integrity, registryIntegrity, `${name}@${version} integrity mismatch`);
205
+ const file = plainFile(path.join(destination, packed[0].filename), `${name}@${version} tarball`);
206
+ return { name, version, path: file, integrity: registryIntegrity, sha256: sha256(file) };
207
+ }
208
+ function canonicalJson(value) {
209
+ if (Array.isArray(value))
210
+ return value.map((entry) => canonicalJson(entry));
211
+ if (value !== null && typeof value === 'object') {
212
+ return Object.fromEntries(Object.entries(value)
213
+ .sort(([left], [right]) => compareCanonicalText(left, right))
214
+ .map(([key, entry]) => [key, canonicalJson(entry)]));
215
+ }
216
+ return value;
217
+ }
218
+ function canonicalPlanBody(plan) {
219
+ return JSON.stringify(canonicalJson(plan));
220
+ }
221
+ export function computeGlobalUpdatePlanId(plan) {
222
+ return `sha256:${createHash('sha256').update(canonicalPlanBody(plan)).digest('hex')}`;
223
+ }
224
+ function defaultUpdateRoot(configRoot) {
225
+ const root = configRoot?.trim()
226
+ ? path.resolve(configRoot)
227
+ : path.join(os.homedir(), '.aops');
228
+ if (!existsSync(root))
229
+ mkdirSync(root, { recursive: true, mode: 0o700 });
230
+ return plainDirectory(root, 'AOPS config root');
231
+ }
232
+ export function prepareGlobalUpdate(options = {}, run = defaultRunner) {
233
+ const check = inspectGlobalUpdate(run);
234
+ assert.equal(check.updateAvailable, true, 'aops_global_update_not_available');
235
+ const installed = inspectGlobalInstall(run);
236
+ const services = serviceSnapshot(run, installed.cliPath);
237
+ assertHealthyServices(services);
238
+ const configRoot = defaultUpdateRoot(options.configRoot);
239
+ const updatesRoot = path.join(configRoot, 'global-updates');
240
+ mkdirSync(updatesRoot, { recursive: true, mode: 0o700 });
241
+ const operationRoot = path.join(updatesRoot, `${Date.now()}-${process.pid}`);
242
+ mkdirSync(operationRoot, { recursive: false, mode: 0o700 });
243
+ const candidateRoot = path.join(operationRoot, 'candidate');
244
+ const restoreRoot = path.join(operationRoot, 'restore');
245
+ const cacheRoot = path.join(operationRoot, 'cache');
246
+ mkdirSync(candidateRoot, { mode: 0o700 });
247
+ mkdirSync(restoreRoot, { mode: 0o700 });
248
+ mkdirSync(cacheRoot, { mode: 0o700 });
249
+ const candidates = [
250
+ packRegistryPackage(run, candidateRoot, '@aopslabs/aops', check.available.cli),
251
+ packRegistryPackage(run, candidateRoot, '@aopslabs/aops-server', check.available.server),
252
+ ];
253
+ const restorePackages = [
254
+ packRegistryPackage(run, restoreRoot, '@aopslabs/aops', check.installed.cli),
255
+ packRegistryPackage(run, restoreRoot, '@aopslabs/aops-server', check.installed.server),
256
+ ];
257
+ const body = {
258
+ schemaVersion: 1,
259
+ contract: PLAN_CONTRACT,
260
+ createdAt: new Date().toISOString(),
261
+ globalPrefix: installed.globalPrefix,
262
+ globalRoot: installed.globalRoot,
263
+ cliPath: installed.cliPath,
264
+ operationRoot,
265
+ prior: { packages: installed.packages, topology: installed.topology, services },
266
+ target: {
267
+ packages: check.available,
268
+ topology: { nestedServer: true, topLevelServer: false },
269
+ },
270
+ candidates,
271
+ restorePackages,
272
+ safety: {
273
+ candidateIntegrity: 'verified-from-public-registry',
274
+ restoreIntegrity: 'verified-from-public-registry',
275
+ automaticRollback: true,
276
+ requiresExactConfirmation: true,
277
+ healthSamples: HEALTH_SAMPLES,
278
+ healthIntervalMs: HEALTH_INTERVAL_MS,
279
+ },
280
+ };
281
+ const plan = { ...body, planId: computeGlobalUpdatePlanId(body) };
282
+ const planPath = path.join(operationRoot, 'update-plan.json');
283
+ writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
284
+ return { check, plan, planPath };
285
+ }
286
+ function packageRecordByName(records, name) {
287
+ const matches = records.filter((record) => record.name === name);
288
+ assert.equal(matches.length, 1, `update plan must contain exactly one ${name} tarball`);
289
+ return matches[0];
290
+ }
291
+ function validateRecordSet(records, expected, root, label) {
292
+ assert.equal(records.length, PACKAGE_NAMES.length, `${label} must contain exactly two packages`);
293
+ for (const [name, version] of [
294
+ ['@aopslabs/aops', expected.cli],
295
+ ['@aopslabs/aops-server', expected.server],
296
+ ]) {
297
+ const record = packageRecordByName(records, name);
298
+ assert.equal(exactVersion(record.version, `${name} ${label} version`), version);
299
+ assert.match(record.integrity, SHA512_INTEGRITY, `${name} ${label} integrity is invalid`);
300
+ assert.match(record.sha256, SHA256, `${name} ${label} sha256 is invalid`);
301
+ const file = plainFile(record.path, `${name} ${label} tarball`);
302
+ ensureWithin(root, file, `${name} ${label} tarball`);
303
+ assert.equal(file, record.path, `${name} ${label} tarball must be canonical`);
304
+ assert.equal(sha256(file), record.sha256, `${name} tarball changed after planning`);
305
+ }
306
+ }
307
+ export function readGlobalUpdatePlan(planPath) {
308
+ const resolved = plainFile(planPath, 'global update plan');
309
+ const plan = parseJson(readFileSync(resolved, 'utf8'), 'global_update_plan');
310
+ assert.equal(plan.schemaVersion, 1);
311
+ assert.equal(plan.contract, PLAN_CONTRACT);
312
+ assert.match(plan.planId, PLAN_ID);
313
+ const { planId, ...body } = plan;
314
+ assert.equal(planId, computeGlobalUpdatePlanId(body), 'global update plan identity mismatch');
315
+ plainDirectory(plan.globalPrefix, 'planned global npm prefix');
316
+ plainDirectory(plan.globalRoot, 'planned global npm root');
317
+ ensureWithin(plan.globalPrefix, plan.globalRoot, 'planned global npm root');
318
+ const operationRoot = plainDirectory(plan.operationRoot, 'global update operation root');
319
+ assert.equal(operationRoot, path.dirname(resolved), 'global update plan must stay at its operation root');
320
+ assert.deepEqual(plan.target.topology, { nestedServer: true, topLevelServer: false });
321
+ exactVersion(plan.prior.packages.cli, 'prior CLI version');
322
+ exactVersion(plan.prior.packages.server, 'prior Server version');
323
+ exactVersion(plan.target.packages.cli, 'target CLI version');
324
+ exactVersion(plan.target.packages.server, 'target Server version');
325
+ validateRecordSet(plan.candidates, plan.target.packages, operationRoot, 'candidate set');
326
+ validateRecordSet(plan.restorePackages, plan.prior.packages, operationRoot, 'restore set');
327
+ assert.equal(plan.safety.candidateIntegrity, 'verified-from-public-registry');
328
+ assert.equal(plan.safety.restoreIntegrity, 'verified-from-public-registry');
329
+ assert.equal(plan.safety.automaticRollback, true);
330
+ assert.equal(plan.safety.requiresExactConfirmation, true);
331
+ assert.equal(plan.safety.healthSamples, HEALTH_SAMPLES);
332
+ assert.equal(plan.safety.healthIntervalMs, HEALTH_INTERVAL_MS);
333
+ return plan;
334
+ }
335
+ export function installGlobalUpdateClosure(run, plan, records, topology) {
336
+ const cli = packageRecordByName(records, '@aopslabs/aops');
337
+ const server = packageRecordByName(records, '@aopslabs/aops-server');
338
+ const cacheRoot = path.join(plan.operationRoot, 'cache');
339
+ mkdirSync(cacheRoot, { recursive: true, mode: 0o700 });
340
+ run(npmCommand(), publicNpmArgs(['cache', 'add', server.path, `--cache=${cacheRoot}`]));
341
+ const topLevelServerRoot = path.join(plan.globalRoot, '@aopslabs', 'aops-server');
342
+ if (existsSync(path.join(topLevelServerRoot, 'package.json'))) {
343
+ run(npmCommand(), publicNpmArgs([
344
+ '--prefix',
345
+ plan.globalPrefix,
346
+ 'uninstall',
347
+ '--global',
348
+ '--ignore-scripts',
349
+ '--fund=false',
350
+ '--audit=false',
351
+ '@aopslabs/aops-server',
352
+ ]));
353
+ }
354
+ const commonInstallArgs = [
355
+ '--prefix',
356
+ plan.globalPrefix,
357
+ 'install',
358
+ '--global',
359
+ '--ignore-scripts',
360
+ '--prefer-offline',
361
+ `--cache=${cacheRoot}`,
362
+ '--fund=false',
363
+ '--audit=false',
364
+ ];
365
+ if (topology.topLevelServer && !topology.nestedServer) {
366
+ run(npmCommand(), publicNpmArgs([...commonInstallArgs, cli.path, server.path]));
367
+ return;
368
+ }
369
+ run(npmCommand(), publicNpmArgs([...commonInstallArgs, cli.path]));
370
+ if (topology.topLevelServer) {
371
+ run(npmCommand(), publicNpmArgs([
372
+ ...commonInstallArgs,
373
+ server.path,
374
+ ]));
375
+ }
376
+ }
377
+ function stopService(run, cliPath, service, bestEffort = false) {
378
+ try {
379
+ run(process.execPath, [cliPath, service, 'stop', '--json']);
380
+ }
381
+ catch (error) {
382
+ if (!bestEffort)
383
+ throw error;
384
+ }
385
+ }
386
+ function startService(run, cliPath, service) {
387
+ run(process.execPath, [cliPath, service, 'start', '--json']);
388
+ }
389
+ const defaultExecutionDependencies = {
390
+ fetch: globalThis.fetch.bind(globalThis),
391
+ sleep: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
392
+ };
393
+ async function assertStableHealth(run, plan, execution) {
394
+ const evidence = [];
395
+ for (let sample = 1; sample <= plan.safety.healthSamples; sample += 1) {
396
+ const installed = inspectGlobalInstall(run);
397
+ const services = serviceSnapshot(run, installed.cliPath);
398
+ assertHealthyServices(services);
399
+ const serverOrigin = validateLoopbackOrigin(services.server.origin, 'AOPS Server origin');
400
+ const cockpitOrigin = validateLoopbackOrigin(services.cockpit.origin, 'AOPS Cockpit origin');
401
+ const endpoints = [];
402
+ for (const [name, url] of [
403
+ ['server', `${serverOrigin}/api/health`],
404
+ ['cockpit', cockpitOrigin],
405
+ ['cockpit-proxy', `${cockpitOrigin}/api/health`],
406
+ ]) {
407
+ const response = await execution.fetch(url, { cache: 'no-store', signal: AbortSignal.timeout(15_000) });
408
+ assert.equal(response.status, 200, `${name} health returned ${response.status}`);
409
+ const body = await response.arrayBuffer();
410
+ endpoints.push({ name, url, status: response.status, bytes: body.byteLength });
411
+ }
412
+ evidence.push({ sample, observedAt: new Date().toISOString(), endpoints });
413
+ if (sample < plan.safety.healthSamples) {
414
+ await execution.sleep(plan.safety.healthIntervalMs);
415
+ }
416
+ }
417
+ return evidence;
418
+ }
419
+ export function validateLoopbackOrigin(value, label) {
420
+ assert.equal(typeof value, 'string', `${label} must be a string`);
421
+ const url = new URL(value);
422
+ assert.equal(url.protocol, 'http:', `${label} must use http`);
423
+ assert.equal(url.username, '', `${label} must not include credentials`);
424
+ assert.equal(url.password, '', `${label} must not include credentials`);
425
+ assert.equal(['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname), true, `${label} must be loopback`);
426
+ assert.equal(url.pathname, '/', `${label} must not include a path`);
427
+ assert.equal(url.search, '', `${label} must not include a query`);
428
+ assert.equal(url.hash, '', `${label} must not include a fragment`);
429
+ return url.origin;
430
+ }
431
+ export async function applyGlobalUpdate(options, run = defaultRunner, execution = defaultExecutionDependencies) {
432
+ const plan = readGlobalUpdatePlan(options.plan);
433
+ assert.equal(options.confirm, plan.planId, 'global update confirmation does not match the exact plan');
434
+ const current = inspectGlobalInstall(run);
435
+ assert.deepEqual(current.packages, plan.prior.packages, 'global packages changed after update planning');
436
+ assert.deepEqual(current.topology, plan.prior.topology, 'global package topology changed after update planning');
437
+ assert.equal(current.globalPrefix, plan.globalPrefix, 'global npm prefix changed after update planning');
438
+ assertHealthyServices(serviceSnapshot(run, current.cliPath));
439
+ const events = [];
440
+ try {
441
+ stopService(run, current.cliPath, 'cockpit');
442
+ events.push('stopped:cockpit');
443
+ stopService(run, current.cliPath, 'server');
444
+ events.push('stopped:server');
445
+ installGlobalUpdateClosure(run, plan, plan.candidates, plan.target.topology);
446
+ events.push('installed:candidate');
447
+ const updated = inspectGlobalInstall(run);
448
+ assert.deepEqual(updated.packages, plan.target.packages, 'installed candidate closure is not exact');
449
+ assert.deepEqual(updated.topology, plan.target.topology, 'installed candidate topology is not canonical');
450
+ startService(run, updated.cliPath, 'server');
451
+ events.push('started:server');
452
+ startService(run, updated.cliPath, 'cockpit');
453
+ events.push('started:cockpit');
454
+ const healthEvidence = await assertStableHealth(run, plan, execution);
455
+ return {
456
+ schemaVersion: 1,
457
+ contract: RESULT_CONTRACT,
458
+ status: 'updated',
459
+ planId: plan.planId,
460
+ installed: updated.packages,
461
+ rollbackPerformed: false,
462
+ events,
463
+ healthEvidence,
464
+ next: 'Exit and reopen the AOPS TUI to run the newly installed binary.',
465
+ };
466
+ }
467
+ catch (updateError) {
468
+ events.push('rollback:started');
469
+ try {
470
+ stopService(run, plan.cliPath, 'cockpit', true);
471
+ stopService(run, plan.cliPath, 'server', true);
472
+ installGlobalUpdateClosure(run, plan, plan.restorePackages, plan.prior.topology);
473
+ events.push('installed:restore');
474
+ const restored = inspectGlobalInstall(run);
475
+ assert.deepEqual(restored.packages, plan.prior.packages, 'rollback package closure is not exact');
476
+ assert.deepEqual(restored.topology, plan.prior.topology, 'rollback package topology is not exact');
477
+ startService(run, restored.cliPath, 'server');
478
+ startService(run, restored.cliPath, 'cockpit');
479
+ await assertStableHealth(run, plan, execution);
480
+ events.push('rollback:healthy');
481
+ }
482
+ catch (rollbackError) {
483
+ throw new AggregateError([updateError, rollbackError], `global update and automatic rollback both failed; recovery artifacts remain at ${plan.operationRoot}`);
484
+ }
485
+ throw new Error('global update failed; the prior exact packages were restored and are healthy', { cause: updateError });
486
+ }
487
+ }
488
+ function output(value, json) {
489
+ process.stdout.write(`${JSON.stringify(value, null, json ? 0 : 2)}\n`);
490
+ }
491
+ export function makeGlobalUpdateCommand() {
492
+ const command = new Command('update').description('Check, prepare, and apply a guarded global AOPS npm update');
493
+ command
494
+ .command('check')
495
+ .description('Compare the installed global AOPS closure with the public npm latest tag')
496
+ .option('--json', 'Output JSON')
497
+ .action((options) => output(inspectGlobalUpdate(), options.json === true));
498
+ command
499
+ .command('prepare')
500
+ .description('Download and verify exact candidate and rollback tarballs without changing the installation')
501
+ .option('--config-root <path>', 'AOPS config root for the immutable update plan')
502
+ .option('--json', 'Output JSON')
503
+ .action((options) => output(prepareGlobalUpdate(options), options.json === true));
504
+ command
505
+ .command('apply')
506
+ .description('Apply one exact prepared plan with automatic rollback and health verification')
507
+ .requiredOption('--plan <path>', 'Exact update-plan.json path returned by prepare')
508
+ .requiredOption('--confirm <plan-id>', 'Exact sha256 plan id returned by prepare')
509
+ .option('--json', 'Output JSON')
510
+ .action(async (options) => output(await applyGlobalUpdate(options), options.json === true));
511
+ return command;
512
+ }
@@ -543,9 +543,9 @@ function defaultNativeRoot() {
543
543
  return moduleDirectory.endsWith(`${path.sep}dist`) ? bundled : compiledOrSource;
544
544
  }
545
545
  function injectedNativeManifestSha256() {
546
- return typeof "b97413fd3d4d2568a5a37483a7bcea62ceb48cadbbb76dbabb9109e7cf1ca161" === 'undefined'
546
+ return typeof "a1ddbb2b62d0b9b929667faf1404db6d2623ae8fd448ba770ccf3b59c478cbd2" === 'undefined'
547
547
  ? undefined
548
- : "b97413fd3d4d2568a5a37483a7bcea62ceb48cadbbb76dbabb9109e7cf1ca161";
548
+ : "a1ddbb2b62d0b9b929667faf1404db6d2623ae8fd448ba770ccf3b59c478cbd2";
549
549
  }
550
550
  function sha256(bytes) {
551
551
  return createHash('sha256').update(bytes).digest('hex');
package/dist/main.js CHANGED
@@ -37,6 +37,7 @@ import { makeCommunityCockpitCommand } from './commands/community-cockpit.js';
37
37
  import { makeCommunityDoctorCommand } from './commands/community-doctor.js';
38
38
  import { makeTargetCommand } from './commands/target.js';
39
39
  import { makeVersionCommand } from './commands/version.js';
40
+ import { makeGlobalUpdateCommand } from './commands/global-update.js';
40
41
  import { launchBundledTui, shouldLaunchBundledTui } from './lib/tui-launcher.js';
41
42
  import { CommunityDiagnosticError, formatCommunityDiagnostic, } from './lib/community-diagnostic.js';
42
43
  import { resolveCliApiBaseUrl } from './utils/api.js';
@@ -152,6 +153,7 @@ export function buildCommunityProgram() {
152
153
  program.addCommand(makeCommunityDoctorCommand());
153
154
  program.addCommand(makeTargetCommand());
154
155
  program.addCommand(makeVersionCommand());
156
+ program.addCommand(makeGlobalUpdateCommand());
155
157
  program.addHelpText('after', `
156
158
  AOPS Community is a single-user, self-hosted/local-trusted distribution.
157
159
  Canonical writes go to the local AOPS server; .aops/** remains a read-only cache.
@@ -42,7 +42,7 @@
42
42
  "capabilityClass": "windows-ntfs-crash-recoverable-v1",
43
43
  "qualification": {
44
44
  "relativePath": "qualifications/win32-x64.json",
45
- "sha256": "36fe11856fe825462846197238926c508a8753f39b6eb306b3c0e638659ef0c7"
45
+ "sha256": "c02837036e8e0254db24c0c7e7db49e24acc659359ebc42ce9941da1173a1cab"
46
46
  }
47
47
  }
48
48
  ]
@@ -7,7 +7,7 @@
7
7
  "filesystem": "NTFS",
8
8
  "primitiveProfile": "windows-createfile-flush-movefileex-v1",
9
9
  "capabilityClass": "windows-ntfs-crash-recoverable-v1",
10
- "evidenceSha256": "86523b4e9d51c687d3386aaa006ce6bee7c8483b0c745d88fcceaf8ad22ae8aa",
10
+ "evidenceSha256": "011dad8836525e5fa57f452a7f199f9c3fd644170938a765253a409c051237fe",
11
11
  "crashInjectionPoints": [
12
12
  "authority-history",
13
13
  "authority-current",
Binary file
Binary file
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@aopslabs/aops",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
4
4
  "type": "module",
5
5
  "description": "AOPS CLI and terminal setup application.",
6
- "aopsDockerServerVersion": "0.2.11",
6
+ "aopsDockerServerVersion": "0.2.13",
7
7
  "license": "SEE LICENSE IN LICENSE",
8
8
  "repository": {
9
9
  "type": "git",
@@ -43,6 +43,7 @@
43
43
  "test:commercial-performance": "node --test test/commercial-performance.test.mjs",
44
44
  "test:package-identity": "node --test test/package-identity.test.mjs test/npm-tar-entry-mode.test.mjs",
45
45
  "test:tui-launcher": "node --test test/tui-launcher.test.mjs",
46
+ "test:global-update": "node --test test/global-update.test.mjs",
46
47
  "test:skill-discovery": "node --test test/skill-discovery.test.mjs",
47
48
  "test:target-auth": "node --test test/target-auth.test.mjs test/device-login.test.mjs",
48
49
  "test:target-transport": "node --test test/target-transport.test.mjs",
@@ -53,12 +54,12 @@
53
54
  "test:hosted-contract-hardening": "node --test test/hosted-contract-hardening.test.mjs",
54
55
  "test:home": "node --test test/home-menu.test.mjs",
55
56
  "test:launchers": "node --test test/terminal-launchers.test.mjs",
56
- "test:shortcuts": "pnpm --dir ../.. run build && pnpm run test:home && pnpm run test:cockpit && pnpm run test:launchers && pnpm run test:assets-menu && pnpm run test:agent-assets-content && pnpm run test:chatv3-session-store && pnpm run test:projectman-review-evidence && pnpm run test:setup-install && pnpm run test:container-runtime && pnpm run test:native-lifecycle && pnpm run test:operation-journal && pnpm run test:commercial-canonical-order && pnpm run test:commercial-runtime-closure && pnpm run test:commercial-artifact && pnpm run test:commercial-final-readiness && pnpm run test:commercial-admission && pnpm run test:commercial-license && pnpm run test:commercial-runbook && pnpm run test:package-identity && pnpm run test:skill-discovery && pnpm run test:target-transport && pnpm run test:target-auth && pnpm run test:r6-auth-cutover && pnpm run test:r6-cutover-baseline && pnpm run test:hosted-contract-hardening",
57
+ "test:shortcuts": "pnpm --dir ../.. run build && pnpm run test:home && pnpm run test:cockpit && pnpm run test:launchers && pnpm run test:assets-menu && pnpm run test:agent-assets-content && pnpm run test:chatv3-session-store && pnpm run test:projectman-review-evidence && pnpm run test:setup-install && pnpm run test:container-runtime && pnpm run test:native-lifecycle && pnpm run test:operation-journal && pnpm run test:commercial-canonical-order && pnpm run test:commercial-runtime-closure && pnpm run test:commercial-artifact && pnpm run test:commercial-final-readiness && pnpm run test:commercial-admission && pnpm run test:commercial-license && pnpm run test:commercial-runbook && pnpm run test:package-identity && pnpm run test:tui-launcher && pnpm run test:global-update && pnpm run test:skill-discovery && pnpm run test:target-transport && pnpm run test:target-auth && pnpm run test:r6-auth-cutover && pnpm run test:r6-cutover-baseline && pnpm run test:hosted-contract-hardening",
57
58
  "typecheck": "tsc -p tsconfig.json --noEmit",
58
59
  "start": "node dist/main.js"
59
60
  },
60
61
  "dependencies": {
61
- "@aopslabs/aops-server": "0.2.11",
62
+ "@aopslabs/aops-server": "0.2.13",
62
63
  "@aopslabs/artifact-trust-contracts": "0.3.1",
63
64
  "@aopslabs/cli-kit": "0.1.0",
64
65
  "@aopslabs/aops-host-registration": "0.2.1",