@clawops/cli 1.7.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +37 -92
  2. package/dist/{apply-BTZFFGAD.js → apply-PZ5IIU7Z.js} +5 -4
  3. package/dist/{aws-D7Y6LCGK.js → aws-L4RR2LSE.js} +1 -1
  4. package/dist/{azure-JQAMNVHN.js → azure-7OXQENQL.js} +1 -1
  5. package/dist/{bootstrap-RY4VOSDJ.js → bootstrap-HL4DNUNG.js} +13 -4
  6. package/dist/bootstrap.sh.tmpl +204 -0
  7. package/dist/chunk-2YOP6N7X.js +126 -0
  8. package/dist/{chunk-GJEF6UQA.js → chunk-3XK66DKK.js} +100 -16
  9. package/dist/{chunk-ISFHLA4G.js → chunk-5SPESD5N.js} +8 -6
  10. package/dist/{chunk-YTH4L2GN.js → chunk-6X45DDGH.js} +5 -4
  11. package/dist/{chunk-XKT42M34.js → chunk-C5X375RO.js} +14 -1
  12. package/dist/{chunk-LCKD7L7X.js → chunk-DQDAWNGB.js} +1 -1
  13. package/dist/{chunk-CG3Y7Y2R.js → chunk-FSUWPL7Q.js} +9 -9
  14. package/dist/{chunk-FQ4JXUCR.js → chunk-NESXDU5F.js} +7 -4
  15. package/dist/{chunk-ZFNPM2WG.js → chunk-O3F7OGH7.js} +40 -3
  16. package/dist/{chunk-3MFZ7E74.js → chunk-P5LKWRPL.js} +3 -3
  17. package/dist/chunk-PVUVI35Y.js +29 -0
  18. package/dist/cli.js +122 -68
  19. package/dist/{context-ALSJMTHE.js → context-5LCUG2QR.js} +1 -1
  20. package/dist/{gcp-6FT2A45S.js → gcp-UG6AWPIZ.js} +1 -1
  21. package/dist/{generate-SPT7PJKR.js → generate-6E7J6BTM.js} +4 -3
  22. package/dist/{harden-BDVYW567.js → harden-URPXLSVF.js} +2 -2
  23. package/dist/{mcp-wire-ZWIYMLEW.js → mcp-wire-SLL4TLSC.js} +1 -1
  24. package/dist/{package-OMPI6RMV.js → package-QE7V2JAT.js} +3 -2
  25. package/dist/{pool-JZGKPP6K.js → pool-QGFQRMGU.js} +2 -2
  26. package/dist/{remote-config-QF5TT7GU.js → remote-config-PFB66RPY.js} +3 -1
  27. package/dist/{server-RGLKKCCU.js → server-L22AJQZO.js} +19 -18
  28. package/dist/{ssh-E2AMBPZY.js → ssh-CNJNLM3E.js} +1 -1
  29. package/dist/{validate-T5M5EHSJ.js → validate-CFQ4FH2T.js} +2 -1
  30. package/dist/version-guard-MZAO4KHS.js +25 -0
  31. package/dist/versions-OEPAS2EL.js +24 -0
  32. package/package.json +3 -2
  33. package/spec/_gen-schemas.md +136 -0
  34. package/spec/deploy-plan.schema.json +193 -0
  35. package/spec/errors.yaml +175 -0
  36. package/spec/integrations.yaml +97 -0
  37. package/spec/invariants.yaml +81 -0
  38. package/spec/mcp-tools.yaml +532 -0
  39. package/spec/models.yaml +113 -0
  40. package/spec/openclaw-versions.yaml +67 -0
  41. package/spec/providers.schema.json +120 -0
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ applyPlan
4
+ } from "./chunk-5SPESD5N.js";
5
+ import "./chunk-6ZFIFDBJ.js";
6
+ import "./chunk-BOPSG2LI.js";
2
7
  import {
3
8
  extractBaseOutputs
4
9
  } from "./chunk-3QJBNAHW.js";
