@dp-pcs/ogp 0.7.2 → 0.8.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.
Files changed (63) hide show
  1. package/README.md +59 -12
  2. package/dist/cli/config.d.ts +4 -0
  3. package/dist/cli/config.d.ts.map +1 -1
  4. package/dist/cli/config.js +45 -2
  5. package/dist/cli/config.js.map +1 -1
  6. package/dist/cli/expose.d.ts +4 -1
  7. package/dist/cli/expose.d.ts.map +1 -1
  8. package/dist/cli/expose.js +7 -106
  9. package/dist/cli/expose.js.map +1 -1
  10. package/dist/cli/install.d.ts +1 -0
  11. package/dist/cli/install.d.ts.map +1 -1
  12. package/dist/cli/install.js +8 -2
  13. package/dist/cli/install.js.map +1 -1
  14. package/dist/cli/project.d.ts +24 -0
  15. package/dist/cli/project.d.ts.map +1 -1
  16. package/dist/cli/project.js +68 -15
  17. package/dist/cli/project.js.map +1 -1
  18. package/dist/cli/tunnel.d.ts +65 -0
  19. package/dist/cli/tunnel.d.ts.map +1 -0
  20. package/dist/cli/tunnel.js +413 -0
  21. package/dist/cli/tunnel.js.map +1 -0
  22. package/dist/cli.js +21 -8
  23. package/dist/cli.js.map +1 -1
  24. package/dist/daemon/contribution-signing.d.ts +49 -0
  25. package/dist/daemon/contribution-signing.d.ts.map +1 -0
  26. package/dist/daemon/contribution-signing.js +91 -0
  27. package/dist/daemon/contribution-signing.js.map +1 -0
  28. package/dist/daemon/message-handler.js +41 -18
  29. package/dist/daemon/message-handler.js.map +1 -1
  30. package/dist/daemon/openclaw-bridge.d.ts +6 -0
  31. package/dist/daemon/openclaw-bridge.d.ts.map +1 -1
  32. package/dist/daemon/openclaw-bridge.js +27 -12
  33. package/dist/daemon/openclaw-bridge.js.map +1 -1
  34. package/dist/daemon/peers.d.ts.map +1 -1
  35. package/dist/daemon/peers.js +19 -0
  36. package/dist/daemon/peers.js.map +1 -1
  37. package/dist/daemon/projects.d.ts +20 -0
  38. package/dist/daemon/projects.d.ts.map +1 -1
  39. package/dist/daemon/projects.js +70 -0
  40. package/dist/daemon/projects.js.map +1 -1
  41. package/dist/daemon/server.d.ts.map +1 -1
  42. package/dist/daemon/server.js +43 -2
  43. package/dist/daemon/server.js.map +1 -1
  44. package/dist/daemon/state-lock.d.ts +23 -0
  45. package/dist/daemon/state-lock.d.ts.map +1 -0
  46. package/dist/daemon/state-lock.js +115 -0
  47. package/dist/daemon/state-lock.js.map +1 -0
  48. package/package.json +13 -3
  49. package/scripts/completion.bash +25 -6
  50. package/scripts/completion.zsh +26 -8
  51. package/skills/ogp-expose/SKILL.md +40 -10
  52. package/docs/RC1-FEDERATION-TEST-CHECKLIST.md +0 -477
  53. package/docs/case-studies/CRASH_RESOLUTION_20260407.md +0 -190
  54. package/docs/case-studies/OpenClaw_Hermes_Status_Report_20260407.md +0 -142
  55. package/docs/case-studies/OpenClaw_Stability_Fix_Summary.md +0 -209
  56. package/docs/case-studies/README.md +0 -40
  57. package/docs/case-studies/crash_observations.md +0 -250
  58. package/docs/nat-hole-punch-spike.md +0 -399
  59. package/docs/project-intent-testing.md +0 -97
  60. package/scripts/render-ogp-overview-video.mjs +0 -454
  61. package/scripts/test-migration-execute.js +0 -74
  62. package/scripts/test-migration.js +0 -42
  63. package/scripts/test-project-intents.mjs +0 -614
