Authorization boundary, immutable evidence ingest, custody chain, and job orchestration for the Afterprint evidence-intelligence platform.
afterprint-api is the boundary every request to Afterprint crosses. It:
- Authenticates users via Freighter wallet signature (Stellar keypair, no passwords) — see SEP-53
- Enforces role-based permissions per case (
CASE_ADMIN,INVESTIGATOR,LEGAL_REVIEWER, etc.) - Issues presigned S3 upload URLs and records evidence as immutable, versioned objects with an append-only custody chain (enforced at the Postgres trigger level, not just in application code)
- Orchestrates background jobs (via BullMQ/Redis) that hand evidence to
afterprint-aifor processing and queue Stellar anchoring for custody events and attestations - Anchors integrity proofs on Stellar via the
afterprint-contractsregistries
afterprint-web → afterprint-api → Postgres (Supabase)
│ → S3-compatible storage (Supabase Storage)
│ → Redis (Upstash) — job queues
├────────→ afterprint-ai (evidence processing, AI analysis)
└────────→ Stellar Testnet (custody/attestation anchoring)
pnpm install
cp .env.example .env # fill in DATABASE_URL, REDIS_URL, AI_URL, S3_*, etc.
pnpm prisma generate
pnpm prisma migrate deploy
pnpm dev # API on :4000, hot reload
pnpm worker # background job worker, separate processpnpm build # tsc
pnpm test # unit tests (node:test)
pnpm typecheck
pnpm format:check # prettierAfter evidence is processed, the worker records a SHA-256 of a manifest (digests and opaque references only, never evidence content) on the evidence_anchor_registry contract from afterprint-contracts. Choose a signing method in .env:
| Method | Set | Notes |
|---|---|---|
| In-process | STELLAR_SIGNER_SECRET, STELLAR_EVIDENCE_ANCHOR_CONTRACT |
The worker builds, signs, and submits the Soroban transaction. The key must be the registry's controller. Testnet only. |
| Signing service | STELLAR_ANCHOR_SERVICE_URL, STELLAR_SIGNER_TOKEN |
Takes priority when set. |
With neither set, anchor jobs stay pending and retry, so nothing is lost. Retrying is safe: the contract treats an identical anchor as a no-op and rejects a conflicting one. See src/anchor.ts.
See CONTRIBUTING.md for the workflow and coding standards, and SECURITY.md to report a vulnerability privately.
| GitHub | @helloworld1-star |
| devt14985@gmail.com |