5
10
  import {
6
11
  generatePlan
7
- } from "./chunk-FQ4JXUCR.js";
8
- import {
9
- applyPlan
10
- } from "./chunk-ISFHLA4G.js";
12
+ } from "./chunk-NESXDU5F.js";
11
13
  import {
12
14
  validatePlan
13
- } from "./chunk-YTH4L2GN.js";
14
- import "./chunk-6ZFIFDBJ.js";
15
- import "./chunk-BOPSG2LI.js";
15
+ } from "./chunk-6X45DDGH.js";
16
16
  import {
17
17
  errText,
18
18
  formatUptime,
@@ -23,16 +23,17 @@ import {
23
23
  handleConfigValidate,
24
24
  okText,
25
25
  resolveConn
26
- } from "./chunk-CG3Y7Y2R.js";
27
- import "./chunk-ZFNPM2WG.js";
28
- import {
29
- buildContext
30
- } from "./chunk-3MFZ7E74.js";
26
+ } from "./chunk-FSUWPL7Q.js";
31
27
  import {
32
28
  acquireSession,
33
29
  drainPool
34
- } from "./chunk-LCKD7L7X.js";
35
- import "./chunk-GJEF6UQA.js";
30
+ } from "./chunk-DQDAWNGB.js";
31
+ import "./chunk-O3F7OGH7.js";
32
+ import {
33
+ buildContext
34
+ } from "./chunk-P5LKWRPL.js";
35
+ import "./chunk-PVUVI35Y.js";
36
+ import "./chunk-3XK66DKK.js";
36
37
  import "./chunk-Q7NQY5HV.js";
37
38
  import "./chunk-A2I76FTA.js";
