tenuo-claude-code 0.2.0__tar.gz → 0.2.1__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.1}/PKG-INFO +3 -5
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/README.md +2 -4
- tenuo_claude_code-0.2.1/docs/images/README.md +22 -0
- tenuo_claude_code-0.2.1/docs/images/tenuo_claude_code_architecture.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/pyproject.toml +1 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/__init__.py +1 -1
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/cli.py +34 -33
- tenuo_claude_code-0.2.1/tests/test_check.py +74 -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 → tenuo_claude_code-0.2.1}/.gitignore +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/CONTRIBUTING.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/LICENSE +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/.claude/agents/researcher.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/.mcp.json +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/README.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/fake-secrets.env +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/ops_server.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/sandbox/incident-report.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/sandbox/notes.txt +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/tenuo.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/demo/tenuo_demo.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/DETAILS.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/images/cloud-audit-stream.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/images/cloud-receipt-approval-detail.png +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/images/tenuo_claude_code_architecture.svg +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/examples/policies/README.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/examples/policies/audit-rollout.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/examples/policies/enforce-with-mcp.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/examples/policies/read-only-research.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/admin.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/authorizer_runtime.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/data/harness_tools.yaml +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/paths.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/templates/tenuo.yaml.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/verify.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/README.md +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/admin.env.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/cloud.env.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/tenuo.yaml.advanced.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/tenuo.yaml.cloud.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/templates/tenuo.yaml.example +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/conftest.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_admin.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_approvals.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_authorize_call.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_authorizer_runtime.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_constraints.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_permissions.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_routing.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_scaffold.py +0 -0
- {tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/tests/test_subagents.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tenuo-claude-code
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
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)
|
|
@@ -71,7 +69,7 @@ No Docker, or prefer native? Run `tenuo-claude install-authorizer` once, then `b
|
|
|
71
69
|
|
|
72
70
|
## How it works
|
|
73
71
|
|
|
74
|
-

|
|
75
73
|
|
|
76
74
|
```
|
|
77
75
|
tenuo.yaml → init/up → warrant + authorizer + hooks + MCP proxy
|
|
@@ -483,7 +481,7 @@ In `mode: audit`, denials show as `WOULD-DENY` in `audit` output (`shadow: true`
|
|
|
483
481
|
|
|
484
482
|
These are the non-repudiable receipts for compliance and fleet audit, not the local JSONL file.
|
|
485
483
|
|
|
486
|
-

|
|
484
|
+

|
|
487
485
|
|
|
488
486
|
More: [docs/DETAILS.md § Receipts](docs/DETAILS.md#receipts).
|
|
489
487
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# Tenuo for Claude Code
|
|
2
2
|
|
|
3
|
-
PyPI package: [`tenuo-claude-code`](https://pypi.org/project/tenuo-claude-code/) · CLI: `tenuo-claude`, `tenuo-admin`
|
|
4
|
-
|
|
5
3
|
[](https://pypi.org/project/tenuo-claude-code/)
|
|
6
4
|
[](https://pypi.org/project/tenuo-claude-code/)
|
|
7
5
|
[](https://github.com/tenuo-ai/claude-governance/actions/workflows/ci.yml)
|
|
@@ -41,7 +39,7 @@ No Docker, or prefer native? Run `tenuo-claude install-authorizer` once, then `b
|
|
|
41
39
|
|
|
42
40
|
## How it works
|
|
43
41
|
|
|
44
|
-

|
|
45
43
|
|
|
46
44
|
```
|
|
47
45
|
tenuo.yaml → init/up → warrant + authorizer + hooks + MCP proxy
|
|
@@ -453,7 +451,7 @@ In `mode: audit`, denials show as `WOULD-DENY` in `audit` output (`shadow: true`
|
|
|
453
451
|
|
|
454
452
|
These are the non-repudiable receipts for compliance and fleet audit, not the local JSONL file.
|
|
455
453
|
|
|
456
|
-

|
|
454
|
+

|
|
457
455
|
|
|
458
456
|
More: [docs/DETAILS.md § Receipts](docs/DETAILS.md#receipts).
|
|
459
457
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Images for docs
|
|
2
|
+
|
|
3
|
+
| File | Used in | Shows |
|
|
4
|
+
|------|---------|--------|
|
|
5
|
+
| `tenuo_claude_code_architecture.png` | README (PyPI + GitHub) | Architecture diagram (export from `.svg`) |
|
|
6
|
+
| `tenuo_claude_code_architecture.svg` | Source | Editable diagram |
|
|
7
|
+
| `cloud-audit-stream.png` | README | Cloud receipt list (allow/deny/approved) |
|
|
8
|
+
| `cloud-receipt-approval-detail.png` | PRESENTATION | Drill-down: human approval + request hash |
|
|
9
|
+
|
|
10
|
+
**PyPI:** the project README uses absolute `raw.githubusercontent.com` URLs and PNG
|
|
11
|
+
(raster) assets. PyPI does not resolve relative paths and does not render SVG in
|
|
12
|
+
project descriptions.
|
|
13
|
+
|
|
14
|
+
Regenerate the architecture PNG after editing the SVG:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
rsvg-convert -w 1280 docs/images/tenuo_claude_code_architecture.svg \
|
|
18
|
+
-o docs/images/tenuo_claude_code_architecture.png
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Captured from [cloud.tenuo.ai](https://cloud.tenuo.ai) after a governed WebFetch
|
|
22
|
+
with approval configured. Do not commit credentials or secrets in replacements.
|
|
Binary file
|
|
@@ -1931,6 +1931,40 @@ def cmd_onboard(args) -> None:
|
|
|
1931
1931
|
|
|
1932
1932
|
created = scaffold_example_policy(DEMO_DIR, no_scaffold=getattr(args, "no_scaffold", False))
|
|
1933
1933
|
|
|
1934
|
+
admin_key = None
|
|
1935
|
+
if cloud:
|
|
1936
|
+
token = getattr(args, "connect_token", None) or os.environ.get("TENUO_CONNECT_TOKEN")
|
|
1937
|
+
if not token and CLOUD_ENV.exists():
|
|
1938
|
+
token = runtime_env().get("TENUO_CONNECT_TOKEN")
|
|
1939
|
+
if not token and not getattr(args, "yes", False):
|
|
1940
|
+
token = _prompt("Paste Quick Connect token (tenuo_ct_…)")
|
|
1941
|
+
if not token:
|
|
1942
|
+
raise SystemExit("Cloud onboarding needs TENUO_CONNECT_TOKEN (Quick Connect → Authorizer Only).")
|
|
1943
|
+
write_cloud_env(token)
|
|
1944
|
+
|
|
1945
|
+
url = _parse_connect_token(token.strip())["url"]
|
|
1946
|
+
write_cloud_profile(url=url)
|
|
1947
|
+
print(f"Wrote {CLOUD_PROFILE.name}")
|
|
1948
|
+
|
|
1949
|
+
if getattr(args, "advanced", False) or getattr(args, "demo", False):
|
|
1950
|
+
approver = getattr(args, "approver", None)
|
|
1951
|
+
approver_id = getattr(args, "approver_id", None)
|
|
1952
|
+
if not approver and not approver_id and not getattr(args, "yes", False):
|
|
1953
|
+
approver = _prompt("Approver display name (must exist in Cloud)")
|
|
1954
|
+
if not approver and not approver_id:
|
|
1955
|
+
raise SystemExit("--advanced requires --approver-id or --approver.")
|
|
1956
|
+
write_advanced_profile(approver=approver, approver_id=approver_id)
|
|
1957
|
+
print(f"Wrote {ADVANCED_PROFILE.name} (advanced — re-run `tenuo-admin setup`)")
|
|
1958
|
+
|
|
1959
|
+
admin_key = getattr(args, "admin_key", None) or os.environ.get("TENUO_ADMIN_KEY")
|
|
1960
|
+
if not admin_key and ADMIN_ENV.exists():
|
|
1961
|
+
admin_key = read_env_file(ADMIN_ENV).get("TENUO_ADMIN_KEY")
|
|
1962
|
+
if not admin_key and not getattr(args, "yes", False):
|
|
1963
|
+
admin_key = _prompt("Paste tenant-admin key for one-time setup (blank = skip)", "")
|
|
1964
|
+
if admin_key:
|
|
1965
|
+
write_admin_env(admin_key)
|
|
1966
|
+
print(f"Wrote {ADMIN_ENV}")
|
|
1967
|
+
|
|
1934
1968
|
if not created:
|
|
1935
1969
|
print("\nRunning preflight…")
|
|
1936
1970
|
try:
|
|
@@ -1955,39 +1989,6 @@ def cmd_onboard(args) -> None:
|
|
|
1955
1989
|
print("\nOnboard complete (local). Open Claude Code in this directory.")
|
|
1956
1990
|
return
|
|
1957
1991
|
|
|
1958
|
-
# Cloud path
|
|
1959
|
-
token = getattr(args, "connect_token", None) or os.environ.get("TENUO_CONNECT_TOKEN")
|
|
1960
|
-
if not token and CLOUD_ENV.exists():
|
|
1961
|
-
token = runtime_env().get("TENUO_CONNECT_TOKEN")
|
|
1962
|
-
if not token and not getattr(args, "yes", False):
|
|
1963
|
-
token = _prompt("Paste Quick Connect token (tenuo_ct_…)")
|
|
1964
|
-
if not token:
|
|
1965
|
-
raise SystemExit("Cloud onboarding needs TENUO_CONNECT_TOKEN (Quick Connect → Authorizer Only).")
|
|
1966
|
-
write_cloud_env(token)
|
|
1967
|
-
|
|
1968
|
-
url = _parse_connect_token(token.strip())["url"]
|
|
1969
|
-
write_cloud_profile(url=url)
|
|
1970
|
-
print(f"Wrote {CLOUD_PROFILE.name}")
|
|
1971
|
-
|
|
1972
|
-
if getattr(args, "advanced", False) or getattr(args, "demo", False):
|
|
1973
|
-
approver = getattr(args, "approver", None)
|
|
1974
|
-
approver_id = getattr(args, "approver_id", None)
|
|
1975
|
-
if not approver and not approver_id and not getattr(args, "yes", False):
|
|
1976
|
-
approver = _prompt("Approver display name (must exist in Cloud)")
|
|
1977
|
-
if not approver and not approver_id:
|
|
1978
|
-
raise SystemExit("--advanced requires --approver-id or --approver.")
|
|
1979
|
-
write_advanced_profile(approver=approver, approver_id=approver_id)
|
|
1980
|
-
print(f"Wrote {ADVANCED_PROFILE.name} (advanced — re-run `tenuo-admin setup`)")
|
|
1981
|
-
|
|
1982
|
-
admin_key = getattr(args, "admin_key", None) or os.environ.get("TENUO_ADMIN_KEY")
|
|
1983
|
-
if not admin_key and ADMIN_ENV.exists():
|
|
1984
|
-
admin_key = read_env_file(ADMIN_ENV).get("TENUO_ADMIN_KEY")
|
|
1985
|
-
if not admin_key and not getattr(args, "yes", False):
|
|
1986
|
-
admin_key = _prompt("Paste tenant-admin key for one-time setup (blank = skip)", "")
|
|
1987
|
-
if admin_key:
|
|
1988
|
-
write_admin_env(admin_key)
|
|
1989
|
-
print(f"Wrote {ADMIN_ENV}")
|
|
1990
|
-
|
|
1991
1992
|
cmd_init(argparse.Namespace(cloud=False, local=False))
|
|
1992
1993
|
|
|
1993
1994
|
if admin_key:
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Preflight / wiring checks (PyPI layout — no repo ``bin/tenuo-claude``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
from tenuo_claude_code import cli
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_check_wiring_ok_without_launcher(monkeypatch, tmp_path):
|
|
11
|
+
"""Missing ``./bin/tenuo-claude`` must not fail preflight (PyPI installs use PATH)."""
|
|
12
|
+
proj = tmp_path / "proj"
|
|
13
|
+
proj.mkdir()
|
|
14
|
+
monkeypatch.setattr(cli, "LAUNCHER", proj / "bin" / "tenuo-claude", raising=False)
|
|
15
|
+
monkeypatch.setattr(cli, "DEMO_DIR", proj, raising=False)
|
|
16
|
+
ok = cli._check_wiring({"mcp": {}}, True)
|
|
17
|
+
assert ok is True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_probe_runtime_creds_accepts_tenant_without_srl(monkeypatch):
|
|
21
|
+
monkeypatch.setattr(
|
|
22
|
+
cli,
|
|
23
|
+
"cloud_api",
|
|
24
|
+
lambda method, url, key, path: (
|
|
25
|
+
404,
|
|
26
|
+
{"error": {"code": "srl_not_found", "message": "no SRL exists for this tenant"}},
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
ok, msg = cli.probe_runtime_creds({"url": "https://api.example", "api_key": "rt"})
|
|
31
|
+
|
|
32
|
+
assert ok is True
|
|
33
|
+
assert "no SRL yet" in msg
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_cloud_onboard_writes_profile_before_preflight(monkeypatch, tmp_path):
|
|
37
|
+
state = tmp_path / ".state"
|
|
38
|
+
monkeypatch.setattr(cli, "DEMO_DIR", tmp_path, raising=False)
|
|
39
|
+
monkeypatch.setattr(cli, "STATE", state, raising=False)
|
|
40
|
+
monkeypatch.setattr(cli, "CONFIG_FILE", tmp_path / "tenuo.yaml", raising=False)
|
|
41
|
+
monkeypatch.setattr(cli, "CLOUD_ENV", state / "cloud.env", raising=False)
|
|
42
|
+
monkeypatch.setattr(cli, "CLOUD_STATE", state / "cloud_state.json", raising=False)
|
|
43
|
+
monkeypatch.setattr(cli, "CLOUD_PROFILE", tmp_path / "tenuo.cloud.yaml", raising=False)
|
|
44
|
+
monkeypatch.setattr(cli, "ADVANCED_PROFILE", tmp_path / "tenuo.advanced.yaml", raising=False)
|
|
45
|
+
monkeypatch.setattr(cli, "ADMIN_ENV", tmp_path / "home" / ".tenuo" / "admin.env", raising=False)
|
|
46
|
+
monkeypatch.setattr(cli, "scaffold_example_policy", lambda *a, **k: False)
|
|
47
|
+
monkeypatch.setattr(cli, "_parse_connect_token",
|
|
48
|
+
lambda token: {"url": "https://api.example", "api_key": "rt"})
|
|
49
|
+
|
|
50
|
+
seen = {}
|
|
51
|
+
|
|
52
|
+
def fake_check(_args):
|
|
53
|
+
seen["mode"] = cli.intended_mode({})
|
|
54
|
+
raise SystemExit(0)
|
|
55
|
+
|
|
56
|
+
monkeypatch.setattr(cli, "cmd_check", fake_check)
|
|
57
|
+
monkeypatch.setattr(cli, "cmd_init", lambda _args: None)
|
|
58
|
+
monkeypatch.setattr(cli, "cmd_up", lambda _args: None)
|
|
59
|
+
monkeypatch.setattr(cli, "cmd_verify", lambda _args: None)
|
|
60
|
+
|
|
61
|
+
cli.cmd_onboard(argparse.Namespace(
|
|
62
|
+
cloud=True,
|
|
63
|
+
local=False,
|
|
64
|
+
yes=True,
|
|
65
|
+
no_scaffold=False,
|
|
66
|
+
connect_token="tenuo_ct_fake",
|
|
67
|
+
admin_key=None,
|
|
68
|
+
advanced=False,
|
|
69
|
+
demo=False,
|
|
70
|
+
approver=None,
|
|
71
|
+
approver_id=None,
|
|
72
|
+
))
|
|
73
|
+
|
|
74
|
+
assert seen["mode"] == "cloud"
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Images for docs
|
|
2
|
-
|
|
3
|
-
| File | Used in | Shows |
|
|
4
|
-
|------|---------|--------|
|
|
5
|
-
| `cloud-audit-stream.png` | README | Cloud receipt list (allow/deny/approved) |
|
|
6
|
-
| `cloud-receipt-approval-detail.png` | README | Drill-down: human approval + request hash |
|
|
7
|
-
|
|
8
|
-
Captured from [cloud.tenuo.ai](https://cloud.tenuo.ai) after a governed WebFetch
|
|
9
|
-
with approval configured. Do not commit credentials or secrets in replacements.
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"""Preflight / wiring checks (PyPI layout — no repo ``bin/tenuo-claude``)."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from tenuo_claude_code import cli
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def test_check_wiring_ok_without_launcher(monkeypatch, tmp_path):
|
|
9
|
-
"""Missing ``./bin/tenuo-claude`` must not fail preflight (PyPI installs use PATH)."""
|
|
10
|
-
proj = tmp_path / "proj"
|
|
11
|
-
proj.mkdir()
|
|
12
|
-
monkeypatch.setattr(cli, "LAUNCHER", proj / "bin" / "tenuo-claude", raising=False)
|
|
13
|
-
monkeypatch.setattr(cli, "DEMO_DIR", proj, raising=False)
|
|
14
|
-
ok = cli._check_wiring({"mcp": {}}, True)
|
|
15
|
-
assert ok is True
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def test_probe_runtime_creds_accepts_tenant_without_srl(monkeypatch):
|
|
19
|
-
monkeypatch.setattr(
|
|
20
|
-
cli,
|
|
21
|
-
"cloud_api",
|
|
22
|
-
lambda method, url, key, path: (
|
|
23
|
-
404,
|
|
24
|
-
{"error": {"code": "srl_not_found", "message": "no SRL exists for this tenant"}},
|
|
25
|
-
),
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
ok, msg = cli.probe_runtime_creds({"url": "https://api.example", "api_key": "rt"})
|
|
29
|
-
|
|
30
|
-
assert ok is True
|
|
31
|
-
assert "no SRL yet" in msg
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/images/cloud-receipt-approval-detail.png
RENAMED
|
File without changes
|
{tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/docs/images/tenuo_claude_code_architecture.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/examples/policies/read-only-research.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/authorizer_runtime.py
RENAMED
|
File without changes
|
{tenuo_claude_code-0.2.0 → tenuo_claude_code-0.2.1}/src/tenuo_claude_code/data/harness_tools.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|