-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Digitalisierung ohne Prozessänderung — digitize the paper notice board without changing how the organization works.
Aushang is a privacy-by-construction digitization layer for old-school German organizations — Kitas, Vereine, Kirchengemeinden, Kleingartenkolonien, small businesses. They keep pinning paper to their physical board; one admin photographs it from inside the app; the system OCRs and redacts PII locally before any LLM call, an LLM extracts structured content + dates from the redacted text only, the admin reviews and confirms, and members get a private feed, browsable category libraries, a shared calendar, an ICS subscription, and an email digest. Ships as a PWA and a native Android app (Capacitor). The repo is named DIGITNEWS; the product is Aushang (working title — all branding lives in one file, src/config/brand.ts).
Stack: Next.js 16 (App Router) · React 19 · TypeScript (strict) · Tailwind v4 · Supabase EU (Postgres + Auth + Storage, RLS on every table) · Python FastAPI worker (Tesseract + Microsoft Presidio + spaCy) · Claude (claude-haiku-4-5) extraction, Mistral-EU / OpenAI / Gemini optional · Resend email · Web Push · Vercel + VPS (Docker).
Deep-dive pages: Architecture · Workflows · Security Model · Data Model · Design Decisions · Setup and Deployment
| Problem | Old-school orgs run their comms on a physical notice board. They won't change that process. |
| Solution | Photograph the board → OCR → local PII redaction → LLM structuring → admin review → private digital feed/calendar/ICS/email. The process on the wall is untouched. |
| Hard rule | The tool processes only what the org already posted publicly to its own board. No new data collection. |
| Surfaces | PWA (web), native Android shell (Capacitor remote-URL), per-user ICS calendar feed, email digest, web push. |
| Languages | German is the source of truth; UI + content auto-translated to English + Russian at publish. |
Live and in real-world testing. Phases 1–5 are built and the full pipeline runs end-to-end in production.
| Item | State |
|---|---|
| Web app | Live on Vercel at kita-connect.cloud |
| OCR/redaction/extraction worker | Built + tested; runs on a VPS (Docker) |
| First customer | One Kita testing in production |
| Hardening roadmap | Tracked follow-ups before general availability: TLS termination in front of the worker, a generated DB types file, promoting CSP to enforcing, and enabling AI cover images via an EU image endpoint. |
This is the standout of the project — see Security Model for the full treatment.
photo (raw, private bucket)
│ short-TTL signed URL
▼
[ VPS WORKER — runs entirely off the client ]
OpenCV deskew → Tesseract OCR (German) → text
│
▼ LOCAL PII redaction (Presidio + spaCy + German regex pack), FAIL-CLOSED
redacted text: "Bitte melden bei [NAME_1], Tel. [TEL_1]"
│
▼ ONLY redacted text crosses this line
== EXTERNAL LLM CALL == (Claude default; never raw images, never raw PII)
The LLM never sees the raw image or raw PII. Placeholders like [NAME_1], [TEL_1], [EMAIL_1], [IBAN_1], [GEB_1] are preserved verbatim end-to-end. The provider key lives only on the worker — the web app never calls an LLM and never holds the key.
Three roles, multi-tenant by org_id. Operator-provisioned — no public signup, no self-service join.
| Role | Scope | Can |
|---|---|---|
superadmin (operator) |
Cross-org | Create orgs, add/remove the first admin per org, grant/revoke admin. The one intended cross-tenant exception. |
admin |
Own org only | Capture, review, publish, take down; add/remove members; release clear photos. Cannot touch other orgs or add admins. |
member |
Own org, read-only | Read published posts + confirmed events; subscribe to ICS, digest, push; opt into clear-photo + UI language. |
| # | Principle |
|---|---|
| 1 |
LLM advises, deterministic code decides. Nothing publishes without explicit admin confirmation; all LLM output is schema-validated. Routing reads only the admin-confirmed content_type, never the LLM's suggestion. |
| 2 | Privacy by construction. PII is detected + masked locally before any external API call; fail-closed. Raw photos never leave the org's own infrastructure to an LLM. |
| 3 | Only published information. The tool processes only what the org already posted to its own board. |
| 4 |
Deny by default. No public surface except /login, /auth/*, /api/ics/*, /apply/*, /api/worker/*, and /datenschutz. Everything else requires auth. |
| 5 | Secret boundary. No server secret in the client bundle (a CI scan blocks the build if one leaks); the service-role key + LLM key are server/worker-only. |
| Page | What's inside |
|---|---|
| Architecture | System shape, the three Supabase clients, four-layer authz, app vs worker split |
| Workflows | Capture → OCR → redact → LLM → review → publish; provisioning; translation; ICS/email/push |
| Security Model | The privacy/PII pipeline, GDPR posture, RLS + column REVOKE, photo consent, adversarial reviews |
| Data Model | Tables, content_type taxonomy, migrations 0001–0030, PII columns |
| Design Decisions | Why redact text not image, why multi-provider, why operator model, rejected ideas |
| Setup and Deployment |
npm run setup, Supabase provisioning, deploying the worker, env contract |
Aushang — Privacy-by-construction notice-board digitization · Repository · Built by Eugen Müller
Overview
Deep dives