tenuo-claude-code 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/.gitignore +1 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/PKG-INFO +116 -65
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/README.md +115 -64
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/README.md +42 -14
- tenuo_claude_code-0.2.2/demo/docs/README.md +21 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/docs/DETAILS.md +44 -17
- tenuo_claude_code-0.2.2/docs/TROUBLESHOOTING.md +221 -0
- tenuo_claude_code-0.2.2/docs/images/README.md +22 -0
- tenuo_claude_code-0.2.2/docs/images/tenuo_claude_code_architecture.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/pyproject.toml +1 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/__init__.py +1 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/admin.py +29 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/authorizer_runtime.py +13 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/cli.py +239 -56
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/README.md +2 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/tenuo.yaml.advanced.example +2 -2
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_admin.py +87 -0
- tenuo_claude_code-0.2.2/tests/test_check.py +74 -0
- tenuo_claude_code-0.2.2/tests/test_cloud_bindings.py +331 -0
- tenuo_claude_code-0.2.2/tests/test_scaffold.py +244 -0
- tenuo_claude_code-0.2.0/docs/images/README.md +0 -9
- tenuo_claude_code-0.2.0/tests/test_check.py +0 -31
- tenuo_claude_code-0.2.0/tests/test_scaffold.py +0 -133
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/CONTRIBUTING.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/LICENSE +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/.claude/agents/researcher.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/.mcp.json +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/fake-secrets.env +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/ops_server.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/sandbox/incident-report.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/sandbox/notes.txt +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/tenuo.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/demo/tenuo_demo.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/docs/images/cloud-audit-stream.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/docs/images/cloud-receipt-approval-detail.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/docs/images/tenuo_claude_code_architecture.svg +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/examples/policies/README.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/examples/policies/audit-rollout.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/examples/policies/enforce-with-mcp.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/examples/policies/read-only-research.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/data/harness_tools.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/paths.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/templates/tenuo.yaml.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/src/tenuo_claude_code/verify.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/admin.env.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/cloud.env.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/tenuo.yaml.cloud.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/templates/tenuo.yaml.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/conftest.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_approvals.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_authorize_call.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_authorizer_runtime.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_constraints.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_permissions.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_routing.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.2}/tests/test_subagents.py +0 -0
|
@@ -24,7 +24,7 @@ tenuo.advanced.yaml
|
|
|
24
24
|
demo/sandbox/out.txt
|
|
25
25
|
demo/sandbox/_probe.txt
|
|
26
26
|
|
|
27
|
-
# Local-only presentation notes (
|
|
27
|
+
# Local-only presentation notes (gitignored — keep your own copy; see demo/docs/README.md)
|
|
28
28
|
demo/docs/PRESENTATION.md
|
|
29
29
|
|
|
30
30
|
# OS / editor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tenuo-claude-code
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Tenuo governance for Claude Code — warrants, hooks, MCP proxy, and Cloud lifecycle
|
|
5
5
|
Project-URL: Homepage, https://tenuo.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/tenuo-ai/claude-governance
|
|
@@ -30,8 +30,6 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
|
|
31
31
|
# Tenuo for Claude Code
|
|
32
32
|
|
|
33
|
-
PyPI package: [`tenuo-claude-code`](https://pypi.org/project/tenuo-claude-code/) · CLI: `tenuo-claude`, `tenuo-admin`
|
|
34
|
-
|
|
35
33
|
[](https://pypi.org/project/tenuo-claude-code/)
|
|
36
34
|
[](https://pypi.org/project/tenuo-claude-code/)
|
|
37
35
|
[](https://github.com/tenuo-ai/claude-governance/actions/workflows/ci.yml)
|
|
@@ -53,9 +51,21 @@ mkdir my-project && cd my-project
|
|
|
53
51
|
tenuo-claude bootstrap
|
|
54
52
|
```
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
When `verify` passes, open Claude Code in this directory.
|
|
55
|
+
|
|
56
|
+
**Native authorizer (no Docker):**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
tenuo-claude install-authorizer
|
|
60
|
+
tenuo-claude bootstrap
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If Docker is not installed, `bootstrap` uses the native authorizer automatically. If Docker is installed and you want native anyway:
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
```bash
|
|
66
|
+
export TENUO_AUTHORIZER_BACKEND=native
|
|
67
|
+
tenuo-claude bootstrap
|
|
68
|
+
```
|
|
59
69
|
|
|
60
70
|
### Where to go next
|
|
61
71
|
|
|
@@ -63,15 +73,16 @@ No Docker, or prefer native? Run `tenuo-claude install-authorizer` once, then `b
|
|
|
63
73
|
|-----------------|------------|
|
|
64
74
|
| Day-to-day commands, ports, CLI reference | [Use the tool](#use-the-tool-pypi) |
|
|
65
75
|
| Edit or replace the example policy | [Policy](#policy-tenuoyaml) |
|
|
66
|
-
| Clone
|
|
76
|
+
| Clone the repo or run the sample project | [Build from source](#build-from-source) |
|
|
67
77
|
| Connect to Tenuo Cloud | [Cloud mode](#cloud-mode) |
|
|
68
78
|
| Review security posture | [Security](#security) |
|
|
69
79
|
| Plan org-wide rollout | [Talk to us](https://tenuo.ai/early-access.html) |
|
|
80
|
+
| Something failed during setup | [Troubleshooting (Q&A)](docs/TROUBLESHOOTING.md) |
|
|
70
81
|
| Implementation depth | [docs/DETAILS.md](docs/DETAILS.md) |
|
|
71
82
|
|
|
72
83
|
## How it works
|
|
73
84
|
|
|
74
|
-

|
|
75
86
|
|
|
76
87
|
```
|
|
77
88
|
tenuo.yaml → init/up → warrant + authorizer + hooks + MCP proxy
|
|
@@ -87,41 +98,42 @@ tenuo.yaml → init/up → warrant + authorizer + hooks + MCP proxy
|
|
|
87
98
|
|
|
88
99
|
**Native tools** (Read, Bash, WebFetch, and the rest) go through a PreToolUse hook. **MCP tools** go through a proxy in place of the downstream server. At `init`, Tenuo mints a **session warrant**; each call must prove it holds that warrant before the authorizer allows the action.
|
|
89
100
|
|
|
90
|
-
Both paths use the same warrant and authorizer.
|
|
91
|
-
|
|
92
101
|
More: [docs/DETAILS.md](docs/DETAILS.md)
|
|
93
102
|
|
|
94
103
|
## Prerequisites
|
|
95
104
|
|
|
96
105
|
- Python ≥ 3.10
|
|
97
|
-
- **Authorizer runtime** (
|
|
98
|
-
- **Docker
|
|
99
|
-
- **Native (no Docker)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
- [Claude Code](https://code.claude.com/docs) for live agent use. Optional: `verify` works without it.
|
|
106
|
+
- **Authorizer runtime** (use one):
|
|
107
|
+
- **Docker** (default when the daemon is running): [Docker Desktop](https://www.docker.com/products/docker-desktop/) or your engine, then `tenuo-claude up`. Uses the pinned `tenuo/authorizer` image.
|
|
108
|
+
- **Native** (no Docker): run `tenuo-claude install-authorizer`, then `tenuo-claude up --native`. On first run, add `--install`. Override the binary with `TENUO_AUTHORIZER_BIN`. Set `TENUO_AUTHORIZER_SKIP_VERSION=1` only for local dev builds.
|
|
109
|
+
- To force native while Docker is installed, set `TENUO_AUTHORIZER_BACKEND=native` before `bootstrap` or `up`.
|
|
110
|
+
- [Claude Code](https://code.claude.com/docs) — Tenuo wires PreToolUse hooks and MCP proxy at `init`.
|
|
103
111
|
|
|
104
|
-
**Local mode:** no Tenuo Cloud account.
|
|
112
|
+
**Local mode:** no Tenuo Cloud account. Suitable for single-project evaluation.
|
|
105
113
|
|
|
106
|
-
**Cloud mode:** [cloud.tenuo.ai](https://cloud.tenuo.ai) tenant for tenant-root warrants, central audit, fleet revocation, and org-wide rollout ([Cloud mode](#cloud-mode)).
|
|
114
|
+
**Cloud mode:** requires a [cloud.tenuo.ai](https://cloud.tenuo.ai) tenant for tenant-root warrants, central audit, fleet revocation, and org-wide rollout ([Cloud mode](#cloud-mode)).
|
|
107
115
|
|
|
108
116
|
---
|
|
109
117
|
|
|
110
118
|
## Use the tool (PyPI)
|
|
111
119
|
|
|
112
|
-
After [Try it](#try-it), you have an example `tenuo.yaml`, a running authorizer, and passing `verify`.
|
|
120
|
+
After [Try it](#try-it), you have an example `tenuo.yaml`, a running authorizer, and passing `verify`.
|
|
113
121
|
|
|
114
122
|
### Day to day
|
|
115
123
|
|
|
116
124
|
| When | Command |
|
|
117
125
|
|------|---------|
|
|
118
|
-
| Start work | `tenuo-claude
|
|
119
|
-
|
|
|
120
|
-
|
|
|
126
|
+
| Start work (Cloud) | `tenuo-claude check && tenuo-claude up` |
|
|
127
|
+
| Start work (local only) | `tenuo-claude up` or `tenuo-claude up --native` |
|
|
128
|
+
| `check` reports cloud bindings failure | `tenuo-admin setup`, then `check && up` again |
|
|
129
|
+
| You edited `tenuo.yaml` | `tenuo-claude refresh` (local); Cloud capability changes also need `tenuo-admin setup` |
|
|
130
|
+
| Diagnose setup | `tenuo-claude check` |
|
|
121
131
|
| See decisions | `tenuo-claude audit` |
|
|
122
132
|
| Stop authorizer | `tenuo-claude down` |
|
|
123
133
|
|
|
124
|
-
|
|
134
|
+
See [Troubleshooting (Q&A)](docs/TROUBLESHOOTING.md) for common errors.
|
|
135
|
+
|
|
136
|
+
If you always use the native authorizer without Docker, set `TENUO_AUTHORIZER_BACKEND=native` in your shell so plain `up` selects the host binary.
|
|
125
137
|
|
|
126
138
|
### Port conflicts
|
|
127
139
|
|
|
@@ -148,13 +160,15 @@ tenuo-claude up
|
|
|
148
160
|
tenuo-claude verify
|
|
149
161
|
```
|
|
150
162
|
|
|
151
|
-
Use `--native` when not
|
|
163
|
+
Use `--native` when Docker is not available. On the first native run, add `--install`. Alternatively, run `tenuo-claude onboard --local` for an interactive setup.
|
|
152
164
|
|
|
153
165
|
### Reference demo
|
|
154
166
|
|
|
155
167
|
Sample policy, MCP stub, and scripted tour in [demo/](demo/). The shipped `demo/tenuo.yaml` is richer than the bootstrap example; Cloud and approval overlays may already be present.
|
|
156
168
|
|
|
157
|
-
|
|
169
|
+
From repo root: `uv venv && uv sync && source .venv/bin/activate`, then:
|
|
170
|
+
|
|
171
|
+
**First time, local only** (no `.state/cloud.env`):
|
|
158
172
|
|
|
159
173
|
```bash
|
|
160
174
|
cd demo
|
|
@@ -162,18 +176,37 @@ tenuo-claude bootstrap
|
|
|
162
176
|
tenuo-claude demo
|
|
163
177
|
```
|
|
164
178
|
|
|
165
|
-
**
|
|
179
|
+
**First time, Cloud** (recommended for the reference demo with receipts):
|
|
166
180
|
|
|
167
181
|
```bash
|
|
168
182
|
cd demo
|
|
169
|
-
tenuo-claude
|
|
183
|
+
tenuo-claude bootstrap --cloud
|
|
184
|
+
# or: tenuo-claude onboard --cloud
|
|
185
|
+
tenuo-claude demo
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Paste Quick Connect (**Authorizer Only**) into `.state/cloud.env` and tenant-admin
|
|
189
|
+
key into `~/.tenuo/admin.env` when prompted. See [Cloud mode](#cloud-mode).
|
|
190
|
+
|
|
191
|
+
**Already Cloud-configured** (`.state/cloud.env` or `tenuo.cloud.yaml` present):
|
|
192
|
+
|
|
193
|
+
Do **not** run plain `bootstrap` — it switches to local mode and moves Cloud files
|
|
194
|
+
aside. Use:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
cd demo
|
|
198
|
+
tenuo-claude check && tenuo-claude up
|
|
170
199
|
tenuo-claude verify
|
|
171
200
|
tenuo-claude demo
|
|
172
201
|
```
|
|
173
202
|
|
|
203
|
+
If `check` fails on **cloud bindings** → `tenuo-admin setup`, then retry.
|
|
204
|
+
|
|
174
205
|
For human approval: [Cloud mode § Human approval](#human-approval-cloud), then `tenuo-claude demo --advanced --live-approval`.
|
|
175
206
|
|
|
176
|
-
If
|
|
207
|
+
If plain `bootstrap` was run on a Cloud-configured project, restore `.state/cloud.env`
|
|
208
|
+
and policy overlays from backup, then `tenuo-admin setup`. See
|
|
209
|
+
[Troubleshooting](docs/TROUBLESHOOTING.md).
|
|
177
210
|
|
|
178
211
|
From a git checkout, see [Build from source](#build-from-source).
|
|
179
212
|
|
|
@@ -186,21 +219,21 @@ From a git checkout, see [Build from source](#build-from-source).
|
|
|
186
219
|
| `up` / `down` | Start / stop authorizer. `up` flags: `--native`, `--docker`, `--install` (native, first run) |
|
|
187
220
|
| `install-authorizer` | Install `tenuo-authorizer` to `~/.tenuo/bin` (no manual `cargo`) |
|
|
188
221
|
| `refresh` | Re-apply `tenuo.yaml` (restarts authorizer if up) |
|
|
189
|
-
| `check` | Preflight: deps, credentials, wiring drift |
|
|
190
|
-
| `verify [--deep]` | Policy self-test against the authorizer |
|
|
222
|
+
| `check` | Preflight: deps, credentials, wiring drift, Cloud binding probe |
|
|
223
|
+
| `verify [--deep]` | Policy self-test against the authorizer (no agent session required) |
|
|
191
224
|
| `status` | Warrant, posture, Cloud summary |
|
|
192
225
|
| `onboard` | Interactive local or Cloud setup wizard |
|
|
193
226
|
| `bench [--json]` | Per-tool-call overhead |
|
|
194
227
|
| `audit [--tail N]` | Receipt trail |
|
|
195
228
|
| `revoke` | Revoke session warrant |
|
|
196
229
|
|
|
197
|
-
See also: [Policy](#policy-tenuoyaml) · [Cloud mode](#cloud-mode) · [docs/DETAILS.md](docs/DETAILS.md)
|
|
230
|
+
See also: [Policy](#policy-tenuoyaml) · [Cloud mode](#cloud-mode) · [Troubleshooting](docs/TROUBLESHOOTING.md) · [docs/DETAILS.md](docs/DETAILS.md)
|
|
198
231
|
|
|
199
232
|
---
|
|
200
233
|
|
|
201
234
|
## Build from source
|
|
202
235
|
|
|
203
|
-
For
|
|
236
|
+
For local development, the reference demo from git, or `./bin/tenuo-claude` instead of a PyPI install.
|
|
204
237
|
|
|
205
238
|
```bash
|
|
206
239
|
git clone https://github.com/tenuo-ai/claude-governance.git
|
|
@@ -224,13 +257,14 @@ Run commands via the repo launcher or editable install:
|
|
|
224
257
|
|
|
225
258
|
```bash
|
|
226
259
|
cd demo
|
|
227
|
-
tenuo-claude up
|
|
260
|
+
tenuo-claude check && tenuo-claude up # Cloud; see Reference demo if check fails
|
|
228
261
|
tenuo-claude demo
|
|
229
262
|
```
|
|
230
263
|
|
|
231
|
-
First local-only run: `tenuo-claude bootstrap` instead
|
|
264
|
+
First local-only run (no `.state/cloud.env`): use `tenuo-claude bootstrap` instead.
|
|
265
|
+
First Cloud run: `tenuo-claude bootstrap --cloud` or `onboard --cloud`.
|
|
232
266
|
|
|
233
|
-
Use `tenuo-claude up --native`
|
|
267
|
+
Use `tenuo-claude up --native` when Docker is not available.
|
|
234
268
|
|
|
235
269
|
Open Claude Code in `demo/`. See [demo/README.md](demo/README.md) and [Reference demo](#reference-demo) above.
|
|
236
270
|
|
|
@@ -294,8 +328,6 @@ Use Cloud when you need organization-scale governance, not just a single laptop:
|
|
|
294
328
|
every tool call at the hook and MCP proxy. Engineers cannot disable it with local
|
|
295
329
|
Claude permission edits or `--dangerously-skip-permissions`
|
|
296
330
|
|
|
297
|
-
Local mode (no Cloud account) remains fully supported for evaluation and single-project use.
|
|
298
|
-
|
|
299
331
|
### Cloud quickstart
|
|
300
332
|
|
|
301
333
|
Two keys, two files. Runtime never sees the admin key:
|
|
@@ -307,9 +339,7 @@ Two keys, two files. Runtime never sees the admin key:
|
|
|
307
339
|
|
|
308
340
|
**Do not** put the tenant-admin key in `.state/cloud.env` or your shell when running `tenuo-claude up`. Runtime refuses to start if an admin key is reachable.
|
|
309
341
|
|
|
310
|
-
**Fresh project**
|
|
311
|
-
|
|
312
|
-
Creates an example `tenuo.yaml` if none exists.
|
|
342
|
+
**Fresh project** (creates `tenuo.yaml` if none exists):
|
|
313
343
|
|
|
314
344
|
```bash
|
|
315
345
|
pip install tenuo-claude-code
|
|
@@ -317,9 +347,7 @@ mkdir my-project && cd my-project
|
|
|
317
347
|
tenuo-claude bootstrap --cloud
|
|
318
348
|
```
|
|
319
349
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
Prompts for credentials, then runs `init`, `tenuo-admin setup`, `up`, and `verify`. Pass a tenant-admin key to run setup in the same step.
|
|
350
|
+
The wizard prompts for a Quick Connect token (`tenuo_ct_…`), then runs `init`, `tenuo-admin setup`, `up`, and `verify`. For an explicit Cloud URL and API key without Quick Connect, use the manual setup block below.
|
|
323
351
|
|
|
324
352
|
Non-interactive:
|
|
325
353
|
|
|
@@ -329,7 +357,7 @@ tenuo-claude bootstrap --cloud --yes \
|
|
|
329
357
|
--admin-key "tc_…"
|
|
330
358
|
```
|
|
331
359
|
|
|
332
|
-
Omit `--admin-key` if `tenuo-admin setup` already ran.
|
|
360
|
+
Omit `--admin-key` if `tenuo-admin setup` already ran. Pass credentials with flags rather than `export TENUO_ADMIN_KEY`. Unset the admin key before `tenuo-claude up`; an admin key in the runtime environment causes startup to fail.
|
|
333
361
|
|
|
334
362
|
One-shot env vars for CI:
|
|
335
363
|
|
|
@@ -347,9 +375,9 @@ cd my-project
|
|
|
347
375
|
tenuo-claude onboard --cloud
|
|
348
376
|
```
|
|
349
377
|
|
|
350
|
-
|
|
378
|
+
If you do not pass an admin key to the wizard, run `tenuo-admin setup` before `up`, or place the admin key in `~/.tenuo/admin.env` and run setup yourself.
|
|
351
379
|
|
|
352
|
-
Manual equivalent. Credential templates in [templates/](templates/):
|
|
380
|
+
**Manual setup** (equivalent to the wizard). Credential templates are in [templates/](templates/):
|
|
353
381
|
|
|
354
382
|
```bash
|
|
355
383
|
cd my-project
|
|
@@ -359,13 +387,21 @@ mkdir -p .state ~/.tenuo
|
|
|
359
387
|
|
|
360
388
|
tenuo-claude init --cloud
|
|
361
389
|
tenuo-admin setup
|
|
362
|
-
tenuo-claude up
|
|
390
|
+
tenuo-claude check && tenuo-claude up
|
|
363
391
|
tenuo-claude verify
|
|
364
392
|
```
|
|
365
393
|
|
|
366
|
-
|
|
394
|
+
**Every session** (after onboarding):
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
tenuo-claude check && tenuo-claude up
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
If `check` reports **cloud bindings** failure, run `tenuo-admin setup` and retry.
|
|
367
401
|
|
|
368
|
-
|
|
402
|
+
### Verify onboarding
|
|
403
|
+
|
|
404
|
+
After onboarding, run:
|
|
369
405
|
|
|
370
406
|
```bash
|
|
371
407
|
tenuo-claude status
|
|
@@ -373,11 +409,14 @@ tenuo-claude check
|
|
|
373
409
|
tenuo-admin show
|
|
374
410
|
```
|
|
375
411
|
|
|
376
|
-
You should see: authorizer up, cloud profile merged, a trigger id in `tenuo-admin show`, and CHECK OK with no admin key in runtime env.
|
|
412
|
+
You should see: authorizer up, cloud profile merged, a trigger id in `tenuo-admin show`, **cloud bindings — trigger fire dry-run OK**, and CHECK OK with no admin key in runtime env.
|
|
377
413
|
|
|
378
414
|
Re-run `tenuo-admin setup` when Cloud capabilities change — setup syncs the local
|
|
379
|
-
gateway and reloads the authorizer when
|
|
380
|
-
`tenuo-claude refresh` for local-only policy edits (no
|
|
415
|
+
gateway, reconciles agent/trigger/holder bindings, and reloads the authorizer when
|
|
416
|
+
it is already running. Re-run `tenuo-claude refresh` for local-only policy edits (no
|
|
417
|
+
Cloud trigger change).
|
|
418
|
+
|
|
419
|
+
Stuck? [Troubleshooting (Q&A)](docs/TROUBLESHOOTING.md).
|
|
381
420
|
|
|
382
421
|
### Human approval (Cloud)
|
|
383
422
|
|
|
@@ -394,8 +433,8 @@ Both use the same session approval policy and the same hook/proxy approval workf
|
|
|
394
433
|
|
|
395
434
|
1. Configure a notification channel and identity binding in Cloud ([channels](https://docs.tenuo.ai/guides/adding-channels),
|
|
396
435
|
[identity bindings](https://docs.tenuo.ai/integrations/identity-bindings)).
|
|
397
|
-
2. Add approval gates in policy.
|
|
398
|
-
configs
|
|
436
|
+
2. Add approval gates in policy. Use `cloud.approver_identity_id` for team and
|
|
437
|
+
shared configs. Use `cloud.approver_identity` (display name) for demos only.
|
|
399
438
|
See [templates/tenuo.yaml.advanced.example](templates/tenuo.yaml.advanced.example).
|
|
400
439
|
3. Wire Cloud and re-run setup:
|
|
401
440
|
|
|
@@ -406,14 +445,14 @@ tenuo-claude up # if authorizer was down
|
|
|
406
445
|
tenuo-claude verify
|
|
407
446
|
```
|
|
408
447
|
|
|
409
|
-
For
|
|
448
|
+
For demos, display-name lookup is supported:
|
|
410
449
|
|
|
411
450
|
```bash
|
|
412
451
|
tenuo-claude onboard --cloud --advanced --approver "Alice Example"
|
|
413
452
|
```
|
|
414
453
|
|
|
415
|
-
If multiple Cloud identities share a display name,
|
|
416
|
-
|
|
454
|
+
If multiple Cloud identities share a display name, use `--approver-id` or
|
|
455
|
+
`cloud.approver_identity_id` in policy.
|
|
417
456
|
|
|
418
457
|
Reference demo:
|
|
419
458
|
|
|
@@ -432,9 +471,7 @@ Details: [docs/DETAILS.md § Human approval](docs/DETAILS.md#human-approval-clou
|
|
|
432
471
|
|
|
433
472
|
## Security
|
|
434
473
|
|
|
435
|
-
Tenuo works **alongside** Claude Code permissions
|
|
436
|
-
|
|
437
|
-
You still deploy hooks. Tenuo adds a signed session warrant, a local authorizer on every tool call, and a decision log per call. Policy is one file (`tenuo.yaml`).
|
|
474
|
+
Tenuo works **alongside** Claude Code permissions — it does not replace managed settings. `tenuo-claude init` wires a PreToolUse hook and MCP proxy; the authorizer enforces the session warrant on every tool call and logs a receipt. Policy is one file (`tenuo.yaml`).
|
|
438
475
|
|
|
439
476
|
### vs. Claude Code permissions
|
|
440
477
|
|
|
@@ -448,7 +485,7 @@ You still deploy hooks. Tenuo adds a signed session warrant, a local authorizer
|
|
|
448
485
|
| Org-wide deployment | Per-user settings; users can edit local hooks | Managed settings + shared policy; hook/proxy enforcement is not user-editable |
|
|
449
486
|
| `--dangerously-skip-permissions` | Bypasses Claude permission prompts | Hook and MCP proxy still enforce the warrant |
|
|
450
487
|
|
|
451
|
-
|
|
488
|
+
`--dangerously-skip-permissions` skips Claude's permission UI, not the warrant.
|
|
452
489
|
|
|
453
490
|
Org admins can block it in managed settings (`disableBypassPermissionsMode`).
|
|
454
491
|
|
|
@@ -465,7 +502,7 @@ For teams that need a **global configuration engineers cannot bypass**:
|
|
|
465
502
|
|
|
466
503
|
### Receipts
|
|
467
504
|
|
|
468
|
-
Every governed tool call
|
|
505
|
+
Every governed tool call carries a proof-of-possession signature; the authorizer verifies it before returning allow/deny.
|
|
469
506
|
|
|
470
507
|
What you can **read back** depends on mode:
|
|
471
508
|
|
|
@@ -483,7 +520,7 @@ In `mode: audit`, denials show as `WOULD-DENY` in `audit` output (`shadow: true`
|
|
|
483
520
|
|
|
484
521
|
These are the non-repudiable receipts for compliance and fleet audit, not the local JSONL file.
|
|
485
522
|
|
|
486
|
-

|
|
523
|
+

|
|
487
524
|
|
|
488
525
|
More: [docs/DETAILS.md § Receipts](docs/DETAILS.md#receipts).
|
|
489
526
|
|
|
@@ -506,11 +543,25 @@ Runtime refuses to start if an admin key is in the environment.
|
|
|
506
543
|
in version control, and the [Cloud capabilities above](#cloud-mode). See
|
|
507
544
|
[Tenuo Cloud docs](https://docs.tenuo.ai).
|
|
508
545
|
|
|
509
|
-
### Scope and
|
|
546
|
+
### Scope and boundaries
|
|
547
|
+
|
|
548
|
+
Tenuo governs **model-invoked tool calls**: Read, Bash, WebFetch, MCP tools,
|
|
549
|
+
subagent spawns, and the rest of the PreToolUse hook path. Each call is checked
|
|
550
|
+
against the signed session warrant before it runs.
|
|
551
|
+
|
|
552
|
+
**Agent Bash is in scope.** When the model uses the Bash tool, PreToolUse fires and
|
|
553
|
+
the authorizer applies your policy.
|
|
554
|
+
|
|
555
|
+
**TUI `!` shell is outside this scope.** In Claude Code, typing `!` in the input
|
|
556
|
+
box runs a command the **operator** typed. The model cannot invoke that path.
|
|
557
|
+
Prompt injection and tool overreach stay on the governed PreToolUse path; they do
|
|
558
|
+
not reach `!`.
|
|
559
|
+
|
|
560
|
+
Details: [docs/DETAILS.md § Agent tools vs operator shell](docs/DETAILS.md#agent-tools-vs-operator-shell).
|
|
510
561
|
|
|
511
|
-
|
|
562
|
+
### Fail-closed
|
|
512
563
|
|
|
513
|
-
Missing or broken `tenuo.yaml` denies every call until restored.
|
|
564
|
+
Missing or broken `tenuo.yaml` denies every governed tool call until restored.
|
|
514
565
|
|
|
515
566
|
Keys and credentials in `.state/` must be owner-only (`0600` in a `0700` directory).
|
|
516
567
|
|