# Project export: Vault Form Agent

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Secure document locker and browser agent for redacted, human-approved form filling across sensitive workflows.
- Devpost: https://devpost.com/software/vault-form-agent
- GitHub: https://github.com/SonuSV7719/vault-form-agent
- Demo: https://sonuvishwakarma.netlify.app/
- Video: https://www.youtube.com/embed/OyWMqwMzveM?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Sonu Vishwakarma (3 commits)

## Devpost submission (written by the team)

### Inspiration

Filling government, healthcare, insurance, and enterprise forms is still a painful copy-paste workflow. The harder version is not just typing into fields: users need to find the right official site, understand what the form asks for, extract details from scattered documents, protect PII/PHI, avoid accidental submission, and keep an audit trail. Vault Form Agent explores what a safer form-filling agent should look like when documents are sensitive and the user still needs control.

### What it does

Vault Form Agent is an enterprise-grade web app with a secure document locker, redaction policy engine, chat-style form agent, visible browser runner, audit trail, CLI, and Codex/Claude-style skill scaffold. Users can upload any kind of document with a name, description, tags, metadata, sensitivity label, consent flag, and retention context. The backend extracts text from PDFs, scanned images, text files, JSON, and document-like inputs through a Docling-ready extraction layer with OCR fallbacks. Before data reaches the agent, built-in and custom redaction rules can mask PII/PHI such as emails, phone numbers, SSNs, dates of birth, member IDs, policy numbers, patient IDs, or any custom user-defined field. The agent page behaves like a chat workspace. A user selects whether the agent should use no documents, selected documents, all non-sensitive documents, or all documents. The user then describes the task in natural language, optionally enables web research, reviews the plan, and lets the browser runner prepare a real web form. The demo proves the process on a public Google Form: eight fields are matched and prepared while a submit guard prevents accidental final submission. Visual proof The GitHub README now includes an embedded visual walkthrough so judges and automated reviewers can see the project without hunting through folders: Agent chat workspace: https://github.com/SonuSV7719/vault-form-agent/blob/main/demo-recordings/chat-agent-redesign.png Real Google Form filled by the agent: https://github.com/SonuSV7719/vault-form-agent/blob/main/demo-recordings/google-form-filled-before-submit.png Corrected eight-field Google Form proof with submit guard: https://github.com/SonuSV7719/vault-form-agent/blob/main/demo-recordings/google-form-clean-8of8-submit-guard.png End-to-end demo recording: https://github.com/SonuSV7719/vault-form-agent/blob/main/demo-recordings/system-end-to-end-google-form-fill.mp4 Clean browser-fill recording: https://github.com/SonuSV7719/vault-form-agent/blob/main/demo-recordings/google-form-clean-8of8-submit-guard.webm How it works FastAPI backend manages the locker, extraction, redaction, planning, audit logs, and browser orchestration. React/Vite frontend provides a multi-page enterprise UI: Dashboard, Document Locker, Agent Chat, Redaction Settings, Approvals, and Audit. Redaction engine supports built-in rules plus custom regex, exact-value, dictionary, and metadata-key rules with multiple masking strategies. Browser runner uses labels, nearby context, DOM roles, JavaScript execution, and page analysis to prepare matching fields. Human-control guard rails keep high-risk actions, especially final submit, reviewable. CLI and skill folders make the capability testable as a developer workflow, not just a web app. How Codex and GPT-5.6 were used Codex with GPT-5.6 was used for the majority of the project: planning the architecture, designing the enterprise UI, generating and iterating backend services, building the React screens, writing the redaction and document-scope mechanisms, implementing the visible browser fill runner, creating sample data, producing demo recordings, and writing the README and docs. The key decisions made with Codex were: make the agent chat-first, require document scope selection, separate extraction from redaction, treat sensitive data as policy-controlled, keep submission human-approved, and include a reusable CLI/skill path for Codex-style workflows. Built during the hackathon The final repo includes setup instructions, sample data, demo recordings, security notes, architecture documentation, redaction handbook, browser-agent handbook, demo guide, visual walkthrough screenshots, and a hackathon submission sheet for judges. Demo proof The included demo assets show the app workflow and a real Google Form preparation run where eight fields are filled and final submission is blocked for safety.

## README (from the GitHub repository)

# Vault Form Agent

