connectonion 0.6.4__py3-none-any.whl → 0.6.5__py3-none-any.whl
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.
- connectonion/__init__.py +1 -1
- connectonion/cli/co_ai/main.py +2 -2
- connectonion/cli/co_ai/prompts/connectonion/concepts/trust.md +166 -208
- connectonion/cli/commands/copy_commands.py +21 -0
- connectonion/cli/commands/trust_commands.py +152 -0
- connectonion/cli/main.py +82 -0
- connectonion/core/llm.py +2 -2
- connectonion/docs/concepts/fast_rules.md +237 -0
- connectonion/docs/concepts/onboarding.md +465 -0
- connectonion/docs/concepts/trust.md +933 -192
- connectonion/docs/design-decisions/023-trust-policy-system-design.md +323 -0
- connectonion/docs/network/README.md +23 -1
- connectonion/docs/network/connect.md +135 -0
- connectonion/docs/network/host.md +73 -4
- connectonion/network/__init__.py +7 -6
- connectonion/network/asgi/__init__.py +3 -0
- connectonion/network/asgi/http.py +125 -19
- connectonion/network/asgi/websocket.py +276 -15
- connectonion/network/connect.py +145 -29
- connectonion/network/host/auth.py +70 -67
- connectonion/network/host/routes.py +88 -3
- connectonion/network/host/server.py +100 -17
- connectonion/network/trust/__init__.py +27 -19
- connectonion/network/trust/factory.py +51 -24
- connectonion/network/trust/fast_rules.py +100 -0
- connectonion/network/trust/tools.py +316 -32
- connectonion/network/trust/trust_agent.py +403 -0
- connectonion/transcribe.py +1 -1
- {connectonion-0.6.4.dist-info → connectonion-0.6.5.dist-info}/METADATA +1 -1
- {connectonion-0.6.4.dist-info → connectonion-0.6.5.dist-info}/RECORD +32 -27
- connectonion/network/trust/prompts.py +0 -71
- {connectonion-0.6.4.dist-info → connectonion-0.6.5.dist-info}/WHEEL +0 -0
- {connectonion-0.6.4.dist-info → connectonion-0.6.5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI commands for managing trust lists (contacts, whitelist, blocklist, admins).
|
|
3
|
+
|
|
4
|
+
Addresses are shown in full (not truncated) so users can easily copy them
|
|
5
|
+
for use in other commands or configuration files.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
co trust list # List all trust lists
|
|
9
|
+
co trust level <address> # Check trust level of address
|
|
10
|
+
co trust add <address> # Add to contacts (default)
|
|
11
|
+
co trust add <address> -w # Add to whitelist
|
|
12
|
+
co trust remove <address> # Remove from all lists
|
|
13
|
+
co trust block <address> # Block an address
|
|
14
|
+
co trust unblock <address> # Unblock an address
|
|
15
|
+
co trust admin add <address> # Add admin (super admin only)
|
|
16
|
+
co trust admin remove <address> # Remove admin (super admin only)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from rich.console import Console
|
|
21
|
+
from rich.table import Table
|
|
22
|
+
|
|
23
|
+
from ...network.trust.tools import (
|
|
24
|
+
CO_DIR,
|
|
25
|
+
get_level,
|
|
26
|
+
promote_to_contact,
|
|
27
|
+
promote_to_whitelist,
|
|
28
|
+
demote_to_stranger,
|
|
29
|
+
block,
|
|
30
|
+
unblock,
|
|
31
|
+
add_admin,
|
|
32
|
+
remove_admin,
|
|
33
|
+
load_admins,
|
|
34
|
+
get_self_address,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
console = Console()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _read_list(list_name: str) -> list[str]:
|
|
41
|
+
"""Read entries from a list file."""
|
|
42
|
+
list_path = CO_DIR / f"{list_name}.txt"
|
|
43
|
+
if not list_path.exists():
|
|
44
|
+
return []
|
|
45
|
+
content = list_path.read_text(encoding='utf-8')
|
|
46
|
+
return [line.strip() for line in content.splitlines()
|
|
47
|
+
if line.strip() and not line.startswith('#')]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def handle_trust_list():
|
|
51
|
+
"""List all trust lists."""
|
|
52
|
+
contacts = _read_list("contacts")
|
|
53
|
+
whitelist = _read_list("whitelist")
|
|
54
|
+
blocklist = _read_list("blocklist")
|
|
55
|
+
admins = load_admins()
|
|
56
|
+
self_addr = get_self_address()
|
|
57
|
+
|
|
58
|
+
console.print()
|
|
59
|
+
|
|
60
|
+
# Admins
|
|
61
|
+
console.print("[bold]Admins[/bold]")
|
|
62
|
+
if admins:
|
|
63
|
+
for addr in admins:
|
|
64
|
+
label = " [dim](self)[/dim]" if addr == self_addr else ""
|
|
65
|
+
console.print(f" {addr}{label}")
|
|
66
|
+
else:
|
|
67
|
+
console.print(" [dim]No admins configured[/dim]")
|
|
68
|
+
console.print()
|
|
69
|
+
|
|
70
|
+
# Whitelist
|
|
71
|
+
console.print("[bold]Whitelist[/bold] [dim](full trust)[/dim]")
|
|
72
|
+
if whitelist:
|
|
73
|
+
for addr in whitelist:
|
|
74
|
+
console.print(f" {addr}")
|
|
75
|
+
else:
|
|
76
|
+
console.print(" [dim]Empty[/dim]")
|
|
77
|
+
console.print()
|
|
78
|
+
|
|
79
|
+
# Contacts
|
|
80
|
+
console.print("[bold]Contacts[/bold] [dim](verified via invite/payment)[/dim]")
|
|
81
|
+
if contacts:
|
|
82
|
+
for addr in contacts:
|
|
83
|
+
console.print(f" {addr}")
|
|
84
|
+
else:
|
|
85
|
+
console.print(" [dim]Empty[/dim]")
|
|
86
|
+
console.print()
|
|
87
|
+
|
|
88
|
+
# Blocklist
|
|
89
|
+
console.print("[bold]Blocklist[/bold] [dim](denied access)[/dim]")
|
|
90
|
+
if blocklist:
|
|
91
|
+
for addr in blocklist:
|
|
92
|
+
console.print(f" [red]{addr}[/red]")
|
|
93
|
+
else:
|
|
94
|
+
console.print(" [dim]Empty[/dim]")
|
|
95
|
+
console.print()
|
|
96
|
+
|
|
97
|
+
console.print(f"[dim]Lists stored in: {CO_DIR}[/dim]")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def handle_trust_level(address: str):
|
|
101
|
+
"""Check trust level of an address."""
|
|
102
|
+
level = get_level(address)
|
|
103
|
+
|
|
104
|
+
level_colors = {
|
|
105
|
+
"stranger": "dim",
|
|
106
|
+
"contact": "cyan",
|
|
107
|
+
"whitelist": "green",
|
|
108
|
+
"blocked": "red",
|
|
109
|
+
}
|
|
110
|
+
color = level_colors.get(level, "white")
|
|
111
|
+
|
|
112
|
+
console.print(f"\n{address}: [{color}]{level}[/{color}]\n")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def handle_trust_add(address: str, whitelist: bool = False):
|
|
116
|
+
"""Add address to contacts or whitelist."""
|
|
117
|
+
if whitelist:
|
|
118
|
+
result = promote_to_whitelist(address)
|
|
119
|
+
console.print(f"\n[green]✓[/green] {result}\n")
|
|
120
|
+
else:
|
|
121
|
+
result = promote_to_contact(address)
|
|
122
|
+
console.print(f"\n[green]✓[/green] {result}\n")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def handle_trust_remove(address: str):
|
|
126
|
+
"""Remove address from all lists (demote to stranger)."""
|
|
127
|
+
result = demote_to_stranger(address)
|
|
128
|
+
console.print(f"\n[yellow]✓[/yellow] {result}\n")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def handle_trust_block(address: str, reason: str = ""):
|
|
132
|
+
"""Block an address."""
|
|
133
|
+
result = block(address, reason)
|
|
134
|
+
console.print(f"\n[red]✓[/red] {result}\n")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def handle_trust_unblock(address: str):
|
|
138
|
+
"""Unblock an address."""
|
|
139
|
+
result = unblock(address)
|
|
140
|
+
console.print(f"\n[green]✓[/green] {result}\n")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def handle_admin_add(address: str):
|
|
144
|
+
"""Add an admin."""
|
|
145
|
+
result = add_admin(address)
|
|
146
|
+
console.print(f"\n[green]✓[/green] {result}\n")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def handle_admin_remove(address: str):
|
|
150
|
+
"""Remove an admin."""
|
|
151
|
+
result = remove_admin(address)
|
|
152
|
+
console.print(f"\n[yellow]✓[/yellow] {result}\n")
|
connectonion/cli/main.py
CHANGED
|
@@ -56,6 +56,7 @@ def _show_help():
|
|
|
56
56
|
console.print(" [green]init[/green] Initialize in current directory")
|
|
57
57
|
console.print(" [green]copy[/green] <name> Copy tool/plugin source to project")
|
|
58
58
|
console.print(" [green]eval[/green] Run evals and show status")
|
|
59
|
+
console.print(" [green]trust[/green] Manage trust lists")
|
|
59
60
|
console.print(" [green]deploy[/green] Deploy to ConnectOnion Cloud")
|
|
60
61
|
console.print(" [green]auth[/green] Authenticate for managed keys")
|
|
61
62
|
console.print(" [green]status[/green] Check account balance")
|
|
@@ -174,6 +175,87 @@ def eval(
|
|
|
174
175
|
handle_eval(name=name, agent_file=agent)
|
|
175
176
|
|
|
176
177
|
|
|
178
|
+
# Trust command group
|
|
179
|
+
trust_app = typer.Typer(help="Manage trust lists (contacts, whitelist, blocklist, admins)")
|
|
180
|
+
app.add_typer(trust_app, name="trust")
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@trust_app.callback(invoke_without_command=True)
|
|
184
|
+
def trust_callback(ctx: typer.Context):
|
|
185
|
+
"""Trust list management."""
|
|
186
|
+
if ctx.invoked_subcommand is None:
|
|
187
|
+
# Default to list
|
|
188
|
+
from .commands.trust_commands import handle_trust_list
|
|
189
|
+
handle_trust_list()
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@trust_app.command("list")
|
|
193
|
+
def trust_list():
|
|
194
|
+
"""List all trust lists."""
|
|
195
|
+
from .commands.trust_commands import handle_trust_list
|
|
196
|
+
handle_trust_list()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@trust_app.command("level")
|
|
200
|
+
def trust_level(address: str = typer.Argument(..., help="Address to check")):
|
|
201
|
+
"""Check trust level of an address."""
|
|
202
|
+
from .commands.trust_commands import handle_trust_level
|
|
203
|
+
handle_trust_level(address)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@trust_app.command("add")
|
|
207
|
+
def trust_add(
|
|
208
|
+
address: str = typer.Argument(..., help="Address to add"),
|
|
209
|
+
whitelist: bool = typer.Option(False, "-w", "--whitelist", help="Add to whitelist instead of contacts"),
|
|
210
|
+
):
|
|
211
|
+
"""Add address to contacts (default) or whitelist."""
|
|
212
|
+
from .commands.trust_commands import handle_trust_add
|
|
213
|
+
handle_trust_add(address, whitelist)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@trust_app.command("remove")
|
|
217
|
+
def trust_remove(address: str = typer.Argument(..., help="Address to remove")):
|
|
218
|
+
"""Remove address from all lists (demote to stranger)."""
|
|
219
|
+
from .commands.trust_commands import handle_trust_remove
|
|
220
|
+
handle_trust_remove(address)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@trust_app.command("block")
|
|
224
|
+
def trust_block(
|
|
225
|
+
address: str = typer.Argument(..., help="Address to block"),
|
|
226
|
+
reason: str = typer.Option("", "-r", "--reason", help="Reason for blocking"),
|
|
227
|
+
):
|
|
228
|
+
"""Block an address."""
|
|
229
|
+
from .commands.trust_commands import handle_trust_block
|
|
230
|
+
handle_trust_block(address, reason)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@trust_app.command("unblock")
|
|
234
|
+
def trust_unblock(address: str = typer.Argument(..., help="Address to unblock")):
|
|
235
|
+
"""Unblock an address."""
|
|
236
|
+
from .commands.trust_commands import handle_trust_unblock
|
|
237
|
+
handle_trust_unblock(address)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# Admin subcommand group
|
|
241
|
+
admin_app = typer.Typer(help="Manage admins (super admin only)")
|
|
242
|
+
trust_app.add_typer(admin_app, name="admin")
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@admin_app.command("add")
|
|
246
|
+
def admin_add(address: str = typer.Argument(..., help="Address to add as admin")):
|
|
247
|
+
"""Add an admin."""
|
|
248
|
+
from .commands.trust_commands import handle_admin_add
|
|
249
|
+
handle_admin_add(address)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@admin_app.command("remove")
|
|
253
|
+
def admin_remove(address: str = typer.Argument(..., help="Address to remove from admins")):
|
|
254
|
+
"""Remove an admin."""
|
|
255
|
+
from .commands.trust_commands import handle_admin_remove
|
|
256
|
+
handle_admin_remove(address)
|
|
257
|
+
|
|
258
|
+
|
|
177
259
|
def cli():
|
|
178
260
|
"""Entry point."""
|
|
179
261
|
app()
|
connectonion/core/llm.py
CHANGED
|
@@ -3,7 +3,7 @@ Purpose: Unified LLM provider abstraction with factory pattern for OpenAI, Anthr
|
|
|
3
3
|
LLM-Note:
|
|
4
4
|
Dependencies: imports from [abc, typing, dataclasses, json, os, base64, openai, anthropic, requests, pathlib, toml, pydantic, .usage, .exceptions] | imported by [agent.py, llm_do.py, conftest.py] | tested by [tests/test_llm.py, tests/test_llm_do.py, tests/test_real_*.py, tests/test_billing_error_agent.py]
|
|
5
5
|
Data flow: Agent/llm_do calls create_llm(model, api_key) → factory routes to provider class → Provider.__init__() validates API key → Agent calls complete(messages, tools) OR structured_complete(messages, output_schema) → provider converts to native format → calls API → parses response → returns LLMResponse(content, tool_calls, raw_response) OR Pydantic model instance
|
|
6
|
-
State/Effects: reads environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENONION_API_KEY) | reads ~/.
|
|
6
|
+
State/Effects: reads environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENONION_API_KEY) | reads ~/.co/config.toml for OpenOnion auth | makes HTTP requests to LLM APIs | no caching or persistence
|
|
7
7
|
Integration: exposes create_llm(model, api_key), LLM abstract base class, OpenAILLM, AnthropicLLM, GeminiLLM, OpenOnionLLM, LLMResponse, ToolCall dataclasses | providers implement complete() and structured_complete() | OpenAI message format is lingua franca | tool calling uses OpenAI schema converted per-provider
|
|
8
8
|
Performance: stateless (no caching) | synchronous (no streaming) | default max_tokens=8192 for Anthropic (required) | each call hits API
|
|
9
9
|
Errors: raises ValueError for missing API keys, unknown models, invalid parameters | provider-specific errors bubble up (openai.APIError, anthropic.APIError, etc.) | OpenOnionLLM transforms 402 errors to InsufficientCreditsError with formatted message and typed attributes | Pydantic ValidationError for invalid structured output
|
|
@@ -97,7 +97,7 @@ Required (pick one):
|
|
|
97
97
|
- OPENAI_API_KEY: For OpenAI models
|
|
98
98
|
- ANTHROPIC_API_KEY: For Claude models
|
|
99
99
|
- GEMINI_API_KEY or GOOGLE_API_KEY: For Gemini models
|
|
100
|
-
- OPENONION_API_KEY: For co/ managed keys (or from ~/.
|
|
100
|
+
- OPENONION_API_KEY: For co/ managed keys (or from ~/.co/config.toml)
|
|
101
101
|
|
|
102
102
|
Optional:
|
|
103
103
|
- OPENONION_DEV: Use localhost:8000 for OpenOnion (development)
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Fast Rules
|
|
2
|
+
|
|
3
|
+
Fast rules are code-executed trust checks that run **before** the LLM. They burn zero tokens and are instant.
|
|
4
|
+
|
|
5
|
+
## Why Fast Rules?
|
|
6
|
+
|
|
7
|
+
Trust verification that uses an LLM costs tokens. Every verification burns money.
|
|
8
|
+
|
|
9
|
+
- 1000 requests/day × $0.001/verification = $365/year just for "should I trust this?"
|
|
10
|
+
- 90% of trust decisions are mechanical (whitelist check, blocklist check)
|
|
11
|
+
- Only 10% need LLM judgment
|
|
12
|
+
|
|
13
|
+
Fast rules handle the 90%. LLM handles the 10%.
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Request comes in
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
┌─────────────────┐
|
|
22
|
+
│ Fast Rules │ ← No tokens, instant
|
|
23
|
+
│ │
|
|
24
|
+
│ 1. blocked? │──deny──►
|
|
25
|
+
│ 2. whitelisted? │──allow──►
|
|
26
|
+
│ 3. contact? │──allow──►
|
|
27
|
+
│ 4. onboard? │──promote + allow──►
|
|
28
|
+
└─────────────────┘
|
|
29
|
+
│
|
|
30
|
+
│ No rule matched
|
|
31
|
+
▼
|
|
32
|
+
┌─────────────────┐
|
|
33
|
+
│ Trust Agent │ ← LLM, burns tokens
|
|
34
|
+
│ (if enabled) │
|
|
35
|
+
└─────────────────┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Policy File Format
|
|
39
|
+
|
|
40
|
+
Trust policies are markdown files with YAML frontmatter:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
---
|
|
44
|
+
# YAML config (fast rules)
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
# Markdown body (LLM system prompt)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Full Example
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
---
|
|
54
|
+
# Who has access
|
|
55
|
+
allow:
|
|
56
|
+
- whitelisted
|
|
57
|
+
- contact
|
|
58
|
+
|
|
59
|
+
# Who is blocked
|
|
60
|
+
deny:
|
|
61
|
+
- blocked
|
|
62
|
+
|
|
63
|
+
# How strangers become contacts (onboarding)
|
|
64
|
+
onboard:
|
|
65
|
+
invite_code: [BETA2024, FRIEND123]
|
|
66
|
+
payment: 10
|
|
67
|
+
|
|
68
|
+
# Strangers without credentials
|
|
69
|
+
default: ask # allow | deny | ask
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
# Careful Trust
|
|
73
|
+
|
|
74
|
+
You evaluate unknown agents...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Config Options
|
|
78
|
+
|
|
79
|
+
### `allow:`
|
|
80
|
+
|
|
81
|
+
Who has access. List of conditions:
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
---
|
|
85
|
+
allow:
|
|
86
|
+
- whitelisted # Users in ~/.co/whitelist.txt
|
|
87
|
+
- contact # Users in ~/.co/contacts.txt
|
|
88
|
+
---
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `deny:`
|
|
92
|
+
|
|
93
|
+
Who is blocked:
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
---
|
|
97
|
+
deny:
|
|
98
|
+
- blocked # Users in ~/.co/blocklist.txt
|
|
99
|
+
---
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `onboard:`
|
|
103
|
+
|
|
104
|
+
How strangers become contacts (OR logic):
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
---
|
|
108
|
+
onboard:
|
|
109
|
+
invite_code: [CODE1, CODE2] # Valid invite codes
|
|
110
|
+
payment: 10 # Minimum payment amount
|
|
111
|
+
---
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- `invite_code`: Client sends `invite_code` in request → becomes contact
|
|
115
|
+
- `payment`: Client sends `payment` >= amount → becomes contact
|
|
116
|
+
|
|
117
|
+
**OR logic**: Either invite_code OR payment passes → promoted to contact.
|
|
118
|
+
|
|
119
|
+
### `default:`
|
|
120
|
+
|
|
121
|
+
What to do with strangers who don't onboard:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
---
|
|
125
|
+
default: ask # Use LLM to decide (careful mode)
|
|
126
|
+
# OR
|
|
127
|
+
default: deny # Reject (strict mode)
|
|
128
|
+
# OR
|
|
129
|
+
default: allow # Accept (open mode)
|
|
130
|
+
---
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## The Three Presets
|
|
134
|
+
|
|
135
|
+
### open (Development)
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
---
|
|
139
|
+
default: allow
|
|
140
|
+
---
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Everyone allowed. No verification.
|
|
144
|
+
|
|
145
|
+
### careful (Staging)
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
---
|
|
149
|
+
allow:
|
|
150
|
+
- whitelisted
|
|
151
|
+
- contact
|
|
152
|
+
|
|
153
|
+
deny:
|
|
154
|
+
- blocked
|
|
155
|
+
|
|
156
|
+
onboard:
|
|
157
|
+
invite_code: [BETA2024]
|
|
158
|
+
payment: 10
|
|
159
|
+
|
|
160
|
+
default: ask
|
|
161
|
+
---
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Whitelisted and contacts allowed. Strangers can onboard or be evaluated by LLM.
|
|
165
|
+
|
|
166
|
+
### strict (Production)
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
---
|
|
170
|
+
allow:
|
|
171
|
+
- whitelisted
|
|
172
|
+
|
|
173
|
+
deny:
|
|
174
|
+
- blocked
|
|
175
|
+
|
|
176
|
+
default: deny
|
|
177
|
+
---
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Whitelist only. Everyone else denied.
|
|
181
|
+
|
|
182
|
+
## Execution Order
|
|
183
|
+
|
|
184
|
+
Fast rules execute in this order:
|
|
185
|
+
|
|
186
|
+
1. Check `deny` list → deny if blocked
|
|
187
|
+
2. Check `allow` list → allow if whitelisted/contact
|
|
188
|
+
3. Try `onboard` → promote + allow if valid credentials
|
|
189
|
+
4. `default` → allow / deny / ask
|
|
190
|
+
|
|
191
|
+
## List Files
|
|
192
|
+
|
|
193
|
+
Fast rules read from `~/.co/`:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
~/.co/
|
|
197
|
+
├── whitelist.txt # Trusted clients
|
|
198
|
+
├── contacts.txt # Verified clients
|
|
199
|
+
└── blocklist.txt # Blocked clients
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Format
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
# Comments start with #
|
|
206
|
+
client-id-123
|
|
207
|
+
another-client
|
|
208
|
+
|
|
209
|
+
# Wildcards supported
|
|
210
|
+
payment-*
|
|
211
|
+
*.trusted.com
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Implementation
|
|
215
|
+
|
|
216
|
+
See `connectonion/network/trust/fast_rules.py`:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from connectonion.network.trust import parse_policy, evaluate_request
|
|
220
|
+
|
|
221
|
+
# Parse policy file
|
|
222
|
+
config, markdown_body = parse_policy(policy_text)
|
|
223
|
+
|
|
224
|
+
# Evaluate request
|
|
225
|
+
result = evaluate_request(config, client_id, request)
|
|
226
|
+
# Returns: 'allow', 'deny', or None (needs LLM)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Summary
|
|
230
|
+
|
|
231
|
+
| Feature | Fast Rules | LLM Trust Agent |
|
|
232
|
+
|---------|------------|-----------------|
|
|
233
|
+
| Tokens | Zero | Burns tokens |
|
|
234
|
+
| Speed | Instant | Slow (API call) |
|
|
235
|
+
| Logic | Simple checks | Complex reasoning |
|
|
236
|
+
| Use | 90% of requests | 10% of requests |
|
|
237
|
+
| Config | YAML frontmatter | Markdown body |
|