38
39
  import {
@@ -535,7 +536,7 @@ async function handleGatewayRestart(input, server) {
535
536
  const cmd = [
536
537
  "docker stop openclaw 2>/dev/null || true",
537
538
  "docker rm openclaw 2>/dev/null || true",
538
- `docker run -d --name openclaw --restart unless-stopped -p 18789:18789 ${image}`
539
+ `docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -e OPENCLAW_CONFIG_PATH=/app/config.json --add-host=host.docker.internal:host-gateway -v /home/clawops/openclaw.json:/app/config.json:ro ${image}`
539
540
  ].join(" && ");
540
541
  const result = await session.exec(cmd);
541
542
  if (result.code !== 0) {
@@ -631,7 +632,7 @@ async function handleUp(input, server) {
631
632
  );
632
633
  }
633
634
  const { localOpts } = stackConfig;
634
- const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
635
+ const { localBootstrap } = await import("./bootstrap-HL4DNUNG.js");
635
636
  const ac = new AbortController();
636
637
  const state = await localBootstrap({
637
638
  host: localOpts.host,
@@ -854,7 +855,7 @@ async function handleTaskStatus(input, _server) {
854
855
 
855
856
  // src/mcp/tools/cli/monitor.ts
856
857
  async function handleMonitor(input, _server) {
857
- const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-JZGKPP6K.js");
858
+ const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-QGFQRMGU.js");
858
859
  const ctx = buildContext({ stack: input.stackName });
859
860
  const tailLines = input.tailLines ?? 5;
860
861
  let conn;
@@ -1306,7 +1307,7 @@ If none of the above resolves the issue:
1306
1307
 
1307
1308
  // src/mcp/server.ts
1308
1309
  async function serveMcp(opts) {
1309
- const { version } = await import("./package-OMPI6RMV.js");
1310
+ const { version } = await import("./package-QE7V2JAT.js");
1310
1311
  const server = new McpServer({ name: "clawops", version });
1311
1312
  registerTools(server, opts);
1312
1313
  registerResources(server);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  connect
4
- } from "./chunk-GJEF6UQA.js";
4
+ } from "./chunk-3XK66DKK.js";
5
5
  import "./chunk-KGXPLI7W.js";
6
6
  export {
7
7
  connect
@@ -2,7 +2,8 @@
2
2
  import {
3
3
  assertValidPlan,
4
4
  validatePlan
5
- } from "./chunk-YTH4L2GN.js";
5
+ } from "./chunk-6X45DDGH.js";
6
+ import "./chunk-PVUVI35Y.js";
6
7
  export {
7
8
  assertValidPlan,
8
9
  validatePlan
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ assertSupportedVersion,
4
+ loadVersionSpec
5
+ } from "./chunk-2YOP6N7X.js";
6
+ import "./chunk-PVUVI35Y.js";
7
+ import {
8
+ UsageError
9
+ } from "./chunk-KGXPLI7W.js";
10
+
11
+ // src/cli/version-guard.ts
12
+ async function defaultOpenclawVersion() {
13
+ const yaml = await import("./js-yaml-PTEEG4FO.js");
14
+ return loadVersionSpec(yaml).support.recommended;
15
+ }
16
+ async function guardOpenclawVersion(version, resolver) {
17
+ const yaml = await import("./js-yaml-PTEEG4FO.js");
18
+ const result = await assertSupportedVersion(version, yaml, resolver);
19
+ if (result.ok) return result.value;
20
+ throw new UsageError(result.error.message);
21
+ }
22
+ export {
23
+ defaultOpenclawVersion,
24
+ guardOpenclawVersion
25
+ };
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ MOVING_TAGS,
4
+ _resetVersionSpecCache,
5
+ assertSupportedVersion,
6
+ checkVersion,
7
+ compareVersions,
8
+ describeRange,
9
+ isMovingTag,
10
+ loadVersionSpec,
11
+ resolveVersion
12
+ } from "./chunk-2YOP6N7X.js";
13
+ import "./chunk-PVUVI35Y.js";
14
+ export {
15
+ MOVING_TAGS,
16
+ _resetVersionSpecCache,
17
+ assertSupportedVersion,
18
+ checkVersion,
19
+ compareVersions,
20
+ describeRange,
21
+ isMovingTag,
22
+ loadVersionSpec,
23
+ resolveVersion
24
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawops/cli",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Deploy and manage self-hosted OpenClaw instances across clouds",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  ".": "./dist/index.js"
11
11
  },
12
12
  "files": [
13
- "dist"
13
+ "dist",
14
+ "spec"
14
15
  ],
15
16
  "repository": {
16
17
  "type": "git",
@@ -0,0 +1,136 @@
1
+ # Schema Code Generation — `pnpm gen:schemas`
2
+
3
+ This document specifies the contract for `scripts/gen-schemas.ts`, the codegen pipeline that emits TypeScript types and Zod schemas from the machine-readable specs in `spec/`.
4
+
5
+ ## Why This Exists
6
+
7
+ R-meta-1 declares schema files as ground truth. To make this enforceable rather than aspirational, generated TypeScript artifacts must mechanically derive from the schemas. CI verifies no drift via `pnpm gen:schemas --check`.
8
+
9
+ ## Inputs
10
+
11
+ | File | Format | Purpose |
12
+ |---|---|---|
13
+ | `spec/providers.schema.json` | JSON Schema | Drives `ProviderAdapter` interface |
14
+ | `spec/mcp-tools.yaml` | YAML | Drives MCP tool Zod schemas + tool registration |
15
+ | `spec/deploy-plan.schema.json` | JSON Schema | Drives `DeployPlan` type + ajv validator |
16
+ | `spec/errors.yaml` | YAML | Drives error class hierarchy + taxonomy IDs |
17
+ | `spec/openclaw-versions.yaml` | YAML | Drives version compatibility check |
18
+ | `spec/invariants.yaml` | YAML | Drives invariants test runner |
19
+
20
+ ## Outputs
21
+
22
+ | File | Source | Purpose |
23
+ |---|---|---|
24
+ | `src/providers/types.ts` | `providers.schema.json` | `ProviderAdapter` TS interface |
25
+ | `src/providers/_schema.ts` | `providers.schema.json` | Embedded JSON Schema for runtime ajv |
26
+ | `src/mcp/tools/_generated.ts` | `mcp-tools.yaml` | Zod schemas for every tool's input/output, tool registration helper |
27
+ | `src/plan/_schema.ts` | `deploy-plan.schema.json` | Embedded JSON Schema for `apply` validation |
28
+ | `src/plan/types.ts` | `deploy-plan.schema.json` | TS types for `DeployPlan` |
29
+ | `src/errors/_generated.ts` | `errors.yaml` | Error class hierarchy, taxonomy IDs as enums |
30
+ | `src/openclaw/versions.ts` | `openclaw-versions.yaml` | Version constants and quirks lookup |
31
+
32
+ All generated files MUST start with a banner comment:
33
+
34
+ ```typescript
35
+ // AUTO-GENERATED by scripts/gen-schemas.ts. DO NOT EDIT.
36
+ // Source: spec/<filename>
37
+ // Run `pnpm gen:schemas` to regenerate.
38
+ ```
39
+
40
+ ## Behavior
41
+
42
+ ### `pnpm gen:schemas`
43
+
44
+ 1. Read all input files
45
+ 2. Parse and validate each against its meta-schema (JSON Schema validates JSON Schema; YAML files validate against `spec/_meta/*.schema.json`)
46
+ 3. For each output file:
47
+ a. Generate the new content
48
+ b. Compare to existing file (if present)
49
+ c. Write if different; preserve mtime if identical
50
+ 4. Format output via `prettier --config .prettierrc <files>`
51
+ 5. Exit 0 on success; non-zero on any validation failure
52
+
53
+ ### `pnpm gen:schemas --check`
54
+
55
+ Same as above, but step 3c becomes:
56
+ - If existing file differs from new content: print diff + exit 1
57
+ - If files match: exit 0
58
+
59
+ This is the CI mode — fails the build if generated files are stale.
60
+
61
+ ## Tooling
62
+
63
+ - **JSON Schema → TypeScript:** `json-schema-to-typescript`
64
+ - **JSON Schema → Zod:** `json-schema-to-zod`
65
+ - **YAML parsing:** `yaml` package
66
+ - **Diff display:** `diff` package + colorized output
67
+ - **Formatting:** `prettier` (programmatic API)
68
+
69
+ ## Validation Rules
70
+
71
+ The generator MUST enforce:
72
+
73
+ 1. **Provider schema:**
74
+ - Every provider name in the enum must have an implementation under `src/providers/<name>/` (warning if missing; not error, to allow scaffolding)
75
+ - Every required field has a `description`
76
+
77
+ 2. **MCP tools:**
78
+ - All tool names start with `clawops_` (R1, I5)
79
+ - Total tool count ≤ 30 (R1, I4)
80
+ - Every tool has all four annotation hints set explicitly (R10, I3)
81
+ - Every description contains "Do NOT use" substring (R3, I6)
82
+ - Every tool is in at least one toolset
83
+
84
+ 3. **Deploy plan schema:**
85
+ - `apiVersion` is a const literal (semantic versioning safety)
86
+ - `secrets[]` items only allow `ref`, never `value` (R6 enforcement)
87
+
88
+ 4. **Errors:**
89
+ - Every taxonomy ID maps to exactly one class
90
+ - Class IDs in the taxonomy must exist in the `classes` list
91
+
92
+ If any validation fails, the generator exits non-zero with a clear error message before writing anything.
93
+
94
+ ## Running in CI
95
+
96
+ In `.github/workflows/ci.yml`:
97
+
98
+ ```yaml
99
+ - name: Verify generated files are up-to-date
100
+ run: pnpm gen:schemas --check
101
+ ```
102
+
103
+ This runs BEFORE typecheck so failures surface clearly.
104
+
105
+ ## Editor Integration
106
+
107
+ For local dev, recommend adding a watcher (in CONTRIBUTING.md):
108
+
109
+ ```bash
110
+ # Watch spec/ and regenerate on change
111
+ pnpm exec chokidar 'spec/**/*' -c 'pnpm gen:schemas'
112
+ ```
113
+
114
+ ## Failure Modes and Recovery
115
+
116
+ | Symptom | Likely Cause | Fix |
117
+ |---|---|---|
118
+ | `gen:schemas --check` fails after spec edit | Forgot to commit generated files | Run `pnpm gen:schemas`, commit |
119
+ | Generator throws "validation failed" | Spec violates meta-schema | Fix the spec to match meta-schema |
120
+ | Generated TS doesn't typecheck | Generator template bug | File issue; revert to last working commit |
121
+ | Tool count exceeds 30 | New MCP tool tipped over R1 | Move a tool to a different toolset, deprecate, or merge |
122
+ | Tool missing "Do NOT use" | Description doesn't include negative guidance | Update spec entry; R3 violation |
123
+
124
+ ## Versioning the Generator Itself
125
+
126
+ The generator's logic is part of the project's interface contract. Major changes to its output format MUST be accompanied by:
127
+
128
+ 1. An ADR documenting the format change
129
+ 2. A migration script if downstream code is affected
130
+ 3. A CHANGELOG entry
131
+
132
+ ## Future Extensions (Not in v1)
133
+
134
+ - Generate OpenAPI spec for the standalone HTTP MCP server from `spec/mcp-tools.yaml`
135
+ - Generate Markdown docs for each provider/tool/error from the specs
136
+ - Generate JSON Schema for `~/.clawops/config.json` from `spec/config.schema.json` (not yet authored)
@@ -0,0 +1,193 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clawops.dev/schemas/deploy-plan.json",
4
+ "title": "DeployPlan",
5
+ "description": "The Maker plan artifact (borrowed from Clanker pattern). Generated by `clawops plan`, applied by `clawops apply`. Reviewable, diff-able, version-controllable.",
6
+ "type": "object",
7
+ "required": ["apiVersion", "kind", "metadata", "spec"],
8
+ "properties": {
9
+ "apiVersion": {
10
+ "const": "clawops.dev/v1",
11
+ "description": "Schema version pinning"
12
+ },
13
+ "kind": {
14
+ "const": "DeployPlan"
15
+ },
16
+ "metadata": {
17
+ "type": "object",
18
+ "required": ["name", "generatedAt"],
19
+ "properties": {
20
+ "name": {
21
+ "type": "string",
22
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
23
+ "description": "Stack name"
24
+ },
25
+ "generatedAt": {
26
+ "type": "string",
27
+ "format": "date-time",
28
+ "description": "ISO-8601 timestamp"
29
+ },
30
+ "generator": {
31
+ "type": "string",
32
+ "default": "clawops",
33
+ "description": "Tool that produced this plan; agents can identify themselves here"
34
+ },
35
+ "generatorVersion": {
36
+ "type": "string",
37
+ "description": "semver of generator"
38
+ },
39
+ "labels": {
40
+ "type": "object",
41
+ "additionalProperties": { "type": "string" },
42
+ "description": "User-supplied labels (env=prod, team=platform, etc.)"
43
+ },
44
+ "stackVersion": {
45
+ "type": "integer",
46
+ "description": "Pulumi stack version at plan generation time (from UpdateSummary.version). Compared at apply time to detect drift. Absent for new stacks with no history."
47
+ }
48
+ }
49
+ },
50
+ "spec": {
51
+ "type": "object",
52
+ "required": ["provider", "stackName", "instanceType", "openclaw", "network"],
53
+ "properties": {
54
+ "provider": {
55
+ "enum": ["aws", "gcp", "azure", "local"]
56
+ },
57
+ "region": {
58
+ "type": "string",
59
+ "description": "Cloud region. Required for non-local providers"
60
+ },
61
+ "stackName": {
62
+ "type": "string",
63
+ "pattern": "^[a-z][a-z0-9-]{0,62}$"
64
+ },
65
+ "instanceType": {
66
+ "type": "string",
67
+ "description": "Provider-native instance type. Adapter normalizes from clawops alias before plan emission"
68
+ },
69
+ "openclaw": {
70
+ "type": "object",
71
+ "required": ["version"],
72
+ "properties": {
73
+ "version": {
74
+ "type": "string",
75
+ "description": "semver or 'stable'/'dev'"
76
+ },
77
+ "config": {
78
+ "type": "object",
79
+ "description": "Overrides applied on top of default openclaw.json. Secrets must use $secret references, never inline values"
80
+ },
81
+ "channels": {
82
+ "type": "object",
83
+ "description": "OpenClaw channel integrations keyed by provider name (e.g. {\"discord\":{\"botToken\":\"...\"}}). Values are provider-specific config objects. Sensitive fields must use $secret references.",
84
+ "additionalProperties": { "type": "object" }
85
+ }
86
+ }
87
+ },
88
+ "secrets": {
89
+ "type": "array",
90
+ "description": "Secret references (R6: never inline values)",
91
+ "items": {
92
+ "type": "object",
93
+ "required": ["name", "source"],
94
+ "properties": {
95
+ "name": { "type": "string" },
96
+ "source": {
97
+ "enum": ["env", "aws-sm", "aws-ssm", "gcp-sm", "azure-kv", "file"]
98
+ },
99
+ "ref": {
100
+ "type": "string",
101
+ "description": "Source-specific reference (env var name, ARN, secret URI, file path)"
102
+ }
103
+ }
104
+ }
105
+ },
106
+ "network": {
107
+ "type": "object",
108
+ "required": ["allowedSshCidrs", "allowedGatewayCidrs"],
109
+ "properties": {
110
+ "allowedSshCidrs": {
111
+ "type": "array",
112
+ "items": { "type": "string", "format": "cidr" },
113
+ "minItems": 0,
114
+ "description": "Empty array = no SSH access (unusual but allowed). Defaults applied at plan generation, not in schema"
115
+ },
116
+ "allowedGatewayCidrs": {
117
+ "type": "array",
118
+ "items": { "type": "string", "format": "cidr" },
119
+ "description": "CIDRs allowed to reach the OpenClaw gateway port (default 18789)"
120
+ },
121
+ "tailscale": {
122
+ "type": "object",
123
+ "description": "Optional Tailscale sidecar (borrowed pattern from schmitthub)",
124
+ "properties": {
125
+ "enabled": { "type": "boolean" },
126
+ "authKeyRef": { "type": "string", "description": "Reference to a secret containing the Tailscale auth key" }
127
+ }
128
+ }
129
+ }
130
+ },
131
+ "ssh": {
132
+ "type": "object",
133
+ "properties": {
134
+ "publicKey": {
135
+ "type": "string",
136
+ "description": "Public key contents (safe to inline). Private key never in plan"
137
+ },
138
+ "user": { "type": "string", "default": "ubuntu" }
139
+ }
140
+ },
141
+ "tags": {
142
+ "type": "object",
143
+ "additionalProperties": { "type": "string" },
144
+ "description": "Cloud-resource tags propagated to all created resources"
145
+ }
146
+ }
147
+ },
148
+ "diff": {
149
+ "type": "object",
150
+ "description": "Optional resource diff populated by `clawops plan` for human review. Not used by `apply`",
151
+ "properties": {
152
+ "create": {
153
+ "type": "array",
154
+ "items": { "$ref": "#/$defs/ResourceRef" }
155
+ },
156
+ "update": {
157
+ "type": "array",
158
+ "items": {
159
+ "type": "object",
160
+ "required": ["resource", "before", "after"],
161
+ "properties": {
162
+ "resource": { "$ref": "#/$defs/ResourceRef" },
163
+ "before": {},
164
+ "after": {}
165
+ }
166
+ }
167
+ },
168
+ "delete": {
169
+ "type": "array",
170
+ "items": { "$ref": "#/$defs/ResourceRef" }
171
+ },
172
+ "totalChanges": { "type": "integer" }
173
+ }
174
+ }
175
+ },
176
+ "$defs": {
177
+ "ResourceRef": {
178
+ "type": "object",
179
+ "required": ["urn", "type"],
180
+ "properties": {
181
+ "urn": {
182
+ "type": "string",
183
+ "description": "Pulumi URN, e.g., urn:pulumi:prod::clawops::clawops:app:Gateway::main-gateway"
184
+ },
185
+ "type": {
186
+ "type": "string",
187
+ "description": "Pulumi resource type token"
188
+ },
189
+ "name": { "type": "string" }
190
+ }
191
+ }
192
+ }
193
+ }
@@ -0,0 +1,175 @@
1
+ # Error Taxonomy — machine-readable companion to ADR 0005.
2
+ # Used by `pnpm gen:schemas` to emit src/errors/_generated.ts.
3
+ # Update via PR; CI verifies generated file matches.
4
+
5
+ version: 1
6
+
7
+ # Top-level error classes; each maps to an exit code (ADR 0005).
8
+ classes:
9
+ - id: UsageError
10
+ exitCode: 2
11
+ description: User input is invalid; user must change input
12
+ retryable: false
13
+ userActionRequired: true
14
+
15
+ - id: AuthError
16
+ exitCode: 3
17
+ description: Credentials missing, invalid, or insufficient
18
+ retryable: false
19
+ userActionRequired: true
20
+
21
+ - id: StateError
22
+ exitCode: 4
23
+ description: clawops-managed state is corrupt or inconsistent
24
+ retryable: false
25
+ userActionRequired: true
26
+
27
+ - id: ProviderError
28
+ exitCode: 5
29
+ description: Cloud provider rejected the request (non-auth)
30
+ retryable: depends # per-taxon
31
+ userActionRequired: depends
32
+
33
+ - id: NetworkError
34
+ exitCode: 6
35
+ description: Network connectivity failure
36
+ retryable: true
37
+ userActionRequired: false
38
+
39
+ - id: OperationalError
40
+ exitCode: 1
41
+ description: Operation-time error during a valid operation
42
+ retryable: depends
43
+ userActionRequired: depends
44
+
45
+ - id: CancelledError
46
+ exitCode: 130
47
+ description: User-initiated cancellation
48
+ retryable: true
49
+ userActionRequired: false
50
+
51
+ # Specific taxonomy IDs that errors must use as their `errorClass` field.
52
+ # Every thrown ClawopsError MUST have one of these IDs.
53
+ taxonomy:
54
+ # Usage
55
+ - id: usage.invalid_flag
56
+ class: UsageError
57
+ suggestedAction: "Check the flag spelling and value with `clawops <command> --help`."
58
+ - id: usage.missing_arg
59
+ class: UsageError
60
+ suggestedAction: "Provide the missing argument; see `clawops <command> --help`."
61
+ - id: usage.invalid_path
62
+ class: UsageError
63
+ suggestedAction: "Provide an absolute path. Relative paths are not accepted (R7)."
64
+ - id: usage.invalid_plan
65
+ class: UsageError
66
+ suggestedAction: "Plan failed schema validation. Regenerate with `clawops plan`."
67
+
68
+ # Auth
69
+ - id: auth.no_credentials
70
+ class: AuthError
71
+ suggestedAction: "Run `clawops init` to configure credentials."
72
+ - id: auth.expired
73
+ class: AuthError
74
+ suggestedAction: "Re-authenticate with your cloud provider; for AWS run `aws sso login`."
75
+ - id: auth.insufficient_permissions
76
+ class: AuthError
77
+ suggestedAction: "The configured credentials lack required IAM permissions; see docs/providers/<name>.md."
78
+
79
+ # State
80
+ - id: state.lock_held
81
+ class: StateError
82
+ suggestedAction: "Another clawops operation may be in progress; wait or run `clawops stacks unlock <name>` if certain it's stale."
83
+ - id: state.signature_mismatch
84
+ class: StateError
85
+ suggestedAction: "The plan file has been modified since generation; regenerate with `clawops plan`."
86
+ - id: state.backend_unreachable
87
+ class: StateError
88
+ suggestedAction: "Cannot reach the state backend (e.g., S3 bucket); verify access and connectivity."
89
+ - id: state.corrupt
90
+ class: StateError
91
+ suggestedAction: "State file is corrupt; consider `clawops state recover` or contact support."
92
+
93
+ # Provider
94
+ - id: provider.quota_exceeded
95
+ class: ProviderError
96
+ retryable: true
97
+ suggestedAction: "Cloud quota exceeded; wait or request a quota increase from your provider."
98
+ - id: provider.region_unsupported
99
+ class: ProviderError
100
+ retryable: false
101
+ userActionRequired: true
102
+ suggestedAction: "Selected region does not support the requested resource; choose a different region."
103
+ - id: provider.api_rate_limited
104
+ class: ProviderError
105
+ retryable: true
106
+ suggestedAction: "Cloud API rate-limited; clawops will retry with backoff."
107
+ - id: provider.resource_not_found
108
+ class: ProviderError
109
+ retryable: false
110
+ suggestedAction: "Required cloud resource not found; check stack state with `clawops status`."
111
+ - id: provider.resource_exists
112
+ class: ProviderError
113
+ retryable: false
114
+ suggestedAction: "Resource with this name already exists; use `--stack` to deploy to a different name."
115
+
116
+ # Network
117
+ - id: network.timeout
118
+ class: NetworkError
119
+ suggestedAction: "Network timeout; check connectivity and retry."
120
+ - id: network.dns_failure
121
+ class: NetworkError
122
+ suggestedAction: "DNS resolution failed; check DNS configuration."
123
+ - id: network.tls_failure
124
+ class: NetworkError
125
+ retryable: false
126
+ userActionRequired: true
127
+ suggestedAction: "TLS handshake failed; check certificate validity and trust chain."
128
+
129
+ # Operational
130
+ - id: op.timeout
131
+ class: OperationalError
132
+ retryable: true
133
+ suggestedAction: "Operation timed out; retry. If persistent, increase timeout via --timeout flag."
134
+ - id: op.unexpected_state
135
+ class: OperationalError
136
+ retryable: false
137
+ suggestedAction: "Cloud resource in unexpected state; run `clawops refresh` then `clawops status`."
138
+ - id: op.openclaw_unhealthy
139
+ class: OperationalError
140
+ retryable: true
141
+ suggestedAction: "OpenClaw gateway not responding; check `clawops logs` for issues."
142
+ - id: op.ssh_connect_failed
143
+ class: OperationalError
144
+ retryable: true
145
+ suggestedAction: "SSH connection failed; check key path, host availability, and security group."
146
+
147
+ # Cancellation
148
+ - id: op.cancelled
149
+ class: CancelledError
150
+ suggestedAction: "Operation cancelled by user."
151
+
152
+ # Sensitive field patterns for redaction (R21).
153
+ # Used by both pino logger config and src/mcp/audit.ts.
154
+ redaction:
155
+ patterns:
156
+ - authorization
157
+ - "*.authorization"
158
+ - token
159
+ - "*.token"
160
+ - password
161
+ - "*.password"
162
+ - secret
163
+ - "*.secret"
164
+ - connectionString
165
+ - "*.connectionString"
166
+ - aws_access_key_id
167
+ - "*.aws_access_key_id"
168
+ - aws_secret_access_key
169
+ - "*.aws_secret_access_key"
170
+ - GOOGLE_APPLICATION_CREDENTIALS
171
+ - AZURE_CLIENT_SECRET
172
+ - HCLOUD_TOKEN
173
+ - DO_API_TOKEN
174
+ - CLOUDFLARE_API_TOKEN
175
+ censor: "***"