Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 30 additions & 21 deletions docs/connecting-to-the-platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,36 @@ control-plane path short-circuits. Local protection — the 63 default rules in

## Connection lifecycle at a glance

```
Developer machine (Prismor, this repo) Prismor control plane (prismor-web, proprietary)
───────────────────────────────────── ───────────────────────────────────────────────
prismor enroll <token> ──POST /api/devices/enroll──▶ validate one-time token
identity.enroll() {token,label,platform} mint revocable device_key
save_identity() 0600 ◀──{device_id,org_id,user_id,── record device row
~/.prismor/identity.json device_key,org_name}

hook-dispatch (hot path)
remote_policy.check_and_refresh()
──GET /api/policy/version?applied=N──────────────▶ {version,profileId,fullCapture,...}
if changed: GET /api/policy/resolve ─────────────▶ SIGN policy with PRIVATE key
verify_and_load() ◀────────{yaml, signature}───────── (private key NOT in this repo)
openssl verify vs keys/public.pub ── fail ⇒ ignore, keep last good

evaluate_tool_call() ⇒ finding
_dispatch_prismor() → build_record() (redact) → assert_redacted()
──POST /api/telemetry/ingest──{org_id,device_id,events[]}──▶ store
heartbeat.maybe_flush() ──POST /api/telemetry/ingest (count only)──▶

on 401/403 from any call ⇒ mark_revoked() ⇒ 1h backoff; last good policy stays
```mermaid
sequenceDiagram
participant Dev as Developer machine<br/>(Prismor, this repo)
participant CP as Prismor control plane<br/>(prismor-web, proprietary)

rect rgb(248, 250, 252)
Note over Dev,CP: Enroll
Dev->>CP: POST /api/devices/enroll<br/>{token, label, platform}
Note right of CP: validate one-time token<br/>mint revocable device_key
CP-->>Dev: {device_id, org_id, user_id,<br/>device_key, org_name}
Note left of Dev: save_identity() 0600<br/>~/.prismor/identity.json
end

rect rgb(248, 250, 252)
Note over Dev,CP: Hook-dispatch (hot path)
Dev->>CP: GET /api/policy/version?applied=N
CP-->>Dev: {version, profileId, fullCapture, ...}
alt version changed
Dev->>CP: GET /api/policy/resolve
Note right of CP: SIGN policy with PRIVATE key<br/>(never leaves the control plane)
CP-->>Dev: {yaml, signature}
Note left of Dev: verify_and_load():<br/>openssl verify vs keys/public.pub<br/>fail ⇒ ignore, keep last good
end
Note left of Dev: evaluate_tool_call() ⇒ finding<br/>build_record() (redact) → assert_redacted()
Dev->>CP: POST /api/telemetry/ingest<br/>{org_id, device_id, events[]}
CP-->>Dev: store
Dev->>CP: POST /api/telemetry/ingest (count only)<br/>heartbeat.maybe_flush()
end

Note over Dev,CP: on 401/403 from any call ⇒ mark_revoked()<br/>1h backoff — last good policy stays enforced
```

The endpoints above are what the **client calls**; the server implementation
Expand Down
59 changes: 22 additions & 37 deletions docs/hermes.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,19 @@ prismor cloak uninstall --agent all # removes both

## Architecture

```
HERMES AGENT
┌─────────────────────────────────────────────────────────────┐
│ │
│ Gateway (Telegram) → Agent (LLM) → Tools (shell/fs) │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌────────────┐ ┌──────────────┐ │
│ │pre_gw │ │pre_tool │ │transform_ │ │
│ │dispatch │ │call │ │terminal_out │ │
│ └──────────┘ └────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Paste guard │ │ Decloak │ │ Scrub output │
│ Detect raw │ │ Substitute │ │ Replace real │
│ secrets in │ │ @@SECRET@@ │ │ values with │
│ user prompts │ │ → real value │ │ placeholders │
│ Auto-vault │ │ at exec time │ │ before model │
└──────────────┘ └──────────────┘ └──────────────┘
```mermaid
flowchart TD
subgraph Hermes["HERMES AGENT"]
direction LR
Gateway["Gateway\n(Telegram)"] --> Agent["Agent\n(LLM)"] --> Tools["Tools\n(shell/fs)"]
Gateway --> GwHook["pre_gateway_dispatch"]
Agent --> ToolHook["pre_tool_call"]
Tools --> OutHook["transform_terminal_out"]
end

GwHook --> PasteGuard["Paste guard\nDetect raw secrets in user prompts\nAuto-vault"]
ToolHook --> Decloak["Decloak\nSubstitute @@SECRET@@ → real value\nat exec time"]
OutHook --> Scrub["Scrub output\nReplace real values with\nplaceholders before model"]
```

### Hooks
Expand Down Expand Up @@ -122,22 +114,15 @@ The flow is fully automatic — you mostly do nothing:

Hermes discovers the plugin via two mechanisms:

```
pip install prismor
Hermes auto-discovers
entry_point "hermes_agent.plugins" ◄── Prefer this
→ prismor.runtime.cloaking.hermes_plugin_entry
└── If not found (e.g. dev install):
┌───────────────────────────┐
│ Filesystem fallback │
│ ~/.hermes/plugins/ │
│ prismor-cloak/ │
│ plugin.yaml │
│ __init__.py │
└───────────────────────────┘
```mermaid
flowchart TD
Install["pip install prismor"] --> Discover["Hermes auto-discovers\nentry_point 'hermes_agent.plugins'"]
Discover -->|"Prefer this"| Entry["prismor.runtime.cloaking.hermes_plugin_entry"]
Discover -->|"If not found (e.g. dev install)"| Manifest

subgraph FS["Filesystem fallback — ~/.hermes/plugins/prismor-cloak/"]
Manifest["plugin.yaml"] --> Init["__init__.py"]
end
```

### Entry Point
Expand Down
Loading