Vault Form Agent is an enterprise-grade prototype for secure, approval-gated document-to-form automation. It combines a metadata-rich document locker, scalable PHI/PII redaction policies, a Claude-style chat agent, official-site research, browser form execution, and audit logging.

The system is designed around HIPAA/PHI/PII-aware handling patterns. It is not a certified compliance product by itself; production HIPAA compliance also requires hosting controls, BAAs, policies, training, risk assessments, and operational governance.

## Highlights

- Chat-first agent workspace with document scope controls.
- Document locker for any file type with name, description, tags, metadata, sensitivity, and consent.
- Docling-ready extraction path with OCR fallbacks for PDFs and scanned images.
- Built-in and custom redaction rules for PHI, PII, financial, government, and internal identifiers.
- Official website research agent for prompts without known target URLs.
- Approval review before execution.
- Visible browser automation for typing, clicking, selecting, uploading, and pausing before final submit.
- Audit trail for document access, field use, approvals, and execution.
- CLI and agent-skill scaffold for Codex/Claude-style integrations.

## Demo

Primary end-to-end recording:

- [`demo-recordings/system-end-to-end-google-form-fill.mp4`](demo-recordings/system-end-to-end-google-form-fill.mp4)
- Corrected clean browser-fill proof: [`demo-recordings/google-form-clean-8of8-submit-guard.webm`](demo-recordings/google-form-clean-8of8-submit-guard.webm)
- Proof screenshot: [`demo-recordings/google-form-clean-8of8-submit-guard.png`](demo-recordings/google-form-clean-8of8-submit-guard.png)

The recording demonstrates:

1. Agent chat workflow.
2. Real-world Google Form test case.
3. Approval-gated execution.
4. Backend-launched Chrome session.
5. Real fields filled on a public Google Form.
6. Submit guard blocks final submission and leaves review to the user.

Sample files are in [`demo-data/`](demo-data/).

## Visual Walkthrough

### Agent chat workspace

The user selects document scope, enters a natural-language request, reviews the agent plan, and prepares the browser execution from a Claude-style chat surface.

![Vault Form Agent chat workspace](demo-recordings/chat-agent-redesign.png)

### Real Google Form filled by the agent

The browser runner opens a public Google Form and prepares the visible fields using the planned values.

![Google Form filled by Vault Form Agent](demo-recordings/google-form-filled-before-submit.png)

### Eight-field controlled browser proof

The corrected proof run shows eight fields prepared and final submit blocked by the safety guard.

![Eight-field Google Form proof with submit guard](demo-recordings/google-form-clean-8of8-submit-guard.png)

### Full workflow recording frames

These frames show the broader locker-to-agent-to-browser flow used in the demo recording.

![Vault full process frame](demo-recordings/vault-full-process-frame-25.png)

![Vault full process final frame](demo-recordings/vault-full-process-final-frame.png)

## Architecture

```mermaid
flowchart TD
    UI[React Enterprise Web App] --> API[FastAPI Backend]
    API --> Locker[Document Locker]
    API --> Redaction[Redaction Policy Engine]
    API --> Chat[Chat Agent Orchestrator]
    API --> Research[Official Site Research Agent]
    API --> Approval[Approval Workflow]
    API --> Audit[Audit Trail]
    Approval --> Browser[Visible Browser Agent]
    Locker --> Extract[Docling/OCR Extraction]
    Locker --> Store[(Document/Object Store Target)]
    Redaction --> Vault[(Secure Token Vault Target)]
    Chat --> Scope[Document Scope Enforcement]
```

## Local Run

Backend:

```powershell
cd backend
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 8010
```

Frontend:

```powershell
cd frontend
npm install
npm run dev -- --port 5173
```

Open:

- App: `http://localhost:5173`
- Backend health: `http://127.0.0.1:8010/health`

Docker compose is included for the target service topology. The current desktop demo uses local backend port `8010` so it does not collide with other services on `8000`.

## Product Flow

1. Upload documents in Locker.
2. Add document name, description, tags, metadata, sensitivity, and consent.
3. Configure redaction rules if custom fields need masking.
4. Open Agent Chat.
5. Choose document scope:
   - no documents
   - selected documents
   - all non-sensitive documents
   - all documents including sensitive
