Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# AGENTS

- Never add credentials, emails, internal URLs, or infra IDs.
- Docs must stay public-safe; architecture only.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Zosavi Public Docs

Public-safe engineering notes for Zosavi, a privacy-focused scan pipeline that pairs a mobile client with an event-driven backend and LLM-assisted analysis. These docs share architecture thinking only and intentionally omit operational runbooks or credentials.

## Contents

- [Architecture overview](docs/architecture/zosavi-architecture-overview.md)
- [Architecture decisions](docs/adr/)

Public-safe note: No source code, secrets, or deployment details live here; this repo only captures high-level architecture rationale.
9 changes: 9 additions & 0 deletions docs/adr/0001-event-driven-scan-pipeline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ADR 0001: Event-driven scan pipeline

Status: Accepted

Context: Scans need to be processed asynchronously so uploads stay fast and workloads can burst without blocking the client.

Decision: Use an event/queue-driven pipeline where edge handlers enqueue work for dedicated scan processors.

Consequences: Adds a queueing dependency and retry semantics, but keeps client latency low and lets processors scale independently.
9 changes: 9 additions & 0 deletions docs/adr/0002-guardrail-first-llm-orchestration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ADR 0002: Guardrail-first LLM orchestration

Status: Accepted

Context: Model calls must stay bounded and auditable to prevent untrusted outputs from reaching clients.

Decision: Run all LLM work inside a lightweight orchestrator that enforces tool allowlists, step limits, schema validation, and deterministic decoding where needed.

Consequences: Orchestrator logic becomes a critical path component, but it centralizes safety policy and observability.
9 changes: 9 additions & 0 deletions docs/adr/0003-structured-results-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ADR 0003: Structured results contract

Status: Accepted

Context: Downstream features need predictable outputs from scan analysis and should not depend on free-form model text.

Decision: Require scan processors to emit structured results that conform to a versioned schema, with validation and safe fallback states on errors.

Consequences: Increases upfront schema work, but simplifies client integrations, migrations, and incident triage.
112 changes: 112 additions & 0 deletions docs/architecture/zosavi-architecture-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Zosavi Architecture Overview

> Public-safe overview; intentionally omits sensitive implementation details, secrets, and vendor-specific endpoints.

## High-level system architecture

```mermaid
flowchart LR
subgraph Client
mobile[Mobile app]
end
subgraph Edge
api[Edge API / lightweight functions]
notifications[Notification service]
end
subgraph Core
firestore[Document DB]
storage[Object storage]
queue[Task / event queue]
worker[Scan processors]
telemetry[Observability + tracing]
end
subgraph Intelligence
orchestrator["LLM orchestrator / agent runtime"]
tools["Tool adapters: retrieval, scoring"]
provider["External LLM provider"]
end

mobile -->|Uploads assets + metadata| api
api --> storage
Comment on lines +29 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align asset upload path across architecture sections

The high-level diagram currently shows uploads flowing from Mobile app -> Edge API -> Object storage, but the Data flow and Trade-offs sections describe direct client uploads to object storage (Mobile->>Store and “Client uploads first”). This internal contradiction makes the documented architecture ambiguous for readers trying to understand trust boundaries and validation responsibilities, so one of these paths should be updated to match the intended design.

Useful? React with 👍 / 👎.

api --> firestore
firestore --> queue
queue --> worker
worker --> orchestrator
orchestrator --> tools
orchestrator --> provider
provider --> orchestrator
orchestrator --> worker
worker --> firestore
worker --> telemetry
worker --> notifications
notifications --> mobile
```

## Data flow

