Spec / docs

Spec · v0.1 draftTrails engineAppend-only · Merkle · CRDT

Tongbuku 同步库 trails & sync spec

This draft defines the event envelope, trail metadata, Merkle-head sync, and read APIs that make Tongbuku 同步库 the trusted trails engine for EarthCloud, Buoychong, ChatCard, and future Glyphd Labs products.

Tongbuku 同步库 keeps append-only trails of events that teams can replay, analyze, and reuse as process templates. Trails sit beneath ChatCard identity and EarthCloud meaning, and this document spells out how events, trails, and projections stay in step.

Core concepts

Four primitives define Tongbuku 同步库.

Event

Smallest unit of history. Immutable JSON describing a turn, tool call, or observation with actors, payload, parents, and tags.

Trail

Append-only sequence of events for a document, room, or workflow. Trails can branch offline and reconcile via Merkle heads.

View / projection

Derived representation of one or more trails—summaries, indexes, or templates that stay ready for models and operators.

Merkle head

Hash frontier representing what a client knows. Sync exchanges heads to request only missing events.

1 · Event envelope

Events capture immutable turns.

Events are append-only objects with a stable identifier, parent references, actor metadata, payload, and tags. They are the atomic unit of sync, replay, and audit.

  • actors contain user_id, app_id, and optional card_id for ChatCard alignment.
  • Use tags for multi-tenant routing and filtering.
  • Payloads remain application-defined but should stay compact and structured.
tb_eventPOST /v1/events/append
{
  "event_id": "evt_01JK9WQ3",
  "trail_id": "trail_conversation_abc",
  "kind": "turn",                         // turn | tool | system | custom
  "timestamp": "2025-11-08T20:00:00Z",

  "parents": ["evt_01JK9WQ2"],
  "actors": {
    "user_id": "user_en",
    "app_id": "chat_surface",
    "card_id": "chatcard_room_alpha"
  },
  "payload": {
    "role": "user",
    "text": "Kickoff sync notes?",
    "lang": ["en", "zh-CN"]
  },

  "tags": ["room:alpha", "plan:pro"],
  "metadata": {
    "glyphir_id": "gph_01HX...",
    "approx_tokens": 128
  }
}

2 · Trail

Trails group related events.

Trails collect metadata about a conversation, workflow, session, or document. They reference one or more Merkle heads that describe how far a client has synced.

The heads array can hold multiple branches for offline edits. Many apps rely on a single head named head_main.

tb_trailGET /v1/trails/{trail_id}
{
  "trail_id": "trail_conversation_abc",
  "kind": "conversation",                 // conversation | session | workflow | document | custom
  "created_at": "2025-11-08T20:00:00Z",
  "updated_at": "2025-11-08T20:15:00Z",

  "tags": ["room:abc", "customer:1234", "plan:pro"],
  "heads": [
    {
      "head_id": "head_main",
      "merkle_hash": "mkh_def456...",
      "last_event_id": "evt_01JK...",
      "branch": "main"
    }
  ],

  "metadata": {
    "title": "Project kickoff chat",
    "summary": "Initial planning discussion about the new release."
  }
}

3 · View / projection

Projections keep trails model-ready.

Snapshots are read-optimized documents derived from trails. They may be per-user, per-trail, or cross-trail indexes that your models consume directly.

  • scope defines the view type (e.g., conversation_summary or agent_turn_pairs).
  • Use based_on_heads to indicate which frontier the view reflects.
tb_snapshotGET /v1/views/{trail_id}
{
  "snapshot_id": "snap_01SNAP...",
  "trail_id": "trail_conversation_abc",
  "scope": "conversation_summary",     // type of view
  "created_at": "2025-11-08T20:16:00Z",
  "based_on_heads": ["mkh_def456..."],

  "data": {
    "summary": "The team agreed to meet tomorrow at 3pm Beijing time...",
    "participants": ["user_en", "user_zh"],
    "languages": ["en", "zh-CN"],
    "turns": 14
  },

  "meta": {
    "generated_by": "summary_agent_v1",
    "model_id": "earthcloud_model_vX",
    "approx_tokens": 256
  }
}

4 · Merkle head

Sync via hashes, not blind polling.

A Merkle head captures the frontier a client has observed. Servers compare hashes to calculate missing events and return only what is new.

Implementations may compress known_event_ids. The contract is simply “given this head, return what I need.”

tb_headPOST /v1/sync
{
  "trail_id": "trail_conversation_abc",
  "merkle_hash": "mkh_def456...",
  "known_event_ids": ["evt_01JH...", "evt_01JG...", "evt_01JK..."],
  "client_id": "device_iphone_13",
  "timestamp": "2025-11-08T20:15:30Z"
}

Endpoints

Minimal API surface for trails.

REST-ish endpoints cover append, metadata, sync, and view reads. You can expose gRPC or GraphQL equivalents as long as the same envelopes are honored.

POST /v1/events/append

Append one or more events to a trail. Supports dedupe and optional return of the trail body.

POST /v1/events/append
Content-Type: application/json
Authorization: Bearer <token>

{
  "events": [
    { ... tb_event ... },
    { ... }
  ],
  "options": {
    "dedupe_on": ["event_id"],
    "return_trail": false
  }
}
{
  "success": true,
  "inserted": ["evt_01JK...", "evt_01JL..."],
  "ignored": [],
  "trail": { ... tb_trail ... }   // optional, if return_trail = true
}
GET /v1/trails/{trail_id}

Fetch metadata and, optionally, a window of events for a trail.

GET /v1/trails/trail_conversation_abc?limit=50&before=evt_01JK...
POST /v1/sync

Sync events for one or more trails by sending Merkle heads and receiving the missing events.

POST /v1/sync
Content-Type: application/json

{
  "heads": [
    {
      "trail_id": "trail_conversation_abc",
      "merkle_hash": "mkh_client_local..."
    }
  ],
  "limit": 256
}
{
  "trails": [
    {
      "trail_id": "trail_conversation_abc",
      "events": [
        { ... tb_event ... },
        { ... }
      ],
      "server_head": {
        "merkle_hash": "mkh_server_latest...",
        "last_event_id": "evt_01JK..."
      }
    }
  ]
}
GET /v1/views/{trail_id}

Fetch or trigger a view over a trail.

GET /v1/views/trail_conversation_abc?scope=conversation_summary
{
  "snapshot": { ... tb_snapshot ... },
  "status": "ready"        // ready | computing | stale
}
POST /v1/views/compute

Optional endpoint to trigger or update materialized views for one or more trails.

Error model

Consistent JSON errors.

Use OAuth-style fields for errors. Keep error codes machine-readable and descriptive enough for operators.

{
  "error": "invalid_request",
  "error_description": "Missing 'events' field in body."
}

Authentication & authz

Transport and data safety.

  • Require bearer tokens or mTLS for write operations.
  • Tag events with user_id, app_id, and optionally card_id for ChatCard-aware permissions.
  • Partition trails by tenant, geography, or compliance boundary using trail_id prefixes and tags.
  • Mirror trails into your warehouse for auditing, but treat Tongbuku 同步库 as the source of truth for ordering.

Spec status & evolution

v0.1 goals

  • Agree on the minimal event & trail envelope.
  • Align on a simple Merkle-head sync protocol that works offline-first.
  • Define read APIs for trails and views that downstream stacks rely on.

Future revisions will formalize merge semantics, ship reference implementations (Postgres, KV, embedded), and expand view types for training/eval workloads. Reach out via info@tongbuku to contribute or request clarifications.