@@ -1,399 +0,0 @@
1
- # NAT Hole Punching Research Spike for OGP
2
-
3
- **Date:** 2026-03-30
4
- **Status:** Research Complete — No Implementation
5
- **Goal:** Evaluate UDP NAT hole punching to enable home users behind NAT to federate without port forwarding or tunnels
6
-
7
- ---
8
-
9
- ## 🎯 Recommendation: DEFER Implementation
10
-
11
- **Do NOT implement UDP hole punching for OGP at this time.**
12
-
13
- ### Rationale
14
-
15
- 1. **HTTP fallback already works** — OGP's rendezvous server + HTTP messaging provides zero-config federation for 95%+ of residential users via UPnP, public IP detection, and tunnel services (ngrok/Cloudflare)
16
-
17
- 2. **Symmetric NAT is a deal-breaker** — UDP hole punching fails for ~15% of residential users behind symmetric NAT, requiring a TURN relay server (expensive, complex, defeats the purpose of P2P)
18
-
19
- 3. **High implementation complexity** — Adding UDP transport is a major undertaking (S → L complexity) with marginal benefit over existing HTTP solution
20
-
21
- 4. **TCP already traverses NAT** — HTTP over TCP is already NAT-friendly and works behind most residential routers without special handling
22
-
23
- 5. **No clear user pain point** — Users aren't blocked by the current HTTP approach; they use rendezvous server or tunnels successfully
24
-
25
- ### If User Demand Changes
26
-
27
- If home users report widespread federation issues due to NAT (not currently the case), revisit this decision. Priority order:
28
-
29
- 1. **Improve HTTP rendezvous** — Add TURN-style relay for HTTP (simpler than UDP hole punching)
30
- 2. **Integrate tunnel services** — Embed ngrok/Cloudflare SDK for automatic tunnel setup
31
- 3. **UDP hole punching** — Only if HTTP solutions prove insufficient (unlikely)
32
-
33
- ---
34
-
35
- ## 📊 Library Comparison
36
-
37
- ### Evaluated Node.js STUN/UDP Libraries
38
-
39
- | Library | Version | Last Updated | Weekly DLs | TS Support | License | Status | Verdict |
40
- |---------|---------|--------------|------------|------------|---------|--------|---------|
41
- | **stun** (nodertc) | 2.1.0 | 6 years ago | Low | ❌ No | MIT | Unmaintained | ❌ Too old |
42
- | **node-stun** | 0.1.2 | 8 years ago | Minimal | ❌ No | Unknown | Abandoned | ❌ Abandoned |
43
- | **werift** | 0.22.2 | 6 months ago | 29 dependents | ✅ Yes | MIT | Active | ⚠️ Overkill (full WebRTC) |
44
- | **udp-hole-puncher** | 1.1.0 | 9 months ago | None | ❌ No | MIT | Stale | ❌ No adoption |
45
- | **xkore** | 1.0.1 | 2 months ago | 1 dependent | Unknown | ISC | New/unproven | ⚠️ Too new |
46
- | **nat-traversal** | Latest | Unknown | Low | ❌ No | Unknown | Active | ⚠️ TCP relay (not UDP hole punch) |
47
-
48
- ### Analysis
49
-
50
- **No clear winner.** The ecosystem is fragmented:
51
-
52
- - **Old libraries** (stun, node-stun) are unmaintained and lack TypeScript
53
- - **New libraries** (xkore) are unproven with zero adoption
54
- - **WebRTC stacks** (werift) include hole punching but bring massive complexity (ICE, DTLS, SRTP, SDP negotiation) — massive overkill for simple peer-to-peer messaging
55
- - **Purpose-built hole punchers** (udp-hole-puncher) have zero community adoption
56
-
57
- **Best option if forced to implement:** Use the **nodertc/stun** library for basic STUN client functionality and implement custom UDP hole punching logic (no library does it well). This is 80% of the work anyway.
58
-
59
- ---
60
-
61
- ## 🏗️ OGP Architecture Analysis
62
-
63
- ### Current HTTP Architecture
64
-
65
- ```
66
- ┌─────────────────────────────────────────────────────────────────┐
67
- │ OGP Daemon (src/daemon/server.ts) │
68
- │ - Express HTTP server on port 18790 │
69
- │ - Endpoints: /federation/request, /federation/message, etc. │
70
- │ - Rendezvous registration (POST /register every 30s) │
71
- │ - Peer lookup (GET /peer/:pubkey) │
72
- └─────────────────────────────────────────────────────────────────┘
73
-
74
- │ HTTP/JSON + RSA signatures
75
-
76
- ┌─────────────────────────────────────────────────────────────────┐
77
- │ Rendezvous Server (rendezvous.elelem.expert) │
78
- │ - HTTPS server (Express on port 3000 default) │
79
- │ - Stores: { pubkey, ip, port, timestamp } with 90s TTL │
80
- │ - Never touches message content (privacy preserved) │
81
- └─────────────────────────────────────────────────────────────────┘
82
- ```
83
-
84
- **Key observation:** OGP daemon is a single-port HTTP server. It does NOT have:
85
- - UDP socket handling
86
- - STUN client/server logic
87
- - ICE candidate gathering
88
- - Hole punching coordination
89
-
90
- ### Integration Points (If Implemented)
91
-
92
- To add UDP hole punching WITHOUT breaking HTTP:
93
-
94
- 1. **Dual transport layer** — Run HTTP server (18790) AND UDP socket (18791) concurrently
95
- 2. **Rendezvous server changes** — Add STUN endpoint on UDP port, store both TCP port (18790) and UDP port (18791) per peer
96
- 3. **Connection attempt sequence** — Try UDP hole punch first, fall back to HTTP if fails (timeout after 3-5s)
97
- 4. **Protocol negotiation** — Peers must agree which transport to use via rendezvous server
98
-
99
- **Critical constraint:** Cannot break existing HTTP federation (v0.2.0 protocol). UDP must be additive, not replacement.
100
-
101
- ---
102
-
103
- ## 🔬 NAT Traversal Feasibility
104
-
105
- ### NAT Type Distribution (Estimated)
106
-
107
- | NAT Type | % of Residential ISPs | UDP Hole Punch Success Rate | Notes |
108
- |----------|----------------------|---------------------------|-------|
109
- | Full Cone | ~5-10% | >95% | Rare in modern routers |
110
- | Restricted Cone | ~40-50% | >95% | Most common, hole punching works |
111
- | Port-Restricted Cone | ~25-35% | ~80% | Common, mostly works |
112
- | Symmetric NAT | ~10-15% | <10% | **Requires TURN relay** |
113
-
114
- **Sources:**
115
- - [Academic research (IEEE)](https://ieeexplore.ieee.org/document/7021753/)
116
- - [NAT usage studies (Springer)](https://link.springer.com/chapter/10.1007/978-3-642-19260-9_4)
117
- - [Tailscale's NAT traversal analysis](https://tailscale.com/blog/how-nat-traversal-works)
118
-
119
- **Key finding:** UDP hole punching succeeds for ~82-85% of peers in cone NAT scenarios. The remaining ~15% (symmetric NAT) require a TURN relay server.
120
-
121
- ### TURN Relay Server Requirements
122
-
123
- For symmetric NAT, peers cannot establish direct UDP connections. A TURN relay server is required:
124
-
125
- - **Server:** [Coturn](https://github.com/coturn/coturn) (most popular open-source TURN server)
126
- - **Hosting cost:** $20-50/month for small deployments (bandwidth-heavy)
127
- - **Implementation effort:** Medium (2-3 weeks for integration + testing)
128
- - **User experience:** Degrades to relay (higher latency, costs money)
129
-
130
- **This defeats the purpose of P2P.** If we're relaying 15% of traffic, why not just use HTTP for everyone?
131
-
132
- ---
133
-
134
- ## 📋 Proposed Protocol Flow (If Implemented)
135
-
136
- **NOTE:** This is theoretical. Do NOT implement without re-evaluating user need.
137
-
138
- ### Step 1: Rendezvous Registration (Startup)
139
-
140
- ```
141
- OGP Daemon A Rendezvous Server
142
- │ │
143
- ├─ POST /register ──────────────▶ Store:
144
- │ { │ - pubkey: "abc123..."
145
- │ pubkey: "abc123...", │ - tcp_ip: "1.2.3.4"
146
- │ tcp_port: 18790, │ - tcp_port: 18790
147
- │ udp_port: 18791, │ - udp_ip: "1.2.3.4"
148
- │ timestamp: 1234567890 │ - udp_port: 18791
149
- │ } │ - timestamp: 1234567890
150
- │◀─ 200 OK ─────────────────────┤ TTL: 90 seconds
151
- ```
152
-
153
- ### Step 2: STUN Binding Request (Detect Public IP/Port)
154
-
155
- ```
156
- OGP Daemon A STUN Server (on rendezvous.elelem.expert:3478 UDP)
157
- │ │
158
- ├─ STUN Binding Request ────────▶
159
- │ (from local UDP port 18791) │
160
- │ │
161
- │◀─ STUN Binding Response ──────┤
162
- │ { │
163
- │ public_ip: "1.2.3.4", │
164
- │ public_port: 54321 │ <-- NAT assigned external port
165
- │ } │
166
- ```
167
-
168
- ### Step 3: Peer Connection Attempt
169
-
170
- ```
171
- OGP Daemon A Rendezvous Server OGP Daemon B
172
- │ │ │
173
- ├─ GET /peer/xyz789... ─────────▶ │
174
- │◀─ 200 OK ───────────────────┤ │
175
- │ { │ │
176
- │ tcp_ip: "5.6.7.8", │ │
177
- │ tcp_port: 18790, │ │
178
- │ udp_ip: "5.6.7.8", │ │
179
- │ udp_port: 65432 │ │
180
- │ } │ │
181
- │ │ │
182
- ├─ Try UDP hole punch ───────────────────────────────────────▶
183
- │ (both send UDP packets simultaneously) │
184
- │ │ │
185
- │◀─ UDP connection established (if cone NAT) ─────────────────┤
186
- │ │ │
187
- │ OR (if symmetric NAT) │ │
188
- │ │ │
189
- ├─ Fall back to HTTP ────────────────────────────────────────▶
190
- │ POST /federation/message │ │
191
- ```
192
-
193
- ### Step 4: Fallback Relay (Symmetric NAT)
194
-
195
- ```
196
- OGP Daemon A TURN Relay Server OGP Daemon B
197
- │ │ │
198
- ├─ Allocate relay ──────────────▶ │
199
- │◀─ Relay address ───────────────┤ │
200
- │ (relay_ip: 9.10.11.12:4000) │ │
201
- │ │ │
202
- ├─ Send to relay ───────────────▶ │
203
- │ ├─ Forward to B ───────────────▶
204
- │ │ │
205
- │◀─ Response from B ─────────────┤◀─ Send via relay ───────────┤
206
- ```
207
-
208
- **Latency impact:**
209
- - Direct UDP: ~10-50ms
210
- - HTTP over TCP: ~20-100ms
211
- - TURN relay: ~50-200ms (double hop)
212
-
213
- ---
214
-
215
- ## 🚧 Implementation Complexity
216
-
217
- ### Estimated Effort: **LARGE (L)**
218
-
219
- **Components to implement:**
220
-
221
- 1. **STUN client** (1-2 weeks)
222
- - Bind to UDP socket (18791)
223
- - Send STUN Binding Request to discover public IP/port
224
- - Parse STUN Binding Response (RFC 5389 / RFC 8489)
225
- - Handle retries and timeouts
226
-
227
- 2. **UDP hole punching logic** (2-3 weeks)
228
- - Coordinate simultaneous send between peers (timing is critical)
229
- - NAT type detection (symmetric vs cone)
230
- - Connection attempt timeout and fallback
231
-
232
- 3. **Rendezvous server updates** (1 week)
233
- - Add STUN endpoint on UDP port 3478
234
- - Store UDP port alongside TCP port in peer registry
235
- - Handle dual-transport lookups
236
-
237
- 4. **TURN relay integration** (2-3 weeks)
238
- - Deploy Coturn server (or use public TURN service)
239
- - Implement TURN client in OGP daemon
240
- - Relay allocation and authentication
241
-
242
- 5. **Dual transport coordination** (1 week)
243
- - Try UDP first, fall back to HTTP
244
- - Protocol negotiation handshake
245
- - Handle mixed scenarios (Peer A has UDP, Peer B HTTP-only)
246
-
247
- 6. **Testing matrix** (2-3 weeks)
248
- - Test all NAT type combinations (4x4 = 16 scenarios)
249
- - Simulate symmetric NAT, firewall rules, packet loss
250
- - Validate fallback paths work reliably
251
-
252
- **Total estimated effort:** 9-13 weeks (2-3 months)
253
-
254
- **Risk factors:**
255
- - NAT behavior is unpredictable (ISPs change router configs)
256
- - Timing synchronization issues (hole punching is timing-sensitive)
257
- - TURN relay costs and maintenance burden
258
- - Breaking changes to existing HTTP federation (backward compatibility risk)
259
-
260
- ---
261
-
262
- ## ⚠️ Risks and Unknowns
263
-
264
- ### 1. Symmetric NAT Prevalence
265
-
266
- **Unknown:** What % of OGP users are actually behind symmetric NAT?
267
-
268
- - Industry estimates: ~10-15% residential, ~40% cellular/CGN
269
- - OGP user base: Unknown (no telemetry data)
270
- - **Mitigation:** Add telemetry to measure NAT type distribution before implementing
271
-
272
- ### 2. TURN Relay Costs
273
-
274
- **Unknown:** How much bandwidth will relayed traffic consume?
275
-
276
- - TURN servers charge by bandwidth (not connections)
277
- - If 15% of traffic routes through relay, costs scale with user growth
278
- - **Mitigation:** Self-host Coturn or use public TURN services (rate-limited, unreliable)
279
-
280
- ### 3. Firewall Interference
281
-
282
- **Unknown:** Do corporate/school firewalls block UDP port 18791?
283
-
284
- - Many networks whitelist HTTP (80/443) but block arbitrary UDP ports
285
- - UDP hole punching may fail even with cone NAT due to firewall rules
286
- - **Mitigation:** Fallback to HTTP (already implemented), so no user impact
287
-
288
- ### 4. IPv6 Considerations
289
-
290
- **Unknown:** Does UDP hole punching work differently on IPv6?
291
-
292
- - IPv6 has no NAT in theory, but many ISPs still use CGN (Carrier-Grade NAT)
293
- - STUN/TURN specs support IPv6, but library support varies
294
- - **Mitigation:** Focus on IPv4 first, add IPv6 later if needed
295
-
296
- ### 5. Mobile/Tethering Scenarios
297
-
298
- **Unknown:** Do mobile hotspots (phone tethering) use symmetric NAT?
299
-
300
- - Cellular networks often use symmetric NAT (40%+ based on research)
301
- - Mobile users may be disproportionately blocked by UDP hole punching
302
- - **Mitigation:** HTTP fallback works fine for mobile users
303
-
304
- ### 6. Library Ecosystem Immaturity
305
-
306
- **Risk:** No battle-tested Node.js library for UDP hole punching exists
307
-
308
- - Would need to implement custom logic on top of basic STUN client
309
- - Debugging NAT traversal issues is notoriously difficult
310
- - **Mitigation:** Use werift (WebRTC stack) despite complexity, or write custom implementation
311
-
312
- ---
313
-
314
- ## 🔗 References
315
-
316
- ### Research Papers
317
- - [Peer-to-Peer Communication Across NATs (Bryan Ford)](https://pdos.csail.mit.edu/papers/p2pnat.pdf)
318
- - [UDP Hole Punching - Wikipedia](https://en.wikipedia.org/wiki/UDP_hole_punching)
319
- - [A New Method for Symmetric NAT Traversal](https://www.researchgate.net/publication/228411948_A_New_Method_for_Symmetric_NAT_Traversal_in_UDP_and_TCP)
320
-
321
- ### Implementation Guides
322
- - [How NAT Traversal Works (Tailscale)](https://tailscale.com/blog/how-nat-traversal-works)
323
- - [NAT Traversal Visual Guide (DEV Community)](https://dev.to/dev-dhanushkumar/nat-traversal-a-visual-guide-to-udp-hole-punching-1936)
324
- - [Understanding NAT Types (DH2i)](https://support.dh2i.com/docs/Archive/kbs/general/understanding-different-nat-types-and-hole-punching/)
325
-
326
- ### Libraries and Tools
327
- - [nodertc/stun (GitHub)](https://github.com/nodertc/stun) — RFC 5389 STUN client/server
328
- - [werift (npm)](https://www.npmjs.com/package/werift) — WebRTC stack for TypeScript/Node.js
329
- - [udp-hole-puncher (npm)](https://www.npmjs.com/package/udp-hole-puncher) — Dedicated hole punching library
330
- - [xkore (npm)](https://www.npmjs.com/search?q=nat+traversal) — Newest NAT traversal library (2 months old)
331
- - [coturn (GitHub)](https://github.com/coturn/coturn) — Open-source TURN server
332
-
333
- ### STUN/TURN Standards
334
- - [RFC 5389: Session Traversal Utilities for NAT (STUN)](https://www.rfc-editor.org/rfc/rfc5389.html)
335
- - [RFC 8489: STUN (obsoletes RFC 5389)](https://www.rfc-editor.org/rfc/rfc8489.html)
336
- - [RFC 5766: Traversal Using Relays around NAT (TURN)](https://www.rfc-editor.org/rfc/rfc5766)
337
- - [RFC 8656: TURN (obsoletes RFC 5766)](https://datatracker.ietf.org/doc/rfc8656/)
338
-
339
- ### Deployment Resources
340
- - [Coturn Setup Guide (Gabriel Tanner)](https://gabrieltanner.org/blog/turn-server/)
341
- - [WebRTC STUN Server Integration (VideoSDK)](https://www.videosdk.live/developer-hub/stun-turn-server/webrtc-stun-server)
342
- - [STUN/TURN Server in Azure (Microsoft)](https://learn.microsoft.com/en-us/gaming/azure/reference-architectures/stun-turn-server-in-azure)
343
-
344
- ---
345
-
346
- ## 🎬 Next Steps (If Reconsidered)
347
-
348
- **Do NOT proceed with implementation until:**
349
-
350
- 1. **User research** — Survey OGP users: Are they blocked by NAT? What % use tunnels vs direct IP?
351
- 2. **Telemetry** — Add NAT type detection to OGP daemon, collect anonymous stats for 30 days
352
- 3. **Cost analysis** — Estimate TURN relay costs based on actual traffic patterns
353
- 4. **Prototype** — Build minimal UDP hole punch prototype (no TURN) and test with 10-20 users
354
- 5. **Decision point** — If >50% of users benefit AND TURN costs are acceptable, proceed with full implementation
355
-
356
- **Until then:** Focus on improving HTTP rendezvous server reliability and user experience.
357
-
358
- ---
359
-
360
- ## Appendix: NAT Type Detection
361
-
362
- For future reference, here's how to detect NAT type using STUN:
363
-
364
- ```typescript
365
- import dgram from 'dgram';
366
-
367
- async function detectNATType(): Promise<'full-cone' | 'restricted' | 'port-restricted' | 'symmetric'> {
368
- const socket = dgram.createSocket('udp4');
369
-
370
- // Test 1: Basic STUN binding to STUN server A
371
- const { ip: publicIP1, port: publicPort1 } = await stunBinding(socket, 'stun.l.google.com', 19302);
372
-
373
- // Test 2: STUN binding to STUN server B (different IP)
374
- const { ip: publicIP2, port: publicPort2 } = await stunBinding(socket, 'stun1.l.google.com', 19302);
375
-
376
- // If public ports differ, it's symmetric NAT
377
- if (publicPort1 !== publicPort2) {
378
- return 'symmetric';
379
- }
380
-
381
- // Test 3: Request STUN server to respond from different port
382
- const respondsFromDifferentPort = await stunBindingWithPortChange(socket, 'stun.l.google.com', 19302);
383
-
384
- if (respondsFromDifferentPort) {
385
- return 'full-cone'; // Accepts packets from any IP:port
386
- }
387
-
388
- // Test 4: Request response from different IP
389
- const respondsFromDifferentIP = await stunBindingWithIPChange(socket, 'stun.l.google.com', 19302);
390
-
391
- if (respondsFromDifferentIP) {
392
- return 'restricted'; // Accepts packets from any port on same IP
393
- }
394
-
395
- return 'port-restricted'; // Only accepts packets from same IP:port
396
- }
397
- ```
398
-
399
- **Note:** This is pseudo-code. Actual implementation requires RFC 5780 (NAT Behavior Discovery).
@@ -1,97 +0,0 @@
1
- # Project Intent Testing
2
-
3
- This repo now includes a runnable local project-intent harness:
4
-
5
- ```bash
6
- npm run test:project-intents
7
- ```
8
-
9
- The harness creates two isolated local gateways with separate `OGP_HOME` directories, federates them over localhost, and exercises the real project commands:
10
-
11
- - `federation request`
12
- - `federation approve`
13
- - `project create`
14
- - `project contribute --local-only`
15
- - `project request-join`
16
- - `project send-contribution`
17
- - `project query-peer`
18
- - `project status-peer`
19
-
20
- ## What It Verifies
21
-
22
- The automated run checks these behaviors:
23
-
24
- 1. Two local daemons can boot independently.
25
- 2. Federation approval completes between them.
26
- 3. The project owner can create a local project and persist local contributions.
27
- 4. A non-member peer cannot query the project before joining.
28
- 5. The peer can join the project through `project.join`.
29
- 6. The joined peer can send a remote contribution through `project.contribute`.
30
- 7. The joined peer can query the owner project through `project.query`.
31
- 8. The status request path for `project.status` succeeds at the transport level.
32
-
33
- ## Useful Variants
34
-
35
- Keep the temp state and logs for inspection:
36
-
37
- ```bash
38
- npm run test:project-intents -- --keep-state
39
- ```
40
-
41
- Use a custom root or ports:
42
-
43
- ```bash
44
- npm run test:project-intents -- \
45
- --root /tmp/ogp-project-intent-test \
46
- --alpha-port 18990 \
47
- --beta-port 18991
48
- ```
49
-
50
- Skip the TypeScript rebuild when `dist/` is already current:
51
-
52
- ```bash
53
- npm run test:project-intents -- --skip-build
54
- ```
55
-
56
- ## Manual Checks
57
-
58
- If you want to replay the flow by hand, the harness prints the exact commands it used. These are the most valuable checks:
59
-
60
- 1. Membership isolation:
61
- `project query-peer` should fail before `project request-join`.
62
- 2. Membership grant:
63
- `project request-join` should create or update the project on the requester and add the remote member on the owner.
64
- 3. Data flow:
65
- `project send-contribution` should create a new contribution on the owner gateway.
66
- 4. Remote visibility:
67
- `project query-peer` should return the contribution after join succeeds.
68
- 5. Local persistence:
69
- `projects.json` under each `OGP_HOME` should reflect the expected project and topic state.
70
-
71
- ## Interpreting Success
72
-
73
- Project intents are working if all of the following are true:
74
-
75
- - both daemons answer `/.well-known/ogp`
76
- - both peers end up `approved` in `peers.json`
77
- - the owner `projects.json` contains the remote member after join
78
- - the owner `projects.json` contains the remote contribution after send
79
- - pre-join query fails and post-join query succeeds
80
-
81
- ## Known Testing Nuance
82
-
83
- `project status-peer` currently confirms that the request was sent, but it is not the best content-verification command because the CLI does not format the returned status payload. Treat it as a transport-path check, and use `project query-peer`, `project status`, `projects.json`, and daemon logs for stronger validation.
84
-
85
- For controlled runs, `project contribute --local-only` is still useful when you want to inspect local state before any federation traffic. The default auto-sync path now limits fan-out to approved peers who are explicit members of the project.
86
-
87
- ## File Transfer
88
-
89
- OGP project intents do not currently implement first-class file transfer. Small structured metadata is fine, but real file movement would need explicit protocol support such as:
90
-
91
- - file manifests with name, size, MIME type, and hash
92
- - signed download URLs
93
- - chunking or streaming for larger payloads
94
- - size limits and approval controls
95
- - storage and retention rules
96
-
97
- For now, the practical pattern is to transfer references, hashes, and URLs through project intents rather than raw file contents.