```mermaid
sequenceDiagram
participant User
participant Mobile as Mobile app
participant Edge as Edge API
participant Store as Object storage
participant DB as Document DB
participant Queue as Task queue
participant Worker as Scan processor
participant Orchestrator as LLM orchestrator
participant LLM as LLM provider
participant Notify as Notification svc

User->>Mobile: Capture scan (image/text) + submit
Mobile->>Store: Upload redacted asset
Mobile->>Edge: Create scan session (status=pending, asset ref)
Edge->>DB: Persist session record
DB-->>Queue: Event triggers queued work
Queue-->>Worker: Deliver job with session pointer
Worker->>Store: Fetch asset (signed URL / scoped token)
Worker->>Orchestrator: Provide normalized payload + context
Orchestrator->>LLM: Call model with guarded prompt/tool spec
LLM-->>Orchestrator: Structured analysis result
Orchestrator-->>Worker: Final output + safety verdicts
Worker->>DB: Update session (status=completed|failed, result)
Worker->>Notify: Send push/email hook
Notify-->>Mobile: Deliver user-facing notification
Mobile->>DB: Refresh session via listener/poll
```

### LLM orchestration

- **Agent loop**: Workers hand off to a lightweight orchestrator that runs a bounded agent loop (max tool hops, latency budget). Each step enriches context with intermediate results to avoid repeated API calls.
- **Tool calls**: The orchestrator supports tool plugins (e.g., retrieval, scoring, formatting). Tools declare schemas and side effects; calls are logged with trace IDs for audit.
- **Guardrails**: Pre-flight validators redact obvious PII, clamp token budgets, and require allowlisted tools. Post-processing enforces JSON schema validation, truncates oversized fields, and downgrades the session to a safe failure when validation fails—never exposing raw model text to clients.
- **Safety tiers**: Different routes can select conservative model tiers and enable deterministic decoding for user-visible summaries, while background scoring can opt into higher-variance settings.

### State management

- **Entities**: Scan session (id, status, asset pointer, structured result, retry count), user profile (tier, notification tokens), and observability spans (trace IDs, timing).
- **Persistence vs. ephemeral**: Durable state lives in the document database; large binaries stay in object storage; transient orchestration state (agent scratchpad, tool responses) remains in-memory per job.
- **Idempotency**: Session records include status + revision fields; workers short-circuit when a job replays and the session is already terminal. Storage uploads use content hashes to avoid duplicate processing.
- **Retries**: Queue-level retries are backoff-controlled; model errors trigger bounded retries with circuit breakers. Failed sessions mark a retry hint so clients can re-submit safely.

## Trade-offs

- **Serverless vs. long-running workers**: Functions/queues keep ops light and scale to bursts but add cold-start latency; dedicated workers would reduce latency but increase ops overhead.
- **Client uploads first**: Uploading assets directly to storage minimizes edge load but requires strict validation and signed URLs to prevent abuse.
- **Central orchestrator**: A single orchestration layer simplifies policy and telemetry, yet concentrates failure domains; mitigation is heavy tracing and feature-flagged fallbacks.
- **LLM dependency**: Offloading to an external LLM accelerates iteration but adds cost and latency variance; caching + schema validation reduce waste and regressions.

## Scaling considerations

- Horizontal scale via the task queue; concurrency tuned per region to balance throughput and model quota limits.
- Use partition-friendly keys in the document store to avoid hot shards; fan-out writes for large batches.
- Streaming uploads + chunked downloads to keep memory bounded for large assets.
- Backpressure signals (queue depth, latency SLOs) feed autoscaling policies and can trigger graceful degradation modes (reduced tool set, lower-fidelity summaries).
- Warm paths (pre-provisioned workers, connection pooling) reduce cold-start impact on peak hours.

## Lessons learned

- Keep the session record authoritative and immutable except for status/result fields; everything else is derived to simplify retries.
- Validate and normalize all payloads before they hit the LLM to reduce downstream cost and noisy failures.
- Observability is a feature: trace IDs through client, queue, orchestrator, and model calls make incident triage far faster.
- Explicit safety fallbacks (safe failure states, redaction, conservative decoding) prevent the rare LLM glitch from leaking to end users.
- Small, deterministic schemas for model outputs are easier to evolve and migrate than free-form text blobs.