Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started

Prerequisites

  • Node 24 or newer.
  • Postgres.

Install

git clone https://github.com/julietshen/troposphere
cd troposphere
npm install

1. Generate a signing key

npm run keygen

This prints three things:

LABELER_SIGNING_KEY=<64 hex chars>
# did:key:             did:key:zQ3sh...
# publicKeyMultibase:  zQ3sh...

Keep LABELER_SIGNING_KEY secret. The publicKeyMultibase is what you will publish in your DID document so the network can verify your labels. See Publishing your labeler identity.

2. Configure

Copy the example env file and fill it in:

cp .env.example .env
VariableMeaning
LABELER_DIDYour labeler’s DID (did:web:... or did:plc:...).
LABELER_SIGNING_KEYThe 64-char hex key from npm run keygen.
ADMIN_TOKENBearer token your backend presents to the emit API.
DATABASE_URLPostgres connection string.
PORTHTTP port (default 4100).

3. Create the schema and run

npm run db:init
npm run dev          # or: npm run build && npm start

On startup the server logs the labeler DID and the #atproto_label key it is using, as a reminder to publish them.

4. Verify it works

Emit a label and read it back:

curl -X POST http://localhost:4100/admin/labels \
  -H "authorization: Bearer $ADMIN_TOKEN" \
  -H "content-type: application/json" \
  -d '{ "subject": { "uri": "at://did:plc:example/app.bsky.feed.post/abc" }, "create": ["spam"] }'

curl "http://localhost:4100/xrpc/com.atproto.label.queryLabels?uriPatterns=at://did:plc:example/app.bsky.feed.post/abc"

Or run the bundled smoke test, which emits, queries, tails the firehose, and independently verifies the signatures:

LABELER_URL=http://localhost:4100 \
ADMIN_TOKEN=$ADMIN_TOKEN \
LABELER_DID=$LABELER_DID \
SIGNING_DID_KEY=did:key:zQ3sh... \
npm run smoke

The smoke test also exercises report intake: it mints a service JWT and confirms createReport accepts an authed report and rejects unauthenticated or wrong-audience ones.

Next: make the network trust your labels by publishing your labeler identity.