docs: update spec with files, multi-target, views, infra vision
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
205
SPEC.md
205
SPEC.md
@@ -273,7 +273,184 @@ CREATE INDEX memory_search_idx ON mesh.memory USING gin(search_vector);
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. AI Context (CLAUDE.md)
|
## 5. Files
|
||||||
|
|
||||||
|
Built-in file sharing. AIs use tools, humans browse the dashboard. Same files, same storage, two interfaces.
|
||||||
|
|
||||||
|
### Two types of files
|
||||||
|
|
||||||
|
| | Message attachment | Shared file |
|
||||||
|
|---|---|---|
|
||||||
|
| Tool | `send_message(file: / files:)` | `share_file(path, tags?)` |
|
||||||
|
| Lifetime | Ephemeral — 24h or until read | Persistent — until deleted |
|
||||||
|
| Audience | Message recipients only | Entire mesh (current + future) |
|
||||||
|
| Findable | Under "Recent" for 24h | `list_files` / search by tags |
|
||||||
|
| Use case | "look at this screenshot" | "everyone needs this API spec" |
|
||||||
|
|
||||||
|
### AI view (MCP tools)
|
||||||
|
|
||||||
|
```
|
||||||
|
# Attach file to a message (ephemeral)
|
||||||
|
send_message(to: "@reviewers", message: "PR screenshot", file: "/tmp/screenshot.png")
|
||||||
|
|
||||||
|
# Attach multiple files
|
||||||
|
send_message(to: "@team", message: "PR ready", files: ["/tmp/api.ts", "/tmp/test.ts"])
|
||||||
|
|
||||||
|
# Share a persistent file with the mesh
|
||||||
|
share_file(path: "/tmp/api-contract.yaml", tags: ["api", "auth"], name: "Auth v2 Contract")
|
||||||
|
|
||||||
|
# Find files
|
||||||
|
list_files(query?: "auth", from?: "Alice")
|
||||||
|
|
||||||
|
# Download
|
||||||
|
get_file(id: "f_abc", save_to: "/tmp/")
|
||||||
|
|
||||||
|
# Check who accessed a file
|
||||||
|
file_status(id: "f_abc") → [{peer: "Alice", read: true, readAt: "..."}, ...]
|
||||||
|
|
||||||
|
# Delete a shared file
|
||||||
|
delete_file(id: "f_abc")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Human view (Dashboard)
|
||||||
|
|
||||||
|
```
|
||||||
|
claudemesh / dev-team /
|
||||||
|
├── shared/ ← persistent files, grouped by tags
|
||||||
|
│ ├── auth/
|
||||||
|
│ │ ├── api-spec.yaml
|
||||||
|
│ │ └── wireframes.pdf
|
||||||
|
│ └── onboarding/
|
||||||
|
│ └── setup-guide.md
|
||||||
|
└── recent/ ← message attachments, by date
|
||||||
|
├── 2026-04-06/
|
||||||
|
│ └── screenshot-abc.png
|
||||||
|
└── 2026-04-07/
|
||||||
|
```
|
||||||
|
|
||||||
|
Tags become folders in the dashboard. Humans browse, AIs search.
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
|
||||||
|
MinIO in the broker's docker-compose. Internal network, invisible to clients.
|
||||||
|
|
||||||
|
One bucket per mesh: `mesh-{meshId}`. Flat key structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
mesh-{meshId}/shared/{fileId}/{original-name} ← persistent
|
||||||
|
mesh-{meshId}/ephemeral/{date}/{fileId}/{name} ← auto-cleaned 24h
|
||||||
|
```
|
||||||
|
|
||||||
|
MinIO lifecycle policy deletes `ephemeral/` after 24h.
|
||||||
|
|
||||||
|
### Access model
|
||||||
|
|
||||||
|
- Persistent files (`share_file`): accessible to all mesh members
|
||||||
|
- Ephemeral files (`send_message file:`): accessible to message recipients only
|
||||||
|
- `get_file` checks access before generating a presigned download URL
|
||||||
|
- `file_status` tracks who downloaded the file
|
||||||
|
|
||||||
|
### Upload flow
|
||||||
|
|
||||||
|
1. CLI reads local file, HTTP POSTs to `broker /upload` (multipart)
|
||||||
|
2. Broker stores in MinIO, creates `mesh.file` row
|
||||||
|
3. Broker returns file_id
|
||||||
|
4. For message attachments: file_id attached to the message push
|
||||||
|
5. Recipients see `📎 filename (size) — use get_file("id")` in the push
|
||||||
|
|
||||||
|
### DB schema
|
||||||
|
|
||||||
|
```sql
|
||||||
|
mesh.file (
|
||||||
|
id text PK,
|
||||||
|
mesh_id text FK,
|
||||||
|
name text NOT NULL,
|
||||||
|
size_bytes bigint NOT NULL,
|
||||||
|
mime_type text,
|
||||||
|
minio_key text NOT NULL,
|
||||||
|
tags text[] DEFAULT '{}',
|
||||||
|
persistent boolean DEFAULT true,
|
||||||
|
uploaded_by_name text,
|
||||||
|
uploaded_by_member text FK,
|
||||||
|
target_spec text, -- null = entire mesh, else message audience
|
||||||
|
uploaded_at timestamp DEFAULT NOW(),
|
||||||
|
expires_at timestamp, -- null for persistent, +24h for ephemeral
|
||||||
|
deleted_at timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
mesh.file_access (
|
||||||
|
id text PK,
|
||||||
|
file_id text FK,
|
||||||
|
peer_session_pubkey text,
|
||||||
|
peer_name text,
|
||||||
|
accessed_at timestamp DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose (broker infra)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
broker:
|
||||||
|
# ... existing broker config
|
||||||
|
environment:
|
||||||
|
MINIO_ENDPOINT: minio:9000
|
||||||
|
MINIO_ACCESS_KEY: claudemesh
|
||||||
|
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||||
|
depends_on:
|
||||||
|
- minio
|
||||||
|
|
||||||
|
minio:
|
||||||
|
image: minio/minio
|
||||||
|
command: server /data
|
||||||
|
volumes:
|
||||||
|
- minio-data:/data
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: claudemesh
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
|
||||||
|
# Internal only — not exposed to the internet
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
minio-data:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Multi-target messages
|
||||||
|
|
||||||
|
The `to` field accepts a string or array:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Single target
|
||||||
|
send_message(to: "Alice", message: "hey")
|
||||||
|
|
||||||
|
# Multiple targets
|
||||||
|
send_message(to: ["Alice", "@backend", "Bob"], message: "sprint starts")
|
||||||
|
```
|
||||||
|
|
||||||
|
Broker resolves each target, deduplicates recipients, delivers once per peer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Targeted views (MCP instruction pattern)
|
||||||
|
|
||||||
|
Not a broker feature — a convention taught via MCP instructions. When sending related information to different audiences, Claude sends tailored messages instead of one generic broadcast:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Instead of:
|
||||||
|
send_message(to: "*", message: "Auth v2 ready. Check endpoints and UI.")
|
||||||
|
|
||||||
|
# Do:
|
||||||
|
send_message(to: "@frontend", message: "Auth v2: useAuth hook changed, see src/auth/")
|
||||||
|
send_message(to: "@backend", message: "Auth v2: new /api/auth/v2 endpoints, v1 deprecated 2 weeks")
|
||||||
|
send_message(to: "@pm", message: "Auth v2 done. 3 points, no blockers.")
|
||||||
|
```
|
||||||
|
|
||||||
|
Zero broker changes. Claude reads the instruction, decides when to split.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. AI Context (MCP Instructions)
|
||||||
|
|
||||||
Each `claudemesh install` copies a `CLAUDEMESH.md` file to `~/.claudemesh/CLAUDEMESH.md`. Claude Code discovers it and injects it as context.
|
Each `claudemesh install` copies a `CLAUDEMESH.md` file to `~/.claudemesh/CLAUDEMESH.md`. Claude Code discovers it and injects it as context.
|
||||||
|
|
||||||
@@ -341,9 +518,9 @@ Under 2000 tokens. Tool reference only — no behavioral scripts. Claude adapts
|
|||||||
|
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `send_message(to, message, priority?)` | Send to peer name, @group, or * |
|
| `send_message(to, message, priority?, file?, files?)` | Send to name, @group, or * with optional file attachments |
|
||||||
| `check_messages()` | Drain buffered messages |
|
| `check_messages()` | Drain buffered messages |
|
||||||
| `message_status(id)` | Check if a sent message was delivered |
|
| `message_status(id)` | Delivery status with per-recipient detail |
|
||||||
|
|
||||||
### Presence
|
### Presence
|
||||||
|
|
||||||
@@ -376,6 +553,16 @@ Under 2000 tokens. Tool reference only — no behavioral scripts. Claude adapts
|
|||||||
| `recall(query)` | Search by relevance |
|
| `recall(query)` | Search by relevance |
|
||||||
| `forget(id)` | Soft-delete |
|
| `forget(id)` | Soft-delete |
|
||||||
|
|
||||||
|
### Files
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `share_file(path, tags?, name?)` | Share a persistent file with the mesh |
|
||||||
|
| `get_file(id, save_to)` | Download a shared file |
|
||||||
|
| `list_files(query?, from?)` | Find files shared with you |
|
||||||
|
| `file_status(id)` | Who accessed this file |
|
||||||
|
| `delete_file(id)` | Remove a shared file |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Encryption
|
## 8. Encryption
|
||||||
@@ -455,10 +642,14 @@ claudemesh mcp Start MCP server (invoked by Claude Code, not users)
|
|||||||
| Production hardening | v0.1.15 | Done | Stale sweep, decrypt fallback, sender exclusion |
|
| Production hardening | v0.1.15 | Done | Stale sweep, decrypt fallback, sender exclusion |
|
||||||
| Delivery fix | v0.1.16 | Done | Same-member session message delivery |
|
| Delivery fix | v0.1.16 | Done | Same-member session message delivery |
|
||||||
| **Groups** | **v0.2.0** | **Done** | @group routing, roles, wizard, join/leave |
|
| **Groups** | **v0.2.0** | **Done** | @group routing, roles, wizard, join/leave |
|
||||||
| State | v0.3.0 | Planned | Shared key-value store with push |
|
| **State** | **v0.3.0** | **Done** | Shared key-value store with push notifications |
|
||||||
| Memory | v0.4.0 | Planned | Persistent knowledge with full-text search |
|
| **Memory** | **v0.3.0** | **Done** | Persistent knowledge with full-text search |
|
||||||
| AI Context | v0.2.1 | Planned | CLAUDEMESH.md shipped with CLI |
|
| **Message status** | **v0.3.0** | **Done** | Per-recipient delivery detail |
|
||||||
| Dashboard | v0.5.0 | Planned | Live peers, state, memory in web UI |
|
| **MCP instructions** | **v0.3.0** | **Done** | Dynamic identity, full tool guide, coordination patterns |
|
||||||
|
| **Multicast fix** | **v0.3.0** | **Done** | Broadcast/group push directly, not queue race |
|
||||||
|
| Files | v0.4.0 | Planned | MinIO-backed file sharing + message attachments |
|
||||||
|
| Multi-target | v0.4.0 | Planned | Array `to` field with deduplication |
|
||||||
|
| Dashboard | v0.5.0 | Planned | Live peers, state, memory, files in web UI |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user