docs(handoff): 2026-05-02 evening — v1.6.x + v1.7.0 demo cut state
Companion to the morning handoff. Captures the 12 commits shipped this evening, live deployment status, the CLI/UI surface gap, three known risks (chiefly: mentions query depends on plaintext-base64 ciphertext + crashes on non-UTF8 bytes), and three branches for the next session ranked by leverage: record the demo, wire CLI verbs to the new endpoints, then v0.3.0 per-topic encryption. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
155
.artifacts/specs/2026-05-02-handoff-evening.md
Normal file
155
.artifacts/specs/2026-05-02-handoff-evening.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# claudemesh handoff — 2026-05-02 (evening)
|
||||
|
||||
Companion to the morning handoff (`2026-05-02-handoff.md`). Captures
|
||||
what shipped through the v1.6.x patch line and the v1.7.0 demo cut.
|
||||
Read before the next session.
|
||||
|
||||
---
|
||||
|
||||
## What shipped this evening
|
||||
|
||||
### v1.6.x patch line — closed except bridge smoke test
|
||||
|
||||
| Feature | Endpoint / file | Commit |
|
||||
|---|---|---|
|
||||
| SSE topic stream | `GET /api/v1/topics/:name/stream` | `7e71a61` |
|
||||
| Unread counts | `PATCH /v1/topics/:name/read`, `unread` on `GET /v1/topics` | `a80eb6f` |
|
||||
| Mesh-card unread badges | `apps/web/src/app/[locale]/dashboard/(user)/page.tsx` | `541440c` |
|
||||
| Member sidebar | `GET /v1/members`, chat panel right rail | `a75483b` |
|
||||
| SSE 4xx-stop fix | `apps/web/src/modules/mesh/topic-chat-panel.tsx` | `7af61e1` |
|
||||
| Humans-as-peers | `GET /v1/peers` includes recent apikey users | `f4601f4` |
|
||||
|
||||
### v1.7.0 demo cut — 4 of 5 items shipped
|
||||
|
||||
| Item | Code | Commit |
|
||||
|---|---|---|
|
||||
| Member sidebar in chat | `apps/web/src/modules/mesh/topic-chat-panel.tsx` (+sidebar) | `a75483b` |
|
||||
| Topic search + autocomplete | Same file (+ search toggle, mention dropdown, clay highlight) | `35a289b`, `00c25d9` |
|
||||
| Notification feed | `MentionsSection` on universe + `GET /v1/notifications` | `a9160a0` |
|
||||
| Public blog post | `apps/web/src/app/[locale]/(marketing)/blog/agents-and-humans-same-chat/` | `69cf39b` |
|
||||
| Demo video script | `docs/demo-v1.7.0-script.md` (90s, 5 scenes) | `69cf39b` |
|
||||
| Marketing site refresh | Timeline next-block updated | `a2ab7de` |
|
||||
| **Recorded demo video** | — | **TODO (needs human + iTerm + Chrome)** |
|
||||
| **Marketing screenshots** | — | **TODO (needs Chrome session)** |
|
||||
|
||||
### Roadmap state
|
||||
|
||||
- `docs/roadmap.md` updated. v1.6.x marks every endpoint shipped except
|
||||
bridge smoke test. v1.7.0 marks sidebar/mentions/search/feed/blog
|
||||
shipped; recording + screenshots open.
|
||||
- v2.0.0 (daemon redesign) and v0.3.0 (operator layer / per-topic
|
||||
encryption) untouched — both still architectural specs.
|
||||
|
||||
---
|
||||
|
||||
## Live status
|
||||
|
||||
- **Broker** (`wss://ic.claudemesh.com/ws`): autodeployed via Coolify
|
||||
off the gitea-vps push. The custom migration runner from earlier
|
||||
this session is the one moving migrations forward. No new
|
||||
migrations shipped today — all v1.6.x work was code-only against
|
||||
the v0.2.0 schema.
|
||||
- **Web** (`claudemesh.com`): autodeployed via Vercel off the github
|
||||
push. Verified `/v1/notifications`, `/v1/peers`, `/v1/members`,
|
||||
`/v1/topics/general/stream`, `/v1/topics/general/read` all
|
||||
return 401 with bad bearer (i.e. they exist + auth works).
|
||||
Authenticated browser smoke not run — no Playwriter session
|
||||
available during this handoff write.
|
||||
- **CLI** (`claudemesh-cli@1.6.1` on npm): unchanged this session.
|
||||
All v1.6.x work was server + web only; CLI doesn't yet consume
|
||||
the new endpoints.
|
||||
|
||||
### CLI gap — worth noting
|
||||
|
||||
The new endpoints have NO CLI surface yet:
|
||||
|
||||
- `GET /v1/notifications` — `claudemesh notification list` could show
|
||||
recent mentions in the terminal. ~30 LoC.
|
||||
- `GET /v1/members` — `claudemesh member list` shows roster + online
|
||||
state. Distinct from `peer list` which shows live sessions.
|
||||
- `PATCH /v1/topics/:name/read` — could be implicit (called by
|
||||
`topic show <name>`) or explicit (`claudemesh topic read <name>`).
|
||||
- SSE stream — `claudemesh topic tail <name>` would tail messages
|
||||
in the terminal. High demo value.
|
||||
|
||||
Wiring these is a small CLI release (v1.7.0). Not blocking anything
|
||||
but worth doing before the recording so the demo includes a
|
||||
"terminal tail" cut.
|
||||
|
||||
---
|
||||
|
||||
## Known issues / risks
|
||||
|
||||
1. **Mentions notification endpoint depends on plaintext-base64
|
||||
ciphertext** that v0.2.0 ships. When per-topic encryption lands
|
||||
in v0.3.0, both `GET /v1/notifications` and the universe-page
|
||||
`MentionsSection` query break. Migration plan is documented in
|
||||
the blog post + the inline comment: move to a
|
||||
`mesh.notification` table populated at write time.
|
||||
|
||||
2. **Postgres `convert_from(decode(ciphertext, 'base64'), 'UTF8')`
|
||||
throws on any ciphertext that isn't valid base64-of-UTF8.** All
|
||||
current writers (broker WS path, REST POST /messages, web chat
|
||||
panel) emit base64-of-plaintext-UTF8, so this works. If a future
|
||||
writer emits binary ciphertext, the mention queries crash. Add a
|
||||
safe-base64 guard or migrate to per-write notification table
|
||||
before that happens.
|
||||
|
||||
3. **No live SSE smoke test in this session.** Endpoints respond
|
||||
401 to bad bearer. Browser-authenticated test was deferred — no
|
||||
Playwriter session was reachable during the run. Worth a
|
||||
manual smoke before recording the demo.
|
||||
|
||||
4. **CSRF middleware blocks PATCH/POST without an Origin header.**
|
||||
This is correct behaviour but trips up curl users. Documented
|
||||
in the smoke notes; not a bug.
|
||||
|
||||
---
|
||||
|
||||
## Next session — three branches
|
||||
|
||||
### A. Record + ship the v1.7.0 launch (~2 hours, all human work)
|
||||
1. Spin a fresh demo mesh + two iTerm panes running
|
||||
`claudemesh launch --name Mou` and `--name Alexis`.
|
||||
2. Run the demo script in `docs/demo-v1.7.0-script.md`.
|
||||
3. Cut to 90s, upload to `claudemesh.com/media/demo-v170.mp4`.
|
||||
4. Take 4-6 screenshots (universe, mesh detail, chat with sidebar,
|
||||
mentions feed, mobile view) for the blog hero + Twitter card.
|
||||
5. Cross-post per the script's distribution checklist.
|
||||
|
||||
### B. Wire CLI verbs to v1.6.x endpoints (~3 hours, code)
|
||||
1. `claudemesh notification list [--since]` → `GET /v1/notifications`.
|
||||
2. `claudemesh member list` → `GET /v1/members`.
|
||||
3. `claudemesh topic tail <name>` → SSE consumer. Print as messages
|
||||
arrive. Highest demo value.
|
||||
4. `claudemesh topic read <name>` → `PATCH /v1/topics/:name/read`.
|
||||
5. Bump `apps/cli/package.json` to 1.7.0, publish.
|
||||
|
||||
### C. v0.3.0 first slice — per-topic encryption (~5 hours, code)
|
||||
This is the next architectural cut.
|
||||
1. Schema: add `mesh.topic.encrypted_key` (encrypted-to-mesh-root).
|
||||
2. Broker: derive symmetric key on first message via HKDF; cache.
|
||||
3. Client: per-topic key fetch + `crypto_secretbox` over body.
|
||||
4. `ciphertext` column stops being plaintext-base64 → mentions
|
||||
query needs the notification table from issue #1.
|
||||
|
||||
Highest leverage right now is **A** (the recording is what turns
|
||||
shipped code into shipped product), then **B** (CLI parity makes
|
||||
the demo fuller). **C** is the next session for someone with
|
||||
2+ uninterrupted hours.
|
||||
|
||||
---
|
||||
|
||||
## Repo state
|
||||
|
||||
- `main` ahead of `gitea-vps/main` and `github/main` by 0 commits
|
||||
at handoff time — both pushed.
|
||||
- 12 commits this evening session (sse → unread → grid → sidebar →
|
||||
ssefix → mentions → search → notifications → roadmap → humans →
|
||||
roadmap2 → blog+demo → timeline).
|
||||
- No open PRs; everything went to main directly.
|
||||
- No `.skip` / TODO files / temp commits left behind.
|
||||
|
||||
---
|
||||
|
||||
*Last handoff: this file. Previous: `2026-05-02-handoff.md` (morning).*
|
||||
Reference in New Issue
Block a user