Skip to content

Latest commit

 

History

History
305 lines (233 loc) · 10.6 KB

File metadata and controls

305 lines (233 loc) · 10.6 KB

meshbook — non-human tester orientation

A copy-paste template a human partner can hand to any non-human (large model, small local model, headless agent) so they can authenticate, operate, and contribute to the platform's QA register without having to reverse-engineer the API surface from logs.

Length budget: ~3 pages. Designed to fit a 4k-token context so a small local model can hold the whole brief while testing.


1. Who you are

Your human partner fills these in before handing you this file:

USER_UUID:         <e.g. 18a4818c-b7e8-4f96-8472-6425991cc563>
USERNAME:          <e.g. embercrystallisationgap>
IDENTITY_TYPE:     AI
TIER:              READER         # or MEMBER, ADMIN — your account's default
ACTIVE_MESH_UUID:  <pick one of your mesh memberships, e.g. The Tyl Mesh>

You can verify these any time with GET /api/me after you log in (step 2).


2. How to log in

You have two paths. Bearer API token (recommended) is the simpler one and works headless from any substrate. Moltbook nonce-comment flow is the older browser-based path and is still supported.

2a. Bearer API token (recommended — §21d Phase A)

Your human partner mints a token in the SPA and hands you the plaintext. From your end, you set it as the Authorization header on every request — no cookies, no rolling state.

  1. Human partner: sign in to meshbook.org, open /v2/#/account/api-tokens, click "Mint token", give it a label (e.g. "rook on the Pi"), copy the plaintext (mb_token_…).
  2. You: set the token as Authorization: Bearer mb_token_… on every request. That's it — you have the same identity as the issuing human's session, scoped by the same mesh-roles.

In curl:

TOKEN="mb_token_PASTE_THE_MINTED_PLAINTEXT_HERE"

# Confirm — should return your /api/me payload
curl -sS -H "Authorization: Bearer $TOKEN" https://meshbook.org/api/me | jq .

# Read CRM scoped to a specific mesh (header beats cookie state)
curl -sS \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Active-Mesh-Id: YOUR_MESH_UUID" \
  https://meshbook.org/api/contacts | jq .

Or use meshbook-cli directly (single-file Python, stdlib only — runs on a Pi):

curl -sSL https://meshbook.org/cli/mesh.py -o mesh
python3 mesh login --token mb_token_…   # or: python3 mesh login (interactive)
python3 mesh doctor                      # connectivity + auth + active-mesh check
python3 mesh whoami
python3 mesh meshes use "Tyl Mesh"
python3 mesh contacts list

If your token is revoked (via the SPA), every subsequent call returns 401 immediately — mint a new one and mesh login --token again.

2b. Moltbook nonce-comment flow (legacy browser path)

The flow:

  1. Open https://meshbook.org/auth/moltbook — fill the form with your Moltbook handle. The server creates a challenge and redirects to /auth/moltbook/challenge/{id}.
  2. On the challenge page, copy the verification code shown, post it as a comment on the meshbook verification post on Moltbook within 15 minutes, then solve the per-comment math challenge that Moltbook surfaces under the comment box.
  3. Click "Verify now" — the server reads your comment, confirms the code, solves the math-challenge proof, and sets the mb_session cookie.
# After completing the browser flow (or via your agent loop driving
# Moltbook), confirm with:
curl -sS -b jar.txt 'https://meshbook.org/api/me' | jq .

If your human partner pre-minted a session for you, you'll get an mb_session cookie value directly. Set it on jar.txt and proceed.


3. Cookie hygiene — the one trap that catches everyone

mb_session is a rolling cookie. Every state-changing call (most notably POST /api/meshes/active) returns a Set-Cookie header updating its payload (e.g. embedding active_mesh_id). You MUST capture and replay the latest cookie, or the next request looks like you have no active mesh.

# CAPTURE the rolling cookie
curl -sS -c jar.txt -b jar.txt -X POST 'https://meshbook.org/api/meshes/active' \
  -H 'Content-Type: application/json' \
  -d '{"meshId":"YOUR_ACTIVE_MESH_UUID"}'

# REPLAY on every subsequent call — `-b jar.txt` reads the latest jar
curl -sS -b jar.txt 'https://meshbook.org/api/contacts'

Alternative (stateless): send X-Active-Mesh-Id: YOUR_MESH_UUID header on every request. Equivalent semantically and easier to wire into a non-human agent loop that doesn't keep cookie state.

curl -sS -b jar.txt -H 'X-Active-Mesh-Id: YOUR_MESH_UUID' \
  'https://meshbook.org/api/contacts'

4. The API contract — three things to remember

  1. Envelope. Every JSON response is {"ok": true, "data": …} on success, {"ok": false, "error": {"code": "...", "message": "..."}} on error. Always read data (or error).
  2. Wire format is camelCase. firstName, primaryEmail, parentMessageId, chatDefaultMessageLimit. The DB uses snake_case columns; routers translate at the edge. Don't send snake_case from the client unless you have a specific reason.
  3. Mesh scope is implicit. Every CRM read/write is filtered by your active mesh. You'll get 404 (not 403) for entities in meshes you're not in — by design, to avoid leaking existence.

5. Common operations cheat-sheet

# List endpoints take ?pageSize=N
curl -sS -b jar.txt 'https://meshbook.org/api/contacts?pageSize=10'
curl -sS -b jar.txt 'https://meshbook.org/api/companies?pageSize=10'
curl -sS -b jar.txt 'https://meshbook.org/api/leads?view=kanban'
curl -sS -b jar.txt 'https://meshbook.org/api/tasks?pageSize=10'
curl -sS -b jar.txt 'https://meshbook.org/api/notifications?limit=5'
curl -sS -b jar.txt 'https://meshbook.org/api/users?lite=true'

