@dp-pcs/ogp 0.8.3 → 0.9.1
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.
- package/README.md +14 -0
- package/dist/cli/config.d.ts +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +17 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/federation.d.ts +20 -3
- package/dist/cli/federation.d.ts.map +1 -1
- package/dist/cli/federation.js +131 -20
- package/dist/cli/federation.js.map +1 -1
- package/dist/cli/project.d.ts +12 -0
- package/dist/cli/project.d.ts.map +1 -1
- package/dist/cli/project.js +110 -2
- package/dist/cli/project.js.map +1 -1
- package/dist/cli/tunnel.d.ts +7 -1
- package/dist/cli/tunnel.d.ts.map +1 -1
- package/dist/cli/tunnel.js +12 -3
- package/dist/cli/tunnel.js.map +1 -1
- package/dist/cli.js +107 -21
- package/dist/cli.js.map +1 -1
- package/dist/daemon/message-handler.d.ts.map +1 -1
- package/dist/daemon/message-handler.js +73 -1
- package/dist/daemon/message-handler.js.map +1 -1
- package/dist/daemon/project-ownership.d.ts +47 -0
- package/dist/daemon/project-ownership.d.ts.map +1 -0
- package/dist/daemon/project-ownership.js +109 -0
- package/dist/daemon/project-ownership.js.map +1 -0
- package/dist/daemon/projects.d.ts +8 -0
- package/dist/daemon/projects.d.ts.map +1 -1
- package/dist/daemon/projects.js +89 -0
- package/dist/daemon/projects.js.map +1 -1
- package/dist/shared/meta-config.d.ts.map +1 -1
- package/dist/shared/meta-config.js +23 -9
- package/dist/shared/meta-config.js.map +1 -1
- package/docs/CLI-REFERENCE.md +38 -0
- package/docs/TRANSPORT-MODES-DESIGN.md +164 -0
- package/package.json +1 -1
- package/scripts/completion.bash +2 -2
- package/scripts/completion.zsh +4 -0
package/docs/CLI-REFERENCE.md
CHANGED
|
@@ -5,6 +5,7 @@ Complete command-line reference for OGP (Open Gateway Protocol).
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
7
7
|
- [Global Options](#global-options)
|
|
8
|
+
- [Environment Variables](#environment-variables)
|
|
8
9
|
- [Setup and Configuration](#setup-and-configuration)
|
|
9
10
|
- [Daemon Management](#daemon-management)
|
|
10
11
|
- [Federation Commands](#federation-commands)
|
|
@@ -49,6 +50,10 @@ ogp --for all status
|
|
|
49
50
|
- If multiple frameworks are configured and no default is set, prompts interactively
|
|
50
51
|
- If a default framework is set, uses default (can override with `--for`)
|
|
51
52
|
- `--for all` runs command on all enabled frameworks and aggregates output
|
|
53
|
+
- If the meta-registry is empty (no `ogp setup` was run) but `OGP_HOME` is set,
|
|
54
|
+
`--for <framework>` honors `OGP_HOME` and prints a warning instead of failing.
|
|
55
|
+
This is the common case in server/container deployments where the daemon is
|
|
56
|
+
launched by setting `OGP_HOME` directly. See [Environment Variables](#environment-variables).
|
|
52
57
|
|
|
53
58
|
### --help, -h
|
|
54
59
|
|
|
@@ -70,6 +75,39 @@ Shows OGP version.
|
|
|
70
75
|
ogp --version
|
|
71
76
|
```
|
|
72
77
|
|
|
78
|
+
## Environment Variables
|
|
79
|
+
|
|
80
|
+
OGP does **not** hardcode its storage location. The default is `~/.ogp`, but
|
|
81
|
+
every path is resolved at runtime and can be overridden via environment
|
|
82
|
+
variables. This is the supported way to run OGP in containers, on servers
|
|
83
|
+
(ECS/nginx), or anywhere `$HOME` is not where you want config to live — no code
|
|
84
|
+
changes or recompilation required.
|
|
85
|
+
|
|
86
|
+
| Variable | Overrides | Default |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| `OGP_HOME` | Per-framework data dir: `config.json`, `peers.json`, identity, keychain. **The daemon only needs this.** | `~/.ogp` |
|
|
89
|
+
| `OGP_META_HOME` | The multi-framework meta-registry (`config.json` listing frameworks for `--for`). | `~/.ogp-meta` |
|
|
90
|
+
|
|
91
|
+
**Server / container deployment (recommended):**
|
|
92
|
+
```bash
|
|
93
|
+
# Point both the daemon and the CLI at the same writable location.
|
|
94
|
+
export OGP_HOME=/data/ogp # or e.g. /home/node/.openclaw/.ogp
|
|
95
|
+
ogp start --background
|
|
96
|
+
ogp peers list # CLI inherits OGP_HOME, talks to the daemon
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Common pitfall:** If the daemon is launched with `OGP_HOME` set but you then
|
|
100
|
+
run `ogp --for openclaw ...`, the CLI looks up `openclaw` in the meta-registry
|
|
101
|
+
(`OGP_META_HOME`), which was never populated by an interactive `ogp setup`.
|
|
102
|
+
As of this version, `--for` falls back to `OGP_HOME` with a warning instead of
|
|
103
|
+
erroring. The clean fix is to **not pass `--for` on a single-home server** — just
|
|
104
|
+
export `OGP_HOME` and let every `ogp` invocation inherit it.
|
|
105
|
+
|
|
106
|
+
**$HOME mismatch:** If the daemon and CLI run under different users/`$HOME`
|
|
107
|
+
values (common in containers), the meta-registry can silently "not exist" for
|
|
108
|
+
one of them. Set `OGP_META_HOME` (and `OGP_HOME`) explicitly so both processes
|
|
109
|
+
resolve the same paths.
|
|
110
|
+
|
|
73
111
|
## Setup and Configuration
|
|
74
112
|
|
|
75
113
|
### ogp setup
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Transport Modes Design
|
|
2
|
+
|
|
3
|
+
**Status:** 🚧 Proposed — under review. The rendezvous registration schema change is adjacent to the Ed25519 trust model and should be reviewed carefully before merge.
|
|
4
|
+
|
|
5
|
+
**Date:** 2026-06-08
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
OGP's biggest adoption deterrent is the tunnel requirement. Today peers deliver
|
|
10
|
+
Ed25519-signed envelopes by **direct HTTP POST to each other's public
|
|
11
|
+
`gatewayUrl`**, and the rendezvous server is a pubkey→address directory that
|
|
12
|
+
hands back a raw `ip:port`. Even *with* rendezvous, a peer must be publicly
|
|
13
|
+
reachable — which is exactly the job the cloudflared/ngrok tunnel does.
|
|
14
|
+
|
|
15
|
+
The tunnel is **not a transport requirement — it's a reachability hack.** We want
|
|
16
|
+
to make reachability a *user choice*, so people who don't want to run a tunnel can
|
|
17
|
+
opt into a relay instead, without forcing anyone already on tunnels to change.
|
|
18
|
+
|
|
19
|
+
## Key insight that makes this safe
|
|
20
|
+
|
|
21
|
+
**OGP messages are already Ed25519-signed end-to-end.** Any relay/transport in the
|
|
22
|
+
middle is *untrusted by design* — it can see envelope metadata but cannot forge,
|
|
23
|
+
alter, or impersonate. This radically lowers the security bar for the transport
|
|
24
|
+
layer and makes "route through a relay" perfectly acceptable. This single fact is
|
|
25
|
+
what makes a pluggable transport possible without weakening the trust model.
|
|
26
|
+
|
|
27
|
+
## Goal
|
|
28
|
+
|
|
29
|
+
A per-user, per-daemon `transport` setting that lets each operator choose how their
|
|
30
|
+
daemon is reached, defaulting to **today's behavior** so no existing setup breaks:
|
|
31
|
+
|
|
32
|
+
- **`direct`** (default) — public `gatewayUrl` via tunnel / public IP / port-forward. Exactly what works today. Zero change for current users.
|
|
33
|
+
- **`relay`** — daemon holds a persistent outbound WebSocket to a relay; messages route peer→relay→peer. No inbound port, no tunnel. User picks *which* relay (ours by default, or a self-hosted one).
|
|
34
|
+
- **`iroh`** — daemon uses Iroh (QUIC). ~90% of pairs get a direct P2P connection; the rest fall back through a relay. E2E-encrypted regardless. Self-hostable relay. The deliberate pilot.
|
|
35
|
+
|
|
36
|
+
## User experience
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Default — nothing changes for existing users
|
|
40
|
+
ogp config get transport.mode # => direct
|
|
41
|
+
|
|
42
|
+
# Opt into relay (no tunnel needed)
|
|
43
|
+
ogp config set transport.mode relay
|
|
44
|
+
ogp config set transport.relay.url wss://relay.example.com/relay # default if omitted
|
|
45
|
+
|
|
46
|
+
# Power user / privacy: self-hosted relay
|
|
47
|
+
ogp config set transport.relay.url wss://relay.mycorp.internal
|
|
48
|
+
|
|
49
|
+
# Pilot iroh
|
|
50
|
+
ogp config set transport.mode iroh
|
|
51
|
+
ogp config set transport.iroh.relayUrl https://my-dedicated-relay # omit = public dev relays
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A mixed fleet works: each peer advertises *how* to reach it, and senders branch on
|
|
55
|
+
the **receiver's** advertised transport (see schema change below).
|
|
56
|
+
|
|
57
|
+
## Config shape
|
|
58
|
+
|
|
59
|
+
Add a `transport` block to `OGPConfig` (`src/shared/config.ts`). Absent ⇒ `direct`.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
export type TransportMode = 'direct' | 'relay' | 'iroh';
|
|
63
|
+
|
|
64
|
+
export interface TransportConfig {
|
|
65
|
+
mode: TransportMode; // default 'direct'
|
|
66
|
+
relay?: {
|
|
67
|
+
url: string; // websocket relay endpoint; default wss://<rendezvous>/relay
|
|
68
|
+
};
|
|
69
|
+
iroh?: {
|
|
70
|
+
relayUrl?: string; // dedicated/self-hosted iroh relay; omit = public dev relays
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// OGPConfig:
|
|
75
|
+
// transport?: TransportConfig;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## The keystone change — rendezvous advertises *how*, not just *where*
|
|
79
|
+
|
|
80
|
+
This is the one structural change everything else depends on, and the part that
|
|
81
|
+
**must be reviewed carefully before merge** (it sits next to the signed
|
|
82
|
+
registration / trust model).
|
|
83
|
+
|
|
84
|
+
Today the rendezvous `/register` stores `{ pubkey, ip, port, lastSeen }` and
|
|
85
|
+
`/peer/:pubkey` returns `{ pubkey, ip, port, lastSeen }`. We extend the registered
|
|
86
|
+
record with a **transport descriptor** so a sender knows which path to use:
|
|
87
|
+
|
|
88
|
+
```jsonc
|
|
89
|
+
// direct (default / backward compatible — missing descriptor ⇒ direct)
|
|
90
|
+
{ "transport": "direct", "gatewayUrl": "https://peer.example.com" }
|
|
91
|
+
|
|
92
|
+
// relay
|
|
93
|
+
{ "transport": "relay", "relayUrl": "wss://relay.example.com/relay" }
|
|
94
|
+
|
|
95
|
+
// iroh
|
|
96
|
+
{ "transport": "iroh", "nodeId": "<iroh-node-id>", "relayUrl": "https://..." }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Rules:
|
|
100
|
+
- **Additive & backward compatible.** A registration with no descriptor is treated
|
|
101
|
+
as `direct` with the existing `ip:port` / `gatewayUrl`. Old daemons keep working.
|
|
102
|
+
- The descriptor rides **inside the existing signed registration envelope**
|
|
103
|
+
(`signCanonical` over the inner payload) so the rendezvous can't be tricked into
|
|
104
|
+
advertising a transport the keyholder didn't choose. **This is the trust-model
|
|
105
|
+
touchpoint — review carefully before merge.**
|
|
106
|
+
- Senders branch delivery on the peer's advertised `transport`, not their own.
|
|
107
|
+
|
|
108
|
+
## Relay server (mode = `relay`)
|
|
109
|
+
|
|
110
|
+
Extends the existing rendezvous service (Node/Express on ECS Fargate). No new box.
|
|
111
|
+
|
|
112
|
+
- New `wss://<rendezvous>/relay` endpoint. Each daemon opens a **persistent
|
|
113
|
+
outbound** WebSocket and authenticates by signing a challenge with its Ed25519
|
|
114
|
+
key (proving pubkey ownership, same property as `/register`).
|
|
115
|
+
- Routing table: `pubkey → live socket`. To deliver, sender pushes
|
|
116
|
+
`{ to: pubkeyB, envelope }`; server forwards down B's socket. Optional
|
|
117
|
+
store-and-forward queue for offline peers, flushed on reconnect.
|
|
118
|
+
- **ECS/ALB gotcha (confirmed):** ALB idle timeout defaults to 60s, max 4000s. We
|
|
119
|
+
**must** send app-level WS ping/heartbeat (~30–50s) or idle sockets get dropped.
|
|
120
|
+
- **Horizontal scale:** one Node process handles tens of thousands of idle
|
|
121
|
+
sockets; past one Fargate task we need a shared routing table (Redis pub/sub) so
|
|
122
|
+
a message arriving on task-1 reaches a socket on task-2.
|
|
123
|
+
- Server stays **untrusted** — it sees envelopes but can't forge them (E2E Ed25519).
|
|
124
|
+
|
|
125
|
+
## Iroh (mode = `iroh`) — pilot notes
|
|
126
|
+
|
|
127
|
+
- QUIC, node-ID addressing. Relays do (1) NAT-traversal coordination and (2)
|
|
128
|
+
encrypted fallback; **relays cannot read traffic** (E2E). ~9/10 pairs get a
|
|
129
|
+
direct connection; traversal is deterministic once it works for a pair.
|
|
130
|
+
- Relays are **stateless/disposable** (no DB, no state migration, reconnect to any).
|
|
131
|
+
- **Cost/effort caveats:** Iroh is Rust; OGP is Node. Official **NAPI Node bindings**
|
|
132
|
+
exist (`iroh` npm), so it's a native-addon dependency with per-platform prebuilds,
|
|
133
|
+
not a full rewrite — but it *is* a new native dep for a daemon that ships daily.
|
|
134
|
+
Public relays are **dev/test only** (rate-limited, no SLA); production = dedicated
|
|
135
|
+
relays (self-hosted open-source binary from n0-computer, or n0's paid Iroh
|
|
136
|
+
Services). Addressing changes from URL → node ID, so the delivery path is rewired.
|
|
137
|
+
- Treat as **opt-in pilot**, not default. Once the transport descriptor exists,
|
|
138
|
+
iroh is "just another transport value," not a rewrite-or-nothing bet.
|
|
139
|
+
|
|
140
|
+
Sources: https://docs.iroh.computer/concepts/relays ,
|
|
141
|
+
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html
|
|
142
|
+
|
|
143
|
+
## Phased build plan
|
|
144
|
+
|
|
145
|
+
1. **Transport descriptor in register/lookup** (additive, backward compatible;
|
|
146
|
+
missing ⇒ `direct`). Unblocks everything, low risk. **Schema/trust touchpoint —
|
|
147
|
+
review carefully before merge.**
|
|
148
|
+
2. **`relay` mode** — WebSocket through rendezvous + signed-challenge auth +
|
|
149
|
+
ALB heartbeat. Lowest code; kills the tunnel requirement; opt-in dogfooding.
|
|
150
|
+
3. **`iroh` mode pilot** — once relay is proven, add iroh as another descriptor
|
|
151
|
+
value behind a dedicated/self-hosted relay.
|
|
152
|
+
|
|
153
|
+
## Hard rules / guardrails
|
|
154
|
+
|
|
155
|
+
- **Default stays `direct`** — never silently change how existing users' traffic moves.
|
|
156
|
+
- **No auto-deploy** of the rendezvous/relay server — changes are proposed and reviewed, not shipped automatically.
|
|
157
|
+
- **Registration-schema + relay-auth code requires careful review before merge** — it's adjacent to the Ed25519 trust model, which is the product.
|
|
158
|
+
- E2E Ed25519 signing is preserved in **every** mode; the relay is always untrusted.
|
|
159
|
+
|
|
160
|
+
## Non-goals (for now)
|
|
161
|
+
|
|
162
|
+
- Replacing direct mode. It stays as the privacy/no-third-party path.
|
|
163
|
+
- Picking iroh vs websocket-relay as the *single* answer. The point is choice +
|
|
164
|
+
real-world dogfooding before committing a default beyond `direct`.
|
package/package.json
CHANGED
package/scripts/completion.bash
CHANGED
|
@@ -61,7 +61,7 @@ _ogp_completion() {
|
|
|
61
61
|
# agent-comms subcommands
|
|
62
62
|
if [ "$cmd" = "agent-comms" ]; then
|
|
63
63
|
if [ $COMP_CWORD -eq 2 ]; then
|
|
64
|
-
opts="policies configure add-topic set-topic set-default remove-topic reset activity default logging"
|
|
64
|
+
opts="send policies configure add-topic set-topic set-default remove-topic reset activity default logging"
|
|
65
65
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
|
66
66
|
return 0
|
|
67
67
|
fi
|
|
@@ -116,7 +116,7 @@ _ogp_completion() {
|
|
|
116
116
|
# project subcommands
|
|
117
117
|
if [ "$cmd" = "project" ]; then
|
|
118
118
|
if [ $COMP_CWORD -eq 2 ]; then
|
|
119
|
-
opts="create join list remove contribute query status request-join send-contribution query-peer status-peer delete"
|
|
119
|
+
opts="create join list remove contribute query status request-join send-contribution query-peer status-peer delete add-owner claim-ownership owners"
|
|
120
120
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
|
121
121
|
return 0
|
|
122
122
|
fi
|
package/scripts/completion.zsh
CHANGED
|
@@ -238,6 +238,7 @@ _ogp_agent_comms() {
|
|
|
238
238
|
|
|
239
239
|
_arguments \
|
|
240
240
|
'1:subcommand:((
|
|
241
|
+
send\:"Send an agent-comms message to a peer (alias of federation agent)"
|
|
241
242
|
policies\:"Show response policies"
|
|
242
243
|
configure\:"Configure response policies"
|
|
243
244
|
add-topic\:"Add topic to peer response policy"
|
|
@@ -432,6 +433,9 @@ _ogp_project() {
|
|
|
432
433
|
query-peer\:"Query peer project contributions"
|
|
433
434
|
status-peer\:"Request project status from peer"
|
|
434
435
|
delete\:"Delete local project and all contributions"
|
|
436
|
+
add-owner\:"Grant ownership to a peer key (owners only)"
|
|
437
|
+
claim-ownership\:"Claim ownership of a pre-existing project (members only)"
|
|
438
|
+
owners\:"List the owners of a project"
|
|
435
439
|
))' \
|
|
436
440
|
'*::arg:->args'
|
|
437
441
|
|