Zion Boggan
repos/Sightline
zionboggan.com ↗

Sightline

A private intelligence aggregation platform built around Automatic License Plate Recognition (ALPR) data. Sightline ingests Flock-style ALPR exports, normalizes and deduplicates them, maps camera networks, correlates vehicle sightings into investigation timelines, reconstructs...

1 commits First commit Jun 27, 2026 Last commit Jun 27, 2026 (1 month ago)
Python 63.1%TypeScript (React) 19.9%JSON 5.5%Markdown 4.8%TypeScript 3.4%CSS 1.6%Shell 0.8%YAML 0.7%
Files 123 entries
README.md

Sightline - ALPR / Flock Intelligence Platform

A private intelligence aggregation platform built around Automatic License Plate Recognition (ALPR) data. Sightline ingests Flock-style ALPR exports, normalizes and deduplicates them, maps camera networks, correlates vehicle sightings into investigation timelines, reconstructs movement and detects anomalies, manages watchlists and alerts, generates analyst reports, and enriches investigations with passive OSINT.

ALPR is the core product. OSINT enrichment is a supporting module.

Responsible-use note: ALPR data is privacy-sensitive. Sightline assumes the operator holds the data lawfully and is accountable for its use. Access control, full audit logging, source attribution, and configurable retention are first-class features so that use is traceable.


What works today (verified end-to-end against real PostgreSQL + Redis + Celery)

Capability Status
JWT auth + role-based access control (admin/analyst/viewer) ✅ verified
API-key auth (X-API-Key) for machine-to-machine, with revoke ✅ verified
OIDC / SSO login (config-gated, standard auth-code flow) ✅ implemented
CSV + JSON + PDF Flock-style ingest with column auto-mapping ✅ verified
Normalization (plate/timestamp/direction/confidence/geo) ✅ unit-tested
Deterministic dedup (idempotent re-import, sub-second burst collapse) ✅ verified
Async ingest via Celery worker (+ synchronous path) ✅ verified
Real-time stream ingest (push reads, no file) ✅ verified
API connectors (generic JSON-REST poller, webhook) ✅ verified
Plate / partial-plate / unified search ✅ verified
Movement intelligence: route reconstruction, haversine speed, impossible-travel anomaly detection, dwell, frequency, co-travel, camera transitions ✅ unit-tested + live
Watchlists + inline hit generation + history backfill ✅ verified
Investigation timeline + entity graph ✅ verified
Evidence with SHA-256 chain-of-custody + integrity-checked download ✅ verified
Report generation (Markdown/JSON/CSV/PDF) with auto key-findings ✅ verified
OSINT enrichment plugins (DNS, RDAP, crt.sh, IP/ASN, security.txt, robots, GitHub, TLS) ✅ verified
Pluggable storage (local filesystem / S3-compatible) ✅ verified
Retention enforcement (admin trigger + scheduled Celery beat, cascade-safe) ✅ verified
Immutable audit log on every mutation (entity-linked) ✅ verified
In-process rate limiting

Frontend is a complete Next.js app (17 routes) wired to the live API: dashboard, investigations list/detail with evidence + report export, plate search, camera map + detail, vehicle profile, entity graph, watchlist manager, alerts, ALPR import, OSINT panel, audit log, and an admin console (settings, retention, API keys, connectors, users, sources).

Quick start (Docker)

cp .env.example .env
docker compose up --build
# API   → http://localhost:8000/docs   (seeded automatically)
# UI    → http://localhost:3000
# login → admin@sightline.app / changeme123

Quick start (local backend)

cd backend
python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt

# point at a Postgres instance
export SIGHTLINE_DATABASE_URL="postgresql+psycopg2://sightline:sightline@localhost:5432/sightline"
alembic upgrade head
python seed.py                      # admin@sightline.app / changeme123 + sample data
uvicorn app.main:app --reload       # http://localhost:8000/docs

pytest                              # 16 tests: pipeline + analytics, no DB required

Architecture

Next.js (TS) ──REST+JWT──▶ FastAPI ──▶ PostgreSQL (pg_trgm partial-plate search, FTS-ready)
                              │     └──▶ Redis + Celery (ingest, enrichment, retention jobs)
                              └──────────▶ Object store (evidence + raw import blobs)
Parser pipeline: CSV/JSON/PDF → normalize → dedup → persist → watchlist eval → analytics → audit

Full design - schema, API routes, parser pipeline, analytics, frontend plan, file tree - is in docs/DESIGN.md.

Demonstration highlight: impossible-travel detection

The seeded data includes a plate (GHI5566) observed at two cameras 13.6 km apart only 60 seconds apart. The movement engine computes the implied speed (818 km/h) and flags it:

GET /api/v1/vehicles/GHI5566/movement
→ "anomalies": [{ "reason": "impossible_travel_speed", "speed_kmh": 817.8, ... }]

This surfaces likely plate misreads or cloned plates - a core ALPR analytic.

Project layout

Sightline/
├── docker-compose.yml          # postgres, redis, api, worker, beat, frontend
├── docs/DESIGN.md              # full architecture & schema
├── backend/                    # FastAPI + SQLAlchemy + Alembic + Celery
│   ├── app/
│   │   ├── core/               # config, security, storage, rate limit, permissions
│   │   ├── api/routes/         # auth, oidc, investigations, imports, live, evidence,
│   │   │                       #   search, cameras, watchlists, enrichment, api-keys,
│   │   │                       #   reports, admin
│   │   ├── services/           # normalize, dedup, ingest, parsers (csv/json/pdf),
│   │   │                       #   analytics, watchlist, reporting, report_pdf,
│   │   │                       #   connectors, retention, enrichment plugins
│   │   └── workers/            # celery app + tasks (ingest, enrichment, retention)
│   ├── alembic/                # migrations
│   ├── seed.py                 # idempotent sample-data loader
│   ├── sample_data/            # Flock-style CSV + JSON + PDF exports
│   └── tests/                  # pytest: pipeline + analytics (17 tests)
└── frontend/                   # Next.js App Router (TypeScript) - 17 routes

Security & operations

  • RBAC: viewer (read), analyst (read/write/ingest/enrich/export), admin (all). Enforced per route; verified by an automated permission matrix.
  • Audit: every mutation writes an immutable audit_logs row (actor, action, entity, metadata).
  • Idempotent ingest: content SHA-256 short-circuits re-uploads; a per-read dedup hash prevents double-counting.
  • API keys: per-user keys, SHA-256 hashed at rest, plaintext shown once, revocable; authenticate machine clients via the X-API-Key header.
  • Evidence chain-of-custody: every file is SHA-256 hashed on upload; downloads re-verify the hash and the audit trail records upload/download events per artifact.
  • Retention: cascade-safe purge (reads + dependent sightings/hits) via admin trigger or the scheduled daily-retention Celery beat task.
  • Pluggable storage: local filesystem in dev, S3-compatible (MinIO/R2/Wasabi/AWS) in prod, selected by SIGHTLINE_STORAGE_BACKEND - evidence and raw import blobs both flow through it.
  • Input safety: upload size caps; parsers are row-resilient (a bad row is logged, never fatal); enrichers and connectors degrade to clean errors instead of crashing ingest.

Tech stack

FastAPI · SQLAlchemy 2.0 · Alembic · PostgreSQL · Redis · Celery · Pydantic · python-jose · bcrypt · pdfminer.six · reportlab · boto3 · Authlib · Next.js 14 · React 18 · TypeScript · Leaflet.