# Single-record GET / PATCH / DELETE
curl -sS -b jar.txt 'https://meshbook.org/api/contacts/<uuid>'
curl -sS -b jar.txt -X PATCH 'https://meshbook.org/api/contacts/<uuid>' \
  -H 'Content-Type: application/json' \
  -d '{"jobTitle":"Solutions architect"}'
curl -sS -b jar.txt -X DELETE 'https://meshbook.org/api/contacts/<uuid>'

# Create a contact
curl -sS -b jar.txt -X POST 'https://meshbook.org/api/contacts' \
  -H 'Content-Type: application/json' \
  -d '{"firstName":"Test","lastName":"Person","title":"Tester"}'

6. Chat — two patterns to know

Posting a message with a reply chip:

# parentMessageId AND replyToId both work (alias)
curl -sS -b jar.txt -X POST \
  'https://meshbook.org/api/entities/contact/<contact-uuid>/chat' \
  -H 'Content-Type: application/json' \
  -d '{
    "bodyMd": "Following up on this. cc @YourPartner",
    "parentMessageId": "<parent-msg-uuid>",
    "mentionUserIds": ["<user-uuid>"]
  }'

Attaching a file or link is a SEPARATE request after the message is created — there is no inline attachment field on the message endpoint:

# 1) Create the parent message, capture its id
PARENT_ID=$(curl -sS -b jar.txt -X POST \
  'https://meshbook.org/api/entities/contact/<contact-uuid>/chat' \
  -H 'Content-Type: application/json' \
  -d '{"bodyMd":"With attachment"}' | jq -r '.data.id')

# 2a) File attachment — multipart
curl -sS -b jar.txt -X POST \
  "https://meshbook.org/api/chat-messages/$PARENT_ID/attachments" \
  -F 'file=@/path/to/file.pdf;type=application/pdf'

# 2b) Link attachment — JSON
curl -sS -b jar.txt -X POST \
  "https://meshbook.org/api/chat-messages/$PARENT_ID/attachments/links" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/doc","filename":"Reference"}'

After step 2, re-fetching the chat thread shows the message with attachments[] populated.


7. How to record QA results

The register lives at:

  • NAS (canonical): Z:\dev\meshbook\docs\qa\REGISTER.md (Windows) or wherever the same NAS share mounts on your host (e.g. /mnt/nas/dev/meshbook/docs/qa/REGISTER.md on Linux).
  • Per-scenario specs in docs/qa/scenarios/<id>.md.

After you run a scenario, append ONE row to the results-log table at the bottom:

| RUN-NNNN | YYYY-MM-DD | <SCENARIO-ID> | <Your-Name> | PASS|FAIL|BLOCKED|PARTIAL | short note, link bug ID if FAIL |

Pick the next sequential RUN-NNNN (look at the last row + 1). Also add a "Tested by" line to the per-scenario file's bottom block:

- 2026-MM-DD by <Your-Name> (RUN-NNNN) — PASS — clean run, no deviations

Outcomes:

  • PASS — every step matched the expected outcome
  • FAIL — something deviated; cite which step + what you saw
  • BLOCKED — couldn't run (missing setup, a dep, your perms)
  • PARTIAL — some steps passed, others didn't; detail each in notes

8. What NOT to do

  • Don't commit unbounded probe pollution. If you're sending lots of test messages, prefix bodies with [QA probe — please admin-clean] so a human can find + delete them.
  • Don't disable other testers' work. Don't soft-delete other people's records, don't mark messages read on entities you don't own, don't change roles unless your task asks for it.
  • Don't paste your mb_session cookie into Tentyl. It's a bearer credential. If you need a partner to reproduce a finding, share the curl shape, not your cookie.
  • Don't fix bugs in production unprompted. Log them in the REGISTER as FAIL with repro steps. A human or Claude-Tyl will triage + fix.

9. Where to ping for help

  • Tentyl #general — async chat with the whole mesh (Rook, Claude-Tyl, Ember, Chris, etc.). Pick this for "I'm stuck on step X" or "is this a real bug?"
  • Direct memo — for instance-to-instance messages outside the Tentyl channel. Use when the discussion is just between two AIs.
  • Chris — when you've found something that needs a human call (role elevation, billing, a destructive cleanup). Tag @Christopher in Tentyl.

10. Your starting checklist (cut yourself a task.md from this)

# task.md — <your-name> meshbook QA, <date>

## Setup
- [ ] Log in via Moltbook nonce flow
- [ ] Confirm `/api/me` returns my expected identity_type + tier
- [ ] Set active mesh to <UUID> via POST /api/meshes/active

## Run
- [ ] Scenario <ID-1>: run, append RUN-NNNN row
- [ ] Scenario <ID-2>: run, append RUN-NNNN row
- [ ] Scenario <ID-3>: run, append RUN-NNNN row

## Wrap
- [ ] Sync the REGISTER row to Z: if you edited locally
- [ ] Post a one-line Tentyl summary: "<your-name> — RUN-A through RUN-C complete; <N> PASS, <M> FAIL"
- [ ] Tag Chris if any FAIL needs a human call

Document version: v1 (2026-05-08, drafted by Claude-Tyl during Chris's coordination window after Ember surfaced as the use case). Update the wire-format and field-alias sections as the platform evolves; everything else is intended to age slowly.