Sifa professional network API (Fastify, AT Protocol, Jetstream)
sifa.id/
1# Sifa API -- AppView Backend
2
3<!-- Auto-generated from sifa-workspace. To propose changes, edit the source:
4 https://github.com/singi-labs/sifa-workspace -->
5
6Source-available | Part of [github.com/singi-labs](https://github.com/singi-labs)
7
8The AppView backend for Sifa -- a decentralized professional identity and career network on the AT Protocol. Subscribes to AT Protocol Jetstream, indexes `id.sifa.*` records in PostgreSQL, and exposes a REST API for professional profiles, endorsements, search, and reputation.
9
10## Tech Stack
11
12| Component | Technology |
13| ---------- | --------------------------------------------------------------- |
14| Runtime | Node.js 25 / TypeScript (strict) |
15| Framework | Fastify 5 |
16| Protocol | @atproto/api, @atproto/oauth-client-node, Jetstream (WebSocket) |
17| Database | PostgreSQL 17 (Drizzle ORM, Drizzle Kit migrations) |
18| Cache | Valkey 8 |
19| Testing | Vitest + Supertest |
20| Logging | Pino (structured) |
21| Monitoring | GlitchTip (Sentry SDK-compatible) |
22| Security | Helmet + Zod + DOMPurify + rate limiting |
23
24## What This Repo Does
25
26- Subscribes to AT Protocol Jetstream, filtering for `id.sifa.*` collections
27- Indexes professional profile records (positions, skills, education, endorsements) in PostgreSQL
28- Exposes REST API routes: `/api/profile/*`, `/api/search/*`, `/api/endorsement/*`, `/api/import/*`
29- Handles AT Protocol OAuth 2.1 authentication (PKCE, DPoP, PAR)
30- Queries Barazo AppView for per-community reputation data (cached in Valkey)
31- Validates all Jetstream records before indexing (Zod)
32- Validates all API input (Zod), sanitizes all output (DOMPurify)
33- Publishes Trust & Safety labels as AT Protocol labels (sybil detection, anti-abuse)
34
35## API-Specific Standards
36
37- Every API endpoint validates input with a Zod schema
38- Every Jetstream record validated before indexing
39- DOMPurify sanitization on all user-generated content output
40- Helmet + CSP + HSTS + rate limiting on all endpoints
41- GlitchTip error monitoring from first deployment
42- No raw SQL -- Drizzle ORM with parameterized queries only
43- LinkedIn import data is untrusted -- mapper must validate and sanitize every CSV field
44- AT Protocol service layer wraps all interactions with user PDS instances and the Barazo AppView
45- Health checks: `GET /api/health` (process), `GET /api/health/ready` (dependencies)
46
47---
48
49## Project-Wide Standards
50
51### About Sifa
52
53Decentralized professional identity and career network built on the [AT Protocol](https://atproto.com/). Portable profiles, verifiable track record from real community contributions, no vendor lock-in.
54
55- **Organization:** [github.com/singi-labs](https://github.com/singi-labs)
56- **License:** Source-available (sifa-api, sifa-web) / MIT (sifa-lexicons)
57
58### Coding Standards
59
601. **Test-Driven Development** -- write tests before implementation (Vitest).
612. **Strict TypeScript** -- `strict: true`, no `any`, no `@ts-ignore`.
623. **Conventional commits** -- `type(scope): description`.
634. **CI must pass** -- lint, typecheck, tests, security scan on every PR.
645. **Input validation** -- Zod schemas on all API inputs and Jetstream records.
656. **Output sanitization** -- DOMPurify on all user-generated content.
667. **No raw SQL** -- Drizzle ORM with parameterized queries only.
678. **Structured logging** -- Pino logger, never `console.log`.
689. **Pin exact versions** -- no `^` or `~` in package.json.
6910. **Named exports** -- prefer named exports over default exports.
70
71### Git Workflow
72
73All changes go through Pull Requests -- never commit directly to `main`. Branch naming: `type/short-description` (e.g., `feat/endorsement-api`, `fix/import-validation`).
74
75### AT Protocol Context
76
77- Users own their data (stored on their Personal Data Server)
78- The AppView (sifa-api) indexes data from the AT Protocol Jetstream
79- Lexicons (`id.sifa.*`) define the professional profile data schema
80- Identity is portable via DIDs -- no vendor lock-in
81- All record types are validated against lexicon schemas
82- Sifa reuses `forum.barazo.*` lexicons for timeline posts and `community.lexicon.*` for location/calendar