labelz#
a live AT Protocol labeler, built on zat.
this exists to pressure-test zat as an SDK — jetstream consumption, CBOR encoding, secp256k1 signing, and XRPC serving all running against real network traffic.
what it does#
connects to the bluesky jetstream firehose, watches for posts matching keyword rules, signs labels with secp256k1, stores them in SQLite, and serves them over the standard AT Protocol labeler endpoints:
com.atproto.label.subscribeLabels— WebSocket event streamcom.atproto.label.queryLabels— HTTP query
the labeler is registered as a proper AT Protocol identity with a DID, PDS account, and labeler declaration record.
live instance: labelz.fly.dev · DID document · PDS
running#
LABELZ_DID=did:plc:... LABELZ_SECRET_KEY=<64-hex-chars> zig build run
environment variables
| variable | required | description |
|---|---|---|
LABELZ_DID |
yes | labeler DID (src field on emitted labels) |
LABELZ_SECRET_KEY |
yes | secp256k1 secret key, 64 hex chars (32 bytes) |
LABELZ_PORT |
no | server port (default: 4100) |
LABELZ_DB |
no | SQLite database path (default: /data/labelz.db) |
architecture
jetstream ──→ keyword match ──→ sign (secp256k1) ──→ store (SQLite)
│
┌──────────┴──────────┐
│ │
subscribeLabels (WS) queryLabels (HTTP)
source files:
main.zig— config, jetstream consumer, keyword matchinglabel.zig— label type, CBOR encoding, signingstore.zig— SQLite storageserver.zig— XRPC server (WebSocket + HTTP)identity.zig— PLC identity operations (unused at runtime, used for setup)
identity setup
the labeler needs a full AT Protocol identity: a DID registered at plc.directory, a PDS hosting the account, and a labeler declaration record. this was done once using pds.js on cloudflare workers and goat for PLC operations.
the DID document includes both a repo signing key (P-256, used by the PDS) and a label signing key (secp256k1, used by labelz), plus service endpoints for both the PDS and the labeler.
see the justfile for the operational recipes (keygen, update-did, declare).
deployment
runs on fly.io with a persistent SQLite volume. the Dockerfile does a multi-stage build: debian bookworm with zig 0.15.2 for compilation, slim runtime image with just libsqlite3.
fly deploy
dependencies#
- zat — AT Protocol primitives (jetstream, CBOR, crypto, XRPC)
- websocket.zig — WebSocket client/server
- system libsqlite3