6. Enter or speak a prompt.
7. Agent researches official sites when needed.
8. Agent drafts field mappings and asks for review.
9. User approves.
10. Backend opens Chrome, fills the form, and stops before final submit.

## Repository Layout

```text
backend/            FastAPI service, agents, redaction engine, browser runner
frontend/           React + TypeScript enterprise web app
cli/                Command-line API client
demo-data/          Synthetic sample documents
demo-recordings/    Demo videos and screenshots
docs/               Architecture, handbook, compliance, and demo guides
skills/             Agent skill scaffold
legacy_streamlit/   Original MVP preserved for reference
```

## Documentation

- [Architecture](docs/ARCHITECTURE.md)
- [Security and Compliance Notes](docs/SECURITY.md)
- [Redaction Handbook](docs/REDACTION_HANDBOOK.md)
- [Browser Agent Handbook](docs/BROWSER_AGENT_HANDBOOK.md)
- [Demo Guide](docs/DEMO_GUIDE.md)
- [API and Agent Integration](docs/AGENT_INTEGRATION.md)
- [GitHub Publishing Notes](docs/GITHUB_PUBLISHING.md)

## API Overview

- `GET /api/locker/documents`
- `POST /api/locker/documents`
- `POST /api/redaction/rules`
- `GET /api/redaction/rules`
- `POST /api/redaction/preview`
- `POST /api/agent/drafts`
- `POST /api/agent/research`
- `POST /api/agent/approvals/{approval_id}/approve`
- `POST /api/agent/approvals/{approval_id}/execute`
- `GET /api/audit/events`
- `GET /api/security/locker-policy`

## Safety Boundaries

The browser agent does not click final submit automatically. It pauses for:

- CAPTCHA
- MFA
- payment
- signature
- legal attestation
- external file upload confirmation
- final submit

## Validation Used

- Backend compile: `python -m compileall backend/app`
- Frontend build: `npm run build`
- API smoke tests for redaction, upload, scoped draft, approval, and browser execution
- Browser UI smoke tests for Locker, Agent Chat, Redaction, and Approval

## License

Add a license before public distribution.


## Detected evidence (automated analysis)

