Automated facility security-audit pipeline. A staff member uploads a walkthrough video of a school building; the system processes it and flags physical security and safety vulnerabilities — propped/unlocked doors, broken locks, obstructed or damaged cameras, open gates, blocked fire exits, damaged perimeter fencing — so administrators can take preventive action.
This is decision-support, not autonomous enforcement: the system produces evidence-linked findings; a human reviews and acts.
Scope (v1 demo): empty-building walkthrough footage, batch (uploaded files), local Kubernetes. No behavioral/student detection. People-in-frame handling is deferred.
┌─────────────┐
browser ──────▶│ frontend │ (React/Vite + nginx)
└──────┬──────┘
│ REST
┌──────▼──────┐ ┌──────────────┐
│ api │───────▶│ postgres │ (StatefulSet)
│ (FastAPI) │ └──────────────┘
└──┬────────┬─┘
presign PUT │ │ enqueue job
▼ ▼
┌──────────┐ ┌───────┐
│ MinIO │ │ Redis │ (broker/queue)
│ (S3 API) │ └───┬───┘
└────┬─────┘ │ consume
│ ┌────▼────────┐ ┌──────────────┐
└──────▶│ worker │─────▶│ inference │ CV model
download │ (Celery) │ │ (FastAPI) │
└──────┬──────┘ └──────────────┘
│ HTTPS
▼
Anthropic API (Claude vision)
Hybrid detection: a fast CV pass (YOLO-class object detector) handles objective signals (door open/closed, gate, camera presence); a selective Claude vision pass handles nuanced judgments (obstructed lens, exit blocked by storage, door that should be secured). Both sit behind one Detector interface so either can be swapped or disabled.
| Layer | Choice |
|---|---|
| Frontend | TypeScript + React (Vite) |
| API / workers | Python + FastAPI, Celery |
| Queue / broker | Redis |
| Database | Postgres |
| Object storage | MinIO (S3-compatible) |
| Orchestration | Kubernetes via kind (local) |
| Dev loop | kubectl + Makefile (Skaffold later) |
- Docker (running)
kindandkubectl— the bootstrap script installs them if missing.
# 1. Create the local cluster (installs kind/kubectl if missing)
make cluster-up
# 2. Deploy stateful infrastructure (Postgres, MinIO, Redis)
make infra-up
# 3. Watch it come up
kubectl get pods -n safe-school -wAccess:
- MinIO console → http://localhost:9090 (user/pass in
deploy/k8s/infra/minio.yaml) - Postgres →
make psql
Tear down:
make infra-down # remove app workloads, keep cluster
make cluster-down # delete the kind clusterdeploy/
kind/cluster.yaml # local cluster definition (3 nodes: 1 control-plane, 2 workers)
k8s/infra/ # Postgres, MinIO, Redis manifests (kustomize)
scripts/ # bootstrap / teardown
services/ # api, worker, inference (later milestones)
frontend/ # React app (later milestone)
Makefile # convenience targets
.env.example # documented environment variables
An end-to-end smoke test runs the whole stack in Docker Compose (Postgres + Redis + MinIO + api + worker) and exercises the real pipeline:
make smoke # up -> create/upload/complete -> worker processes -> assert findings -> teardown
make k8s-validate # statically render all kustomize overlaysmake smoke is the fastest confidence check that everything talks to each other.
- M1 — Repo skeleton + local cluster + stateful infra (Postgres, MinIO, Redis)
- M2 — API + DB schema (upload presign, jobs, findings, schools)
- M3 — Worker + queue with a mock detector
- M4 — Real detectors (CV inference pod + Claude vision behind
Detectorinterface) - M5 — Frontend (upload + reviewer dashboard with timeline)
- M6 — School-map context, finding dedup, remediation report export