Advanced
Team vault protocol
Pro-only — multi-user, sharded sync, conflict resolution, tiered permissions.
Architecture overview
Team vaults do not rely on Dropbox / iCloud-style whole-directory sync. Instead, you self-host a CRDT hub and clients subscribe to the shards they care about. That keeps concurrent edits on the same paragraph conflict-free while letting large vaults (10GB+) sync only their hot regions.
The hub is a stateless coordinator: relays ops, persists history, enforces ACLs. The on-disk format is still Markdown + attachments + .kitable tables — if the hub vanishes, every client still has a complete, readable local vault.
It is a textbook local-first design: the network is an optimization, not a dependency. Everyone keeps working offline; reconciliation happens automatically on reconnect.
- Hub = self-hosted CRDT sync service (Go)
- Clients = standard Kition desktop or headless
- Sharding: per-directory; hot dirs get their own sync channel
- Conflicts: CRDT auto-merges text; metadata uses timestamp + three-way merge
- Offline: clients keep writing; reconciliation runs on reconnect
Permission model
Permissions are scoped per directory and per role. Roles are pre-defined (owner / editor / commenter / viewer) and customizable. The hub enforces at the op layer — unauthorized writes are rejected and never reach other clients.
Roles compose by inheritance: custom roles can inherits: editor and override specific paths. SSO integrations (OIDC / SAML) map external groups onto roles automatically.
# /etc/kition-hub/acl.yaml
roles:
engineer:
inherits: editor
paths:
- "engineering/**": editor
- "finance/**": viewer
finance:
inherits: editor
paths:
- "finance/**": editor
- "engineering/**": none
users:
- email: [email protected]
role: engineer
- email: [email protected]
role: finance
- email: [email protected]
role: owner
groups:
- oidc_claim: "groups"
mapping:
"eng-team": engineer
"fin-team": finance
"leads": ownerDeploying the hub
The hub ships as a Docker compose stack. For production, keep it inside a VPC, with a reverse proxy (Caddy / nginx) handling TLS and SSO. Postgres stores history; object storage (S3 / R2 / MinIO) holds large attachments.
Minimum production footprint: one hub instance (2 vCPU / 4GB) + one Postgres (managed is fine) + one S3-compatible bucket. Comfortable up to a 50-person team.
services:
hub:
image: ghcr.io/kition-ai/vault-hub:latest
environment:
DATABASE_URL: postgres://hub:secret@db/hub
OBJECT_STORE: s3
S3_BUCKET: kition-vault-prod
S3_REGION: us-east-1
ACL_PATH: /etc/kition-hub/acl.yaml
OIDC_ISSUER: https://auth.acme.com
volumes:
- ./acl.yaml:/etc/kition-hub/acl.yaml:ro
ports: ["7000:7000"]
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
POSTGRES_USER: hub
POSTGRES_DB: hub
volumes: ["db:/var/lib/postgresql/data"]
volumes: { db: {} }Connecting a client
# Pair a desktop client to a hub vault
kition vault join \
--hub https://vault.acme.com \
--vault team-eng \
--as [email protected]
# Force a full resync
kition vault sync --vault team-eng --full
# Inspect sync state
kition vault status --vault team-eng
# List shards the client is subscribed to
kition vault shards --vault team-eng
# Subscribe to an additional shard
kition vault shards add --vault team-eng "design/**"Sync protocol details
The wire protocol is binary frames over WebSocket, in four classes: ops (CRDT ops with vector clocks), presence (cursor and online state), request (history / snapshot fetch), ack (persistence confirmation). Text uses RGA CRDT, metadata uses an LWW map, attachments are content-addressed blob references.
Offline writes accumulate in a local outbox and replay on reconnect. The hub keeps vector clocks per user × shard, so reconciliation is incremental — no full pull.
Operational checklist
- Daily logical backups of Postgres + cross-region replication for object storage
/metricsexposes op rate, active client count, merge-failure counter- Hub upgrades are rolling — clients auto-reconnect through the cut
- Audit log: every op carries user, timestamp, path; ships to your SIEM
- Revoking a user: edit acl.yaml; the hub hot-reloads and live connections downgrade immediately
- Snapshot export:
kition-hub snapshot --vault team-eng --out /backup/ - Even if the hub is down, clients keep reading and writing their local vault — that is the local-first guarantee