Indexed codebase: 76 recognized source files, 192 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- LangChain (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Redis (technology) — detected in the code
- TypeScript (language) — detected in the code
- JavaScript (language) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (90 of 90)

```
.env.example
.gitignore
backend/app/__init__.py
backend/app/agents/__init__.py
backend/app/agents/field_matcher.py
backend/app/agents/intent_agent.py
backend/app/agents/orchestrator.py
backend/app/agents/research_agent.py
backend/app/api/__init__.py
backend/app/api/agent.py
backend/app/api/audit.py
backend/app/api/locker.py
backend/app/api/redaction.py
backend/app/api/security.py
backend/app/audit/__init__.py
backend/app/audit/writer.py
backend/app/browser/__init__.py
backend/app/browser/session.py
backend/app/browser/visible_fill_runner.py
backend/app/config.py
backend/app/extractors/__init__.py
backend/app/extractors/base.py
backend/app/extractors/demo.py
backend/app/extractors/universal.py
backend/app/main.py
backend/app/models/__init__.py
backend/app/models/schemas.py
backend/app/redaction/__init__.py
backend/app/redaction/pii.py
backend/app/security/__init__.py
backend/app/security/policy.py
backend/app/services/__init__.py
backend/app/services/stores.py
backend/app/tools/__init__.py
backend/app/tools/form_tools.py
backend/requirements.txt
cli/vault_cli.py
demo-data/government-id-sample.json
demo-data/insurance-card-sample.txt
demo-data/patient-intake-sample.md
demo-data/README.md
demo-data/redaction-policy-sample.txt
demo-recordings/google-form-8of8-payload.json
docker-compose.yml
docs/AGENT_INTEGRATION.md
docs/ARCHITECTURE.md
docs/BROWSER_AGENT_HANDBOOK.md
docs/DEMO_GUIDE.md
docs/FORM_COVERAGE.md
docs/GITHUB_PUBLISHING.md
docs/HACKATHON_SUBMISSION.md
docs/REDACTION_HANDBOOK.md
docs/SECURITY.md
frontend/index.html
frontend/package.json
frontend/public/manifest.webmanifest
frontend/src/App.tsx
frontend/src/components/Metric.tsx
frontend/src/components/StatusPill.tsx
frontend/src/lib/api.ts
frontend/src/main.tsx
frontend/src/pages/Approval.tsx
frontend/src/pages/AuditLog.tsx
frontend/src/pages/FormFill.tsx
frontend/src/pages/Locker.tsx
frontend/src/pages/RedactionSettings.tsx
frontend/src/styles.css
frontend/src/types/api.ts
frontend/tsconfig.json
frontend/vite.config.ts
legacy_streamlit/example.env
legacy_streamlit/llm/__init__.py
legacy_streamlit/llm/chain.py
legacy_streamlit/llm/initialize_llm.py
legacy_streamlit/llm/input_mapper_ai.py
legacy_streamlit/main.py
legacy_streamlit/prompt/__init__.py
legacy_streamlit/prompt/Decision Making Agent Prompt.txt
legacy_streamlit/prompt/prompt_template.py
legacy_streamlit/prompt/read_decision_making_prompt.py
legacy_streamlit/requirements.txt
legacy_streamlit/ui/__init__.py
legacy_streamlit/ui/chat_ui.py
legacy_streamlit/ui/sidebar.py
legacy_streamlit/utils/__init__.py
legacy_streamlit/utils/common.py
legacy_streamlit/utils/input_highlighter.py
LICENSE
README.md
skills/vault-form-agent/SKILL.md
```

### Dependencies

- backend/requirements.txt: celery@==5.5.3, fastapi@==0.116.1, langchain@==0.3.26, langchain-google-genai@==2.1.6, minio@==7.2.15, Pillow@==11.3.0, playwright@==1.53.0, psycopg[binary]@==3.2.9, pydantic-settings@==2.10.1, PyMuPDF@==1.26.3, pypdf@==5.7.0, pytesseract@==0.3.13, python-multipart@==0.0.20, redis@==6.2.0, sqlalchemy@==2.0.41, uvicorn[standard]@==0.35.0
- frontend/package.json: @types/react@^19.0.2, @types/react-dom@^19.0.2, @vitejs/plugin-react@^4.3.4, lucide-react@^0.468.0, react@^19.0.0, react-dom@^19.0.0, typescript@^5.7.2, vite@^6.0.7

### Recent commits (newest first)

- Add visual walkthrough screenshots
- Add hackathon-ready Vault Form Agent
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### demo-data/patient-intake-sample.md

```markdown
# Patient Intake Packet

Patient Name: Alex Morgan
Date of Birth: 01/02/1990
Phone Number: (555) 010-0199
Email Address: alex.demo@example.com
Street Address: 1600 Pennsylvania Ave NW, Washington, DC 20500

Emergency Contact: Jordan Morgan
Emergency Contact Phone: (555) 010-0123

Notes:
This synthetic record is used only for local demos of document extraction, redaction, and approval-gated form filling.


```

### docs/BROWSER_AGENT_HANDBOOK.md

```markdown
# Browser Agent Handbook

The browser agent is the execution layer that acts on real websites after human approval.

## Action Types

- `navigate`
- `extract_page_context`
- `type`
- `click`
- `select`
- `check`
- `upload_file`
- `drag`
- `scroll`
- `wait`
- `screenshot`
- `ask_user`
- `stop_before_submit`

## Page Context

For every target page, the agent should collect:

- URL
- visible labels
- ARIA labels
- placeholders
- nearby text
- control type
- DOM selector
- bounding box
- iframe context
- button text
- radio/checkbox option text

## Current Implementation

The current visible browser runner supports:

- approved value payloads
- visible Chrome launch
- field/context scoring
- Google Forms question-block matching
- text field filling
- radio/checkbox selection
- visible highlight on filled controls
- fixed banner showing prepared field count
- no final submit

## Stop Conditions

The agent must pause for:

- final submit
- CAPTCHA
- MFA
- password prompt
- payment
- signature
- legal attestation
- external file upload
- medical/financial irreversible submission

## Future Improvements

- persistent browser sessions
- screenshot timeline
- DOM snapshot redaction
- iframe-aware action plans
- drag-and-drop upload
- Playwright trace export
- visual object detection for canvas-heavy apps


```

### docker-compose.yml

```yaml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: vault
      POSTGRES_PASSWORD: vault
      POSTGRES_DB: vault
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  minio:
    image: minio/minio:RELEASE.2025-04-22T22-12-26Z
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: vault
      MINIO_ROOT_PASSWORD: vault-password
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - minio_data:/data

  backend:
    image: python:3.12-slim
    working_dir: /app/backend
    command: sh -c "pip install -r requirements.txt && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
    environment:
      CORS_ORIGINS: http://localhost:5173,http://127.0.0.1:5173
      DATABASE_URL: postgresql+psycopg://vault:vault@postgres:5432/vault
      REDIS_URL: redis://redis:6379/0
      MINIO_ENDPOINT: minio:9000
      MINIO_BUCKET: vault-documents
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    depends_on:
      - postgres
      - redis
      - minio

  frontend:
    image: node:22-alpine
    working_dir: /app/frontend
    command: sh -c "npm install && npm run dev"
    ports:
      - "5173:5173"
    volumes:
      - .:/app
    depends_on:
      - backend

volumes:
  postgres_data:
  minio_data:

```

### backend/requirements.txt

```
fastapi==0.116.1
uvicorn[standard]==0.35.0
pydantic-settings==2.10.1
python-multipart==0.0.20
sqlalchemy==2.0.41
psycopg[binary]==3.2.9
redis==6.2.0
celery==5.5.3
minio==7.2.15
pypdf==5.7.0
playwright==1.53.0
langchain==0.3.26
langchain-google-genai==2.1.6
PyMuPDF==1.26.3
Pillow==11.3.0
pytesseract==0.3.13

```

### frontend/package.json

```
{
  "name": "vault-form-agent",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite --host 0.0.0.0",
    "build": "tsc && vite build",
    "preview": "vite preview --host 0.0.0.0"
  },
  "dependencies": {
    "@vitejs/plugin-react": "^4.3.4",
    "vite": "^6.0.7",
    "typescript": "^5.7.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "lucide-react": "^0.468.0"
  },
  "devDependencies": {
    "@types/react": "^19.0.2",
    "@types/react-dom": "^19.0.2"
  }
}

```

### legacy_streamlit/requirements.txt

```
��a l t a i r = = 5 . 5 . 0  
 a n n o t a t e d - t y p e s = = 0 . 7 . 0  
 a n y i o = = 4 . 9 . 0  
 a t t r s = = 2 5 . 3 . 0  
 b l i n k e r = = 1 . 9 . 0  
 c a c h e t o o l s = = 5 . 5 . 2  
 c e r t i f i = = 2 0 2 5 . 1 . 3 1  
 c h a r s e t - n o r m a l i z e r = = 3 . 4 . 1  
 c l i c k = = 8 . 1 . 8  
 c o l o r a m a = = 0 . 4 . 6  
 d o t e n v = = 0 . 9 . 9  
 f i l e t y p e = = 1 . 2 . 0  
 g i t d b = = 4 . 0 . 1 2  
 G i t P y t h o n = = 3 . 1 . 4 4  
 g o o g l e - a i - g e n e r a t i v e l a n g u a g e = = 0 . 6 . 1 7  
 g o o g l e - a p i - c o r e = = 2 . 2 4 . 2  
 g o o g l e - a u t h = = 2 . 3 8 . 0  
 g o o g l e - g e n a i = = 1 . 1 0 . 0  
 g o o g l e a p i s - c o m m o n - p r o t o s = = 1 . 6 9 . 2  
 g r e e n l e t = = 3 . 1 . 1  
 g r p c i o = = 1 . 7 1 . 0  
 g r p c i o - s t a t u s = = 1 . 7 1 . 0  
 h 1 1 = = 0 . 1 4 . 0  
 h t t p c o r e = = 1 . 0 . 8  
 h t t p x = = 0 . 2 8 . 1  
 i d n a = = 3 . 1 0  
 J i n j a 2 = = 3 . 1 . 6  
 j s o n p a t c h = = 1 . 3 3  
 j s o n p o i n t e r = = 3 . 0 . 0  
 j s o n s c h e m a = = 4 . 2 3 . 0  
 j s o n s c h e m a - s p e c i f i c a t i o n s = = 2 0 2 4 . 1 0 . 1  
 l a n g c h a i n = = 0 . 3 . 2 3  
 l a n g c h a i n - c o r e = = 0 . 3 . 5 1  
 l a n g c h a i n - g o o g l e - g e n a i = = 2 . 1 . 2  
 l a n g c h a i n - t e x t - s p l i t t e r s = = 0 . 3 . 8  
 l a n g s m i t h = = 0 . 3 . 3 0  
 M a r k u p S a f e = = 3 . 0 . 2  
 n a r w h a l s = = 1 . 3 4 . 1  
 n e s t - a s y n c i o = = 1 . 6 . 0  
 n u m p y = = 2 . 2 . 4  
 o r j s o n = = 3 . 1 0 . 1 6  
 p a c k a g i n g = = 2 4 . 2  
 p a n d a s = = 2 . 2 . 3  
 p i l l o w = = 1 1 . 2 . 1  
 p l a y w r i g h t = = 1 . 5 1 . 0  
 p r o t o - p l u s = = 1 . 2 6 . 1  
 p r o t o b u f = = 5 . 2 9 . 4  
 p y a r r o w = = 1 9 . 0 . 1  
 p y a s n 1 = = 0 . 6 . 1  
 p y a s n 1 _ m o d u l e s = = 0 . 4 . 2  
 p y d a n t i c = = 2 . 1 1 . 3  
 p y d a n t i c _ c o r e = = 2 . 3 3 . 1  
 p y d e c k = = 0 . 9 . 1  
 p y e e = = 1 2 . 1 . 1  
 p y t h o n - d a t e u t i l = = 2 . 9 . 0 . p o s t 0  
 p y t h o n - d o t e n v = = 1 . 1 . 0  
 p y t z = = 2 0 2 5 . 2  
 P y Y A M L = = 6 . 0 . 2  
 r e f e r e n c i n g = = 0 . 3 6 . 2  
 r e q u e s t s = = 2 . 3 2 . 3  
 r e q u e s t s - t o o l b e l t = = 1 . 0 . 0  
 r p d s - p y = = 0 . 2 4 . 0  
 r s a = = 4 . 9  
 s i x = = 1 . 1 7 . 0  
 s m m a p = = 5 . 0 . 2  
 s n i f f i o = = 1 . 3 . 1  
 S Q L A l c h e m y = = 2 . 0 . 4 0  
 s t r e a m l i t = = 1 . 4 4 . 1  
 t e n a c i t y = = 9 . 1 . 2  
 t o m l = = 0 . 1 0 . 2  
 t o r n a d o = = 6 . 4 . 2  
 t y p i n g - i n s p e c t i o n = = 0 . 4 . 0  
 t y p i n g _ e x t e n s i o n s = = 4 . 1 3 . 2  
 t z d a t a = = 2 0 2 5 . 2  
 u r l l i b 3 = = 2 . 4 . 0  
 w a t c h d o g = = 6 . 0 . 0  
 w e b s o c k e t s = = 1 5 . 0 . 1  
 z s t a n d a r d = = 0 . 2 3 . 0  
 
```

### legacy_streamlit/main.py

```python
import os
import asyncio
from dotenv import load_dotenv
import streamlit as st
from llm import initialize_llm, get_chain
from prompt import decision_making_agent_prompt, prompt
from ui import display_chat, display_user_message
from ui import sidebar
from utils import highlight_inputs_and_get_metadata_async
from typing import Tuple, Any
from langchain_google_genai import ChatGoogleGenerativeAI

load_dotenv(".env")

def init_settings() -> Tuple[asyncio.AbstractEventLoop, ChatGoogleGenerativeAI, Any]:
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
    llm = initialize_llm()
    chain = get_chain(prompt, llm)
    return loop, llm, chain

def init_sessions():
    # Initialize session state
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = []
        
    if "user_input" not in st.session_state:
        st.session_state.user_input = ""
        
    if "api_key_configured" not in st.session_state:
        st.session_state.api_key_configured = False
        
    if "chain" not in st.session_state:
        st.session_state.chain = chain
        
    if "llm" not in st.session_state:
        st.session_state.llm = llm

# Define the chain as a global variable
chain = None

# Get all the initial settings 
loop, llm, chain = init_settings()


def main():
    # Set page title
    st.set_page_config(page_title="🧠 Form Filling Agent", layout="centered")
    st.title("🧠 Form Filling Agent")

    # Initialize sessions
    init_sessions()

    # Side bar for API key input
    sidebar()

    # Check if API key is configured
    if not st.session_state.api_key_configured and not os.environ.get("GOOGLE_API_KEY"):
        st.warning("⚠️ Please configure your Google API key in the sidebar to use this application.")

    # Chat input
    if st.session_state.api_key_configured or os.environ.get("GOOGLE_API_KEY"):
        user_input = st.chat_input("Ask me about form filling...")
    else:
        user_input = st.chat_input("Please configure API key first...", disabled=True)

    # Display chat interface
    display_chat()

    if user_input:
        user_msg = {"role": "user", "content": user_input}
        st.session_state.chat_history.append(user_msg)
        
        display_user_message(user_msg)
        
        # Spinner for processing
        with st.spinner("Thinking...", show_time=True):
            current_chain = st.session_state.get("chain", chain)
            response = current_chain.invoke({
                "decision_making_agent_prompt": decision_making_agent_prompt,
                "user_prompt": user_input
            })

        if response.get("isItFormFillingRequest"):
            st.session_state.chat_history.append({
                "role": "assistant", 
                "content": response.get("chat", "I'm having trouble processing your request.")
            })
            url_to_fill = response.get("urlWhereDataToFill")
            data_to_fill = response.get("dataToFill")
            print("Done")
            sreenshot_bytes = loop.run_until_complete(highlight_inputs_and_get_metadata_async(url_to_fill, llm, data_to_fill))
            print("Screenshot captured")
            
        else:    
            st.session_state.chat_history.append({
                "role": "assistant", 
                "content": response.get("chat", "I'm having trouble processing your request.")
            })
        
        st.rerun()
        
if __name__ == '__main__':
    main()


```

### frontend/src/main.tsx

```typescript
import React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
import "./styles.css";

createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

### backend/app/main.py

```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.api import agent, audit, locker, redaction, security
from app.config import get_settings


settings = get_settings()

app = FastAPI(
    title=settings.app_name,
    version="0.1.0",
    description=(
        "Secure document locker and approval-gated form filling agent. "
        "Designed around HIPAA/PHI/PII-aware handling patterns, not certified compliance."
    ),
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.allowed_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(locker.router, prefix="/api/locker", tags=["locker"])
app.include_router(agent.router, prefix="/api/agent", tags=["agent"])
app.include_router(audit.router, prefix="/api/audit", tags=["audit"])
app.include_router(security.router, prefix="/api/security", tags=["security"])
app.include_router(redaction.router, prefix="/api/redaction", tags=["redaction"])


@app.get("/health")
def health() -> dict[str, str]:
    return {"status": "ok", "service": settings.app_name}

```

### frontend/src/App.tsx

```typescript
import {
  Activity,
  BadgeCheck,
  ClipboardCheck,
  Database,
  FileLock2,
  Globe2,
  LayoutDashboard,
  LockKeyhole,
  Settings2,
  Radar,
  ScanSearch,
  ShieldCheck,
  ShieldAlert,
  ServerCog,
  Workflow
} from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { Metric } from "./components/Metric";
import { api } from "./lib/api";
import { Approval } from "./pages/Approval";
import { AuditLog } from "./pages/AuditLog";
import { FormFill } from "./pages/FormFill";
import { Locker } from "./pages/Locker";
import { RedactionSettings } from "./pages/RedactionSettings";
import type { ApprovalDraft, AuditEvent, DocumentRecord } from "./types/api";

type Page = "dashboard" | "locker" | "agent" | "redaction" | "approval" | "audit";

const pageMeta: Record<Page, { eyebrow: string; title: string }> = {
  dashboard: {
    eyebrow: "Enterprise command center",
    title: "Autonomous form operations with secure document intelligence."
  },
  locker: {
    eyebrow: "Document locker",
    title: "Secure ingestion for PDFs, scans, images, and records."
  },
  agent: {
    eyebrow: "Agent chat",
    title: "Chat with the form agent and control document access."
  },
  redaction: {
    eyebrow: "Redaction policy",
    title: "Create scalable PHI, PII, and custom masking rules."
  },
  approval: {
    eyebrow: "Human approval",
    title: "Review matched fields before browser execution."
  },
  audit: {
    eyebrow: "Audit trail",
    title: "Track document access, field use, approvals, and execution."
  }
};

function readPage(): Page {
  const value = window.location.hash.replace("#", "");
  return value === "locker" || value === "agent" || value === "redaction" || value === "approval" || value === "audit" ? value : "dashboard";
}

export function App() {
  const [documents, setDocuments] = useState<DocumentRecord[]>([]);
  const [events, setEvents] = useState<AuditEvent[]>([]);
  const [draft, setDraft] = useState<ApprovalDraft | null>(null);
  const [page, setPage] = useState<Page>(readPage);

  async function refresh() {
    const [docs, audit] = await Promise.all([api.documents(), api.audit()]);
    setDocuments(docs);
    setEvents(audit);
  }

  useEffect(() => {
    refresh().catch(console.error);

    function onHashChange() {
      setPage(readPage());
    }

    window.addEventListener("hashchange", onHashChange);
    return () => window.removeEventListener("hashchange", onHashChange);
  }, []);

  const stats = useMemo(() => {
    const fields = documents.reduce((total, doc) => total + doc.extracted_fields.length, 0);
    const low = draft?.matches.filter((match) => match.requires_user_input).length || 0;
    return { fields, low };
  }, [documents, draft]);

  const meta = pageMeta[page];

  function setDraftAndOpenApproval(nextDraft: ApprovalDraft) {
    setDraft(nextDraft);
    refresh().catch(console.error);
  }

  function updateDraft(nextDraft: ApprovalDraft) {
    setDraft(nextDraft);
    refresh().catch(console.error);
  }

  const systemRail = (
    <aside className="system-rail" aria-label="System posture">
      <div className="rail-card">
        <span><BadgeCheck size={16} aria-hidden="true" /> Compliance posture</span>
        <strong>PII / PHI guarded</strong>
        <small>Consent, redaction, audit, retention boundaries</small>
      </div>
      <div className="rail-card">
        <span><Radar size={16} aria-hidden="true" /> Research agent</span>
        <strong>{draft?.research_report ? `${Math.round(draft.research_report.confidence * 100)}%` : "Ready"}</strong>
        <small>{draft?.research_report?.selected_url || "Waiting for a form request"}</small>
      </div>
      <div className="rail-card">
        <span><ServerCog size={16} aria-hidden="true" /> Execution mode</span>
        <strong>Visible browser</strong>
        <small>Prepared forms stop before final user submit</small>
      </div>
      <div className="rail-card warning">
        <span><ShieldAlert size={16} aria-hidden="true" /> Review queue</span>
        <strong>{stats.low}</strong>
        <small>Fields requiring user confirmation</small>
      </div>
    </aside>
  );

  const metrics = (
    <section className="metrics" aria-label="Workspace metrics">
      <Metric label="Locker docs" value={documents.length} detail="Uploaded sources" />
      <Metric label="Extracted fields" value={stats.fields} detail="Normalized records" />
      <Metric label="Needs review" value={stats.low} detail="Below threshold" />
      <Metric label="Audit events" value={events.length} detail="Immutable log" />
    </section>
  );

  function renderPage() {
    if (page === "locker") {
      return (
        <div className="page-grid">
          <Locker documents={documents} onRefresh={refresh} />
          {systemRail}
        </div>
      );
    }

    if (page === "agent") {
      return (
        <FormFill documents={documents} onDraft={setDraftAndOpenApproval} />
      );
    }

    if (page === "redaction") {
      return (
        <div className="page-grid">
          <RedactionSettings />
          {systemRail}
        </div>
      );
    }

    if (page === "approval") {
      return (
        <div className="single-page">
          <Approval draft={draft} onChange={updateDraft} />
        </div>
      );
    }

    if (page === "audit") {
      return (
        <div className="page-grid">
          <AuditLog events={events} />
          {systemRail}
        </div>
      );
    }

    return (
      <>
        {metrics}
        <section className="command-grid" aria-label="Operations overview">
          <div className="hero-shell">
            <div className="hero-copy">
              <span className="mode">Live workflow</span>
              <h2>Research official sites, convert scanned files to Markdown, map fields, and execute in a visible browser.</h2>
              <p>
                The app keeps sensitive records in a consented locker, sends uncertain values to approval, and 
[truncated — 2954 more characters]
```

[67 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]