Skip to content

Commit 28e4358

Browse files
authored
fix(skill): address ClawHub security audit findings (#49) (#53)
* fix(skill): address ClawHub security audit findings (#49) Reframe the skill to lower excessive-agency risk while leaving the CLI surface unchanged. - Rename 'escape hatches' to 'direct SDK and HTTP access' across the skill and docs site; lead with safety disclaimers instead of presenting raw RPC as a routine path. - Add rule 0 ('ASK before persisting'); soften the card-default trigger so ambiguous prompts no longer auto-write. - Tighten SKILL.md description field (remove 'save/capture/write down/document' trigger phrases). - Add explicit agent-confirm warnings around single-ref deletes, dm create/send, action unschedule, MasterTag cascade-delete, document unarchive, card reparent, calendar blockTime/visibility, and recurring-instance deletion. - Wrap the credentials-clear rm -f block under an irreversible- consequence header; keep the literal commands in auth-and-setup.md only. - Expand the RBAC-disable one-liner to a full callout. - Split the cross-project migration recipe into 4 phases with a count-verification gate before delete. Refs #49 * fix(skill): address CodeRabbit review feedback - direct-sdk-access.md + direct-access.md: qualify 'Any URL' as 'Any path on the configured workspace API URL'; document that Authorization is always overwritten by the resolved token. - direct-sdk-access.md: revert 'huly ws space permissions' to the high-level command 'huly space permissions' (space permissions is not a raw RPC method). - cards.md: clarify that the raw-RPC reparenting recipe sets parent:null, i.e. moves the card to the target CardSpace root, and that true reparenting with a target parent is web-UI only. - cards.md: 100ms -> 100 ms. - tracker-projects.md: rewrite migration recipe into 6 phases (tx-audit snapshot, read-validate, capture pre-copy DEST count, dry-run first issue, real copy, verify DEST delta equals SOURCE_COUNT). Handle empty source as a zero-item no-op. - tracker-projects.md: correct duplicate-identifier guidance — exact _id refs return directly; buildIndex overwrites duplicates during findAll, so non-_id refs resolve to the LAST project returned. - SKILL.md: 'wants persisted' -> 'wants to save' in two locations. - SKILL.md: credentials reset now XDG/HULY_ENV_FILE-aware (deletes bootstrap.json and the dotenv file the CLI loaded). - SKILL.md: include bare 'dm send <dm-ref>' in the irreversible-op callout (same auto-create / no find-or-create behavior as --person). - auth-and-setup.md: same XDG/HULY_ENV_FILE-aware reset. * fix(skill): address second-round review feedback - SKILL.md: split the dm send callout. --person variants auto-create (no find-or-create); bare 'dm send <dm-ref>' sends into the existing DM at <dm-ref>. Different failure modes. - SKILL.md + auth-and-setup.md: dotenv loader is NOT XDG-aware (env.ts:23 uses $HOME/.config/huly/.env, not $XDG_CONFIG_HOME). Updated both reset descriptions and the reset script to use $HOME/.config/huly/.env for the dotenv fallback while keeping XDG_CONFIG_HOME for the cached credential files. Added the re-export HULY_URL/HULY_EMAIL/HULY_PASSWORD step before 'huly login --headless' since --headless reads ONLY env vars. - direct-sdk-access.md: 'any method' -> 'any supported method' (the CLI dispatches only GET/POST/PUT/PATCH/DELETE). - tracker-projects.md: migration recipe now - uses 'set -euo pipefail' - resolves the source project's actual space _id via 'huly project get' before the audit snapshot (raw ws does not resolve identifier -> _id) - adds an explicit 'read -r -p ... CONFIRM' gate between the dry run and the real copy, plus a second gate before delete. * fix(skill): address third-round review feedback on migration recipe - tracker-projects.md: orphan comment fragment on line 243 (from a previous draft's Phase 0 prose) is gone — the snapshot call now carries its own complete comment. - tracker-projects.md: phase numbering renumbered Phase 0 -> Phase 1, 2 -> 2, ..., 8 -> 9. No gaps.
1 parent c585bd7 commit 28e4358

16 files changed

Lines changed: 367 additions & 195 deletions

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ root and links here for anything beyond install + quickstart.
5353

5454
## Advanced
5555

56-
- [Escape hatches](advanced/escape-hatches.md)`huly api` and
56+
- [Direct SDK and HTTP access](advanced/direct-access.md)`huly api` and
5757
`huly ws` for raw RPCs
5858
- [CLI architecture](advanced/architecture.md) — source layout,
5959
connection flow, markup handling

docs/advanced/architecture.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ warning to stderr, and — if `HULY_MARKDOWN_FALLBACK_FAIL=1` is set
115115
prosemirror-JSON directly.
116116

117117
For rich-text round-trip features (mention nodes, embeds) that
118-
don't survive the JSON round-trip, use the raw escape hatch with a
118+
don't survive the JSON round-trip, use the raw direct SDK access with a
119119
direct transaction object. The `params` argument is a JSON array
120120
containing a single `TxCreateDoc` transaction object.
121121

@@ -150,7 +150,7 @@ huly ws tx '[{
150150
}]'
151151
```
152152

153-
See [Escape hatches — WebSocket (`huly ws`)](escape-hatches.md#websocket-huly-ws)
153+
See [Direct SDK and HTTP access — WebSocket (`huly ws`)](direct-access.md#websocket-huly-ws)
154154
for the full RPC contract. The `tx` RPC accepts every transaction
155155
type — `TxCreateDoc`, `TxUpdateDoc`, `TxRemoveDoc`, `TxMixin`,
156156
`TxApplyIf` — with the same JSON shape as the `core:class:*`

docs/advanced/direct-access.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
title: Direct SDK and HTTP access (advanced)
3+
description: When huly-cli doesn't have a flag for what you need — `huly api` and `huly ws` for raw, unvalidated passthroughs against your self-hosted Huly workspace. Advanced use only.
4+
---
5+
6+
# Direct SDK and HTTP access (advanced)
7+
8+
> **Advanced only.** Two commands bypass every CLI safety check — ref resolution, type checking, cascade awareness, error mapping, and (for destructive calls) confirmation prompts:
9+
>
10+
> - **`huly api`** — raw HTTP passthrough.
11+
> - **`huly ws`** — raw WebSocket RPC.
12+
>
13+
> Treat them like raw SQL. Most workflows do not need them. If you find yourself reaching for them often for a pattern the CLI should expose, file an issue — that's a missing-feature signal.
14+
15+
When a CLI command doesn't exist for what you need, or the flag you need isn't exposed, talk to the server directly. Both commands are pass-through — they don't filter or transform the response.
16+
17+
## Table of contents
18+
19+
- [HTTP (`huly api`)](#http-huly-api)
20+
- [WebSocket (`huly ws`)](#websocket-huly-ws)
21+
- [When to use direct SDK access](#when-to-use-direct-sdk-access)
22+
23+
---
24+
25+
## HTTP (`huly api`)
26+
27+
```bash
28+
huly api GET /api/v1/version
29+
huly api GET /config.json
30+
huly api POST /api/v1/something --body '{"key":"value"}'
31+
huly api GET /api/v1/things --query foo=bar --query baz=qux
32+
huly api GET /api/v1/things --header "Authorization: Bearer ..."
33+
```
34+
35+
Available methods: `GET | POST | PUT | PATCH | DELETE`. The path
36+
is appended to the workspace's API URL. The CLI does not validate the path, method, body, or any custom headers — anything you send goes straight to the server.
37+
38+
> **`Authorization` is not overridable.** The CLI always sets `Authorization: Bearer <resolved-token>` after merging your custom headers (`packages/cli/src/raw/api.ts:43-49`), so passing `--header "Authorization: Bearer …"` has no effect. All other custom headers pass through verbatim.
39+
40+
---
41+
42+
## WebSocket (`huly ws`)
43+
44+
The Huly RPC protocol uses WebSocket for the SDK connection, but the
45+
raw `huly ws` command is **text JSON only**. Use it for direct
46+
method calls without opening the SDK's binary transport:
47+
48+
```bash
49+
# findAll
50+
huly ws findAll '[{"_class":"tracker:class:Project"},{}]'
51+
52+
# tx (raw transaction)
53+
huly ws tx '[{"_class":"core:class:TxCreateDoc",...}]'
54+
```
55+
56+
> `huly ws` accepts a single positional `<method>` followed by an
57+
> optional `[params]` argument that is a **JSON-encoded array of
58+
> positional parameters** for that method. On Huly 0.7.x the raw
59+
> socket dispatches a small whitelist: `findAll`, `tx`, `hello`, and
60+
> `ping`. Do not rely on `findOne`, `createDoc`, `updateDoc`, or other
61+
> SDK methods through this command — use the high-level commands
62+
> for writes, or `tx` for raw transaction payloads.
63+
>
64+
> The `tx` RPC supports every transaction type — `TxCreateDoc`,
65+
> `TxUpdateDoc`, `TxRemoveDoc`, `TxMixin`, `TxApplyIf`. Build the
66+
> payload directly; the CLI doesn't validate. **Confirm with the user before invoking** — raw RPC has no CLI confirmation prompt and bypasses every safety check.
67+
68+
---
69+
70+
## When to use direct SDK access
71+
72+
- A command exists but doesn't expose the flag you need (rare). Use the high-level command with `--set key=value` first; reach for `huly ws` / `huly api` only when the field is not exposed at all.
73+
- A command exists but operates on a wrong sub-resource.
74+
- You're debugging and need to see the raw server response.
75+
- The CLI doesn't support the surface you need (use the SDK
76+
instead — see
77+
[Migration — from the SDK](../guides/migration.md#from-the-huly-sdk-typescript)).
78+
79+
The commands pass through directly; the CLI handles auth and
80+
caching, not transformation. If you find yourself reaching for
81+
`huly ws` often, that's a signal the CLI should expose that surface
82+
natively — file an issue.
83+
84+
**Do not use raw RPC to bypass `--yes`, validation, or duplicate-identifier checks.** Those refusals are intentional.

docs/advanced/escape-hatches.md

Lines changed: 0 additions & 78 deletions
This file was deleted.

docs/advanced/server-architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ For self-hosted single-pod deployments, use `WS_OPERATION=all+backup`.
151151
## The WebSocket protocol
152152

153153
The SDK connection speaks Huly's binary RPC protocol over WebSocket.
154-
The CLI's raw `huly ws` escape hatch is a separate **text-JSON**
154+
The CLI's raw `huly ws` direct SDK access is a separate **text-JSON**
155155
channel — the two are different transports to the transactor. Key
156156
methods on the binary SDK side:
157157

docs/guides/migration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ error formatting. Prefer the CLI for one-off scripts; prefer the SDK
136136
for long-running services.
137137

138138
If you need to call a method the CLI doesn't expose, see
139-
[Escape hatches](../advanced/escape-hatches.md) for `huly ws` (raw
139+
[Direct SDK and HTTP access](../advanced/direct-access.md) for `huly ws` (raw
140140
WebSocket RPC).
141141

142142
---
@@ -156,7 +156,7 @@ huly api GET /api/v1/version
156156
The CLI's `api` command passes through to the REST API but handles
157157
auth headers automatically. Use it for ad-hoc endpoints the CLI
158158
doesn't cover. See
159-
[Escape hatches — HTTP (`huly api`)](../advanced/escape-hatches.md#http-huly-api).
159+
[Direct SDK and HTTP access — HTTP (`huly api`)](../advanced/direct-access.md#http-huly-api).
160160

161161
---
162162

docs/reference/environment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ huly ws findAll '[{"_class":"core.class.Tx"},{"objectId":"<doc-id>","modifiedOn"
148148

149149
Each tx carries `modifiedBy`, `modifiedOn`, `space`, `objectId`,
150150
and the full operations payload. See
151-
[Escape hatches — WebSocket (`huly ws`)](../advanced/escape-hatches.md#websocket-huly-ws).
151+
[Direct SDK and HTTP access — WebSocket (`huly ws`)](../advanced/direct-access.md#websocket-huly-ws).
152152

153153
---
154154

docs/reference/model.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description: Huly class IDs and plugin-to-CLI mapping — the canonical referenc
77

88
Class IDs and plugin-to-CLI mapping. The CLI's canonical class IDs
99
live in `src/transport/identifiers.ts` — that's the reference for
10-
escape-hatch use ([`huly ws findAll ...`](../advanced/escape-hatches.md#websocket-huly-ws)).
10+
direct SDK access use ([`huly ws findAll ...`](../advanced/direct-access.md#websocket-huly-ws)).
1111

1212
## Table of contents
1313

@@ -21,7 +21,7 @@ escape-hatch use ([`huly ws findAll ...`](../advanced/escape-hatches.md#websocke
2121
## Class ID reference
2222

2323
The platform's class hierarchy. Used as `_class` in JSON, as class
24-
IDs in escape-hatch calls, and as class filters in queries.
24+
IDs in direct SDK access calls, and as class filters in queries.
2525

2626
| Plugin | Class ID pattern | Examples |
2727
| -------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------- |

0 commit comments

Comments
 (0)