Create docs/wiki/openchat-adapter.md
103657a4de0d jacobcole 2026-04-23 1 file
new file mode 100644
index 0000000..4e72a37
@@ -0,0 +1,87 @@
+---
+visibility: public
+---
+
+# OpenChat adapter (candidate third channel)
+
+**Status:** Deferred — [Stage D3](../plans/2026-04-23-initial-roadmap.md#d3-openchat-linq-adapter).
+
+## Premise
+
+picortex's `Channel` interface is shaped to Linq. If we teach OpenChat (`chat.globalbr.ai`) to speak the same dialect — inbound HMAC-signed webhooks, outbound `/api/partner/v3/*` surface, same 14 event types — then picortex gets a **third** channel "for free":
+
+1. Real Linq (iMessage, SMS)
+2. linq-sim (dev)
+3. **OpenChat-as-Linq** (Jacob's own app)
+
+The payoff: Jacob can test picortex end-to-end through OpenChat without needing Linq, and the OpenChat UI becomes a real client for picortex.
+
+## Current OpenChat surface (from research)
+
+- `/api/chat/conversations` (list / create / get / list-messages / send-message)
+- `/api/chat/contacts`
+- `/api/chat/users/by-email/:email`
+- `/api/chat/presence`
+- WebSocket at `/ws/chat` for real-time delivery
+- ~**40% overlap** with Linq's surface
+
+## Gap analysis
+
+| Linq feature | OpenChat today | Work |
+|---|---|---|
+| reactions | none | new schema + 2 routes + WS event + UI |
+| message edits | none | new route + WS event + UI state |
+| delivery / read receipts | partial (`presence`) | add message-status transitions |
+| typing indicator | none | WS event + throttle |
+| thread replies (`reply_to_message_id`) | none | schema + UI affordance |
+| participant add/remove after creation | none | new routes |
+| group rename event | none | new route |
+| HMAC webhook signing | none | new outbound emitter w/ retry + dedup |
+| outbound partner API (`/api/partner/v3/*`) | none | new adapter layer |
+
+## Two strategies
+
+### A. Adapter layer (recommended)
+
+Leave OpenChat's own API alone. Add `src/adapter/linq/` that translates:
+- OpenChat internal events → outbound HMAC-signed `/api/partner/v3/*` webhooks
+- Inbound `/api/partner/v3/sendMessage` calls → OpenChat's `postMessage` internal call
+
+**Pro:** OpenChat keeps its own identity. Adapter is isolated and replaceable.
+**Con:** Some behaviors (reactions, edits) don't exist in OpenChat yet — those are *real* features to add.
+
+### B. Native upgrade
+
+Rebuild OpenChat routes to match Linq names; make Linq the primary internal shape.
+
+**Pro:** Simpler long-term.
+**Con:** Disruptive; breaks existing OpenChat clients; not in scope for picortex.
+
+**Decision:** adapter layer. Even with adapter, the missing features (reactions, edits, typing, threads) must still be built. But the naming stays OpenChat-native.
+
+## Rough effort
+
+- Reactions (schema + routes + WS + UI): ~1 day (already planned in `OpenChat-yg8`-adjacent work)
+- Outbound HMAC webhook emitter + retry + dedup: ~2 days
+- Edits + read receipts + typing: ~2-3 days
+- Thread replies: ~1 day
+- `/api/partner/v3/*` adapter routes: ~1-2 days
+- End-to-end tests against linq-sim shape: ~1-2 days
+- **Total: 1-2 weeks focused work**
+
+## Decision gate for picortex v0.1
+
+**Defer.** v0.1 ships with real Linq + linq-sim. OpenChat adapter lives in `~/code/openchat` on its own timeline. picortex consumes it once available.
+
+## Repo status (2026-04-23)
+
+- `tmad4000/openchat` and `tmad4000/OpenChat` on GitHub are **stale Next.js scaffolds from June 2023** — not the live service.
+- Deployed openchat at `chat.globalbr.ai` on Lightsail is `name: "openchat" v0.1.0, workspaces: [server, client]` but has **no git remote configured** (`/opt/openchat/.git/config`).
+- **Open question for Jacob:** where does the deployed openchat's source live? Possibilities: (a) unpublished private repo; (b) only exists on the Lightsail server + Jacob's M3 laptop; (c) different GitHub name we haven't found. This must be resolved before D3 can start.
+- Until resolved, D3 work is blocked on repo discovery. Candidate action: `cd ~/code/openchat` on M3 laptop and `git remote -v`.
+
+## Related
+
+- [ADR-0004 — Linq as primary channel](../adrs/0004-linq-primary-channel.md)
+- Research: second agent's openchat report (this session)
+- Beads: `picortex-D3-*` (created when D3 kicks off)
\ No newline at end of file