# CaseSignal: online development, portable deployment

Research and architecture decision • October 24, 2026

## Recommendation

Continue the existing Python application as a portable core, add protected intake and case-scoped retrieval, and run an open-weight model behind a replaceable inference interface. Develop and test online, then distribute the same application release with hardware-specific model runtimes. Do not train a foundation model or make a hosted AI service mandatory. This is an architecture recommendation based on official documentation, not a measured model ranking.

The actual source currently uses a Python development HTTP server, separate agency SQLite databases, local originals, agency/case permissions, and scheduled local full backups. The published Site is a static preview and download surface. There is no working hosted Python backend, live AI, automatic government retrieval, quarantine, or malware scanner. Vercel/Supabase migration has not occurred. Preserve the agency isolation already built rather than performing a speculative rewrite.

## What “standalone” means

| Mode | Evidence and AI | New public records | External dependencies |
|---|---|---|---|
| Hosted pilot | Private hosted application, storage, workers and model | Permitted online sources | Hosting, internet, enabled search engines |
| Agency machine with internet | Local application, storage, workers and model | Same connectors as hosted edition | Queries and fetch requests leave the machine |
| Disconnected agency machine | Local application, storage, workers and model | Previously imported documents only | Preloaded dependencies, weights, OCR assets and signatures |

Fresh nationwide searches cannot happen without internet access. Search engines do not expose every government record. Local analysis is feasible offline after installation assets are supplied; it does not mean fresh public records are available offline.

“Any hardware” means supported hardware profiles, not one binary on every device. Use Linux x86-64 with NVIDIA for the first reproducible server profile, then validate Apple Silicon and CPU-only profiles separately. Windows can use a validated Linux VM/WSL2 profile or supported native runtime. Containers do not supply missing GPU drivers or translate CPU architectures automatically.

## Model and runtime selection

| Candidate | Reason to test | Limitation |
|---|---|---|
| Ministral 3 8B Instruct 2512 | Official Apache-2.0 model, text/vision, English/Spanish, structured output; official GGUF artifacts available | Published 12 GB FP8 fit is not a guarantee for long context, concurrency or our workload |
| Qwen3.5-9B | Current multimodal alternative with Apache-2.0 model card and documented serving options | Validate exact runtime build, quantization and tool/citation behavior |
| Qwen3-8B | Earlier text baseline for reproducible comparison | Text-only choice; not the newest Qwen candidate |

Begin with Ministral; compare Qwen3.5-9B on the same evidence and questions. Keep the earlier Qwen3-8B only as an optional baseline. Model cards and general benchmarks do not establish investigative accuracy. Pin model revision, tokenizer, chat template, quantization, vision projector if required, license/NOTICE and checksums. Evaluate the actual quantized deployment, not just full-precision benchmark results.

Use llama.cpp as the first portability runtime: its project supports CPU, Apple Silicon, GPU backends, quantization, Docker/binaries and an OpenAI-compatible server. This API format does not require sending requests to OpenAI. Ollama is a reasonable developer convenience; keep its interface behind our adapter. Add vLLM when GPU concurrency benchmarks justify another runtime. Share the application API contract; hardware-specific runtime artifacts may differ. Do not assume identical outputs across engines.

No fine-tuning initially. Case facts should be retrieved with citations, not trained into shared model weights. Fine-tuning later requires a demonstrated evaluation gap and separately approved training material.

## Retrieval and correlation design

Enforce Agency → authenticated user → authorized case before retrieval, export, background jobs or inference. A case can have multiple assigned users. Agency administrators remain limited to their agency. No shared cross-agency evidence index or model conversation memory. Jobs retain agency, case and actor IDs; recheck access when executing and returning results.

The pipeline is: authorized query → bounded retrieval plan → source search → source capture → file quarantine/scan → isolated extraction → exact and semantic retrieval → suggested connections → cited response → detective review. The model can propose a search, but backend policy authorizes the source and executes bounded tools. It receives no shell, database credentials or unrestricted network tool.

Normalize identifiers deterministically while preserving originals. Phone matches require country context; email rules must avoid silently rewriting meaningful characters; names and OCR require ambiguity handling. A repeated phone may be a shared office or recycled number. A registration may identify a registered agent rather than an owner. Duplicated websites do not establish independent corroboration.

Store individual assertions and their supporting passages rather than merging people automatically: subject, relationship, object, source/document hash, page or timestamp, record date, retrieval time, extraction method, contradictions, review state and reviewer. Separate occurrence, candidate association and detective-verified relationship. Never convert a model confidence number into a probability of identity. Explain missing evidence and abstain when unsupported.

Use exact matching for identifiers plus full-text retrieval. Add locally computed embeddings and reranking to find context and paraphrases; semantic similarity is not proof of identity. For hosted scale, evaluate PostgreSQL + pgvector/full-text search. Keep tenant filtering within the authorized query, including vector queries. Existing per-agency SQLite remains the current development store; database migration needs explicit export/import validation. A separate graph database is unnecessary for the first relationship view.

## Public search without data subscriptions

Start with free official government APIs/downloads and approved website retrieval. SEC's company submissions/XBRL APIs require no API key, but are company-financial sources, not nationwide reverse-phone databases. Add other official sources only after confirming scope, published rate limits and access rules. The registry must include official state/county portals outside .gov after ownership verification.

Offer investigator-opened search links and document imports for portals without supported automation. Test a private SearXNG instance as an optional discovery adapter. Its query API forwards queries to upstream search services; it is not an independent national records database. Upstream CAPTCHAs and blocking remain possible. Engine configuration and reuse terms must be checked source by source; SearXNG does not grant permission. Do not depend on random public instances or promise unlimited free automated searches. If an engine blocks access, show that status and use a permitted/manual alternative.

Search queries may reveal target identifiers to the search provider even when the model is local. Send the minimum approved identifier, not full case narratives or attachments. Record source coverage as searched, unavailable, blocked/manual or not connected. Deduplicate results and preserve final URL, retrieval time, source hash and relevant passage. Snippets are leads until the original is retrieved and checked. Validate redirects, resolved addresses, schemes, content type/size and timeouts to prevent SSRF and unsafe downloads. Government domain suffix alone is insufficient provenance validation.

## Files, security and recovery

Preserve original bytes/hash in quarantine; validate actual file type and limits; scan with ClamAV; distinguish pending, clean, detected, failed, unavailable, encrypted and limit-exceeded. Failed or unavailable scans must not silently release a file. Scanner updates need internet or an approved offline signature transfer. A clean result is not a safety guarantee. Never submit evidence to public sample-analysis services by default.

Evaluate Docling for local PDF/layout/OCR extraction. Preserve page coordinates and original text, and label OCR uncertainty. Preload required models for disconnected use. Use isolated, non-root workers with network denied, read-only input, output limits, CPU/RAM/time quotas and minimal parsers. Later audio/video processing needs separate transcription and frame sampling with timestamps; an LLM alone does not provide reliable complete video analysis. Treat text from pages/files as untrusted data, including instructions embedded within them.

Hosted deployment needs a production server/proxy, TLS, private model endpoint, secure cookies, MFA/SSO, rate limits, tenant tests, protected secrets and monitoring. Keep the current development HTTP server out of direct internet exposure. Turnstile is an online dependency: a disconnected edition needs separately implemented and tested local authentication protections; do not silently disable the existing fail-closed behavior.

Current daily full backups and isolated restore checks remain local and unencrypted. Plan encrypted, deduplicated snapshots using restic over consistent database exports/originals, separate agency encryption boundaries, protected recovery keys, retention and restore drills. Hashes alone do not make audit trails tamper-proof. Do not claim backups are operational online until scheduled runs and recovery succeed there. Copying software creates a new empty agency installation by default, not a copy of another agency's evidence or credentials.

## Hosting and sizing decision

Prefer a rented Linux application server plus a private rented GPU for a fictional-data pilot. Runpod Pods support control of the container environment; that fits testing our own runtime and later moving it. Hugging Face dedicated endpoints support custom containers and reduce model operations work, but do not host the entire CaseSignal evidence/security workflow. Neither option is selected for real agency data solely on technical capability. Location, access, retention and agency requirements need separate assessment.

Do not make Vercel-only functions or proprietary hosted storage/auth necessary for the portable core. A managed web frontend can remain optional. Separate application, storage, identity and inference behind documented interfaces before substituting managed services.

Planning targets, not hardware benchmarks: 32 GB system RAM with 12–16 GB GPU memory for a bounded single-request small-model evaluation; prefer 64 GB RAM, 24 GB GPU memory and 1–2 TB NVMe for pilot headroom. Start around 8k context, queue requests and measure peak RAM/VRAM, time to first token, throughput, extraction duration and evidence growth. CPU-only operation is a compatibility profile; acceptable latency is unproven. Heavy video and concurrency require separate sizing. Do not buy hardware until benchmark results exist.

Hosting cost is hourly compute × active hours + retained volumes + application host + backups/transfer/monitoring. As arithmetic examples, a quoted $0.50/hour GPU costs $50 for 100 hours or about $365 for 730 hours before other charges. These are not provider quotes. Stopping compute may leave storage charges. Earlier $150–$300 total estimates are provisional, not a verified always-on budget. No hosting or data subscription was purchased in this work.

## Build sequence and acceptance

1. Package the current core with reproducible dependencies and bundle verification. Replace the development web server for hosted operation; validate TLS/login/case isolation on the real runtime.
2. Add quarantine/scanning and isolated PDF/OCR extraction with page citations. Test damaged, oversized, encrypted and malicious fixtures.
3. Add a model adapter and case conversation storage; test Ministral vs Qwen3.5 on identical fictional cases. Keep inference server private.
4. Add bounded official-source retrieval and optional SearXNG discovery; record coverage, provenance, blocking and query disclosure.
5. Add relationship assertions, contradictions and detective review. Measure evidence-supported claims rather than fluent answers.
6. Export the exact release to a fresh supported machine; restore synthetic agency data; disconnect internet; verify local search/chat and inspect attempted egress. Test online retrieval separately after reconnection.

Proposed evaluation: at least 100 labeled fictional/consented tasks, including shared/recycled numbers, similar names, outdated filings, OCR errors, contradictory dates, duplicate sources and prompt-injection text. Measure identifier precision/recall, supported-claim/citation rate, false merges, abstention, latency, cost and tenant leakage. Any unauthorized cross-agency disclosure or unsupported automatic identity merge blocks pilot release. Proposed numeric quality thresholds must be agreed against a labeled dataset; none has been measured yet.

## Implemented in this update

Added this decision record, an online research page and a read-only offline bundle checker with tests. The checker verifies required application/runtime/model/license artifacts against a supplied SHA-256 manifest, rejects unsafe/duplicate paths and reports missing/corrupted files. It makes no network calls and never executes artifacts. It is preparation for distribution, not an AI integration, installer, signed release or offline-readiness certification.

Run: `python backend/portable_check.py --bundle /path/to/release --manifest /path/to/manifest.json`.

Manifest schema: `{"schema":1,"artifacts":[{"role":"model","path":"models/model.gguf","sha256":"<64 lowercase hexadecimal characters>"}]}`. Include at least one verified artifact of each role: application, runtime, model and license. Hashes must come from a trusted release manifest; sign that manifest in a later release process. Never put secrets or case data in the software bundle.

## Primary references

- [Ministral model card and FP8 requirements](https://huggingface.co/mistralai/Ministral-3-8B-Instruct-2512)
- [Official Ministral GGUF artifacts](https://huggingface.co/mistralai/Ministral-3-8B-Instruct-2512-GGUF)
- [Qwen3.5-9B model card](https://huggingface.co/Qwen/Qwen3.5-9B)
- [Qwen3-8B baseline](https://huggingface.co/Qwen/Qwen3-8B)
- [llama.cpp runtime and hardware backends](https://github.com/ggml-org/llama.cpp)
- [SearXNG search API](https://docs.searxng.org/dev/search_api.html) and [upstream blocking](https://docs.searxng.org/admin/searx.limiter.html)
- [SEC free APIs and coverage](https://www.sec.gov/search-filings/edgar-application-programming-interfaces)
- [Docling local extraction](https://github.com/docling-project/docling)
- [ClamAV scanner protocol](https://docs.clamav.net/manual/Usage/ClamdProtocol.html)
- [PostgreSQL vector and hybrid search](https://github.com/pgvector/pgvector)
- [restic design and encryption](https://restic.readthedocs.io/en/stable/100_references.html)
- [Runpod Pods](https://docs.runpod.io/pods/overview) and [billing](https://docs.runpod.io/pods/pricing)
- [Hugging Face custom containers](https://huggingface.co/docs/inference-endpoints/en/guides/custom_container) and [pricing](https://huggingface.co/docs/inference-endpoints/en/support/pricing)


## Implementation follow-through — October 24, 2026

Protected intake and PDF page extraction are now coded. See INTAKE_GUIDE.md for logical quarantine, scan-gated access, Linux isolation, retries, page citations, migration and recovery. Live ClamAV and successful sandbox activation remain pending on a supported host. Earlier current-state descriptions above describe the research baseline. AI and automatic retrieval remain unimplemented.
