# Project export: Cena

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: TreeHacks 2026
- Tagline: Protecting your likeness: invisible facial encryptions and local-cloud agent systems for privacy. Ensure your face and data are safe from deepfakes and leaks. [You can't see me... (John Cena, 2016)]
- Devpost: https://devpost.com/software/cena
- GitHub: https://github.com/nvemuri4649/treehacks-26
- Demo: https://drive.google.com/file/d/1ClucjDlTU92WQmcaXACAuMH9Utd0Ht81/view
- Video: https://www.youtube.com/embed/OjcX0RndXMc?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — nikhil (23 commits), Cursor (21 commits), Abhishek Shah (2 commits)

## Devpost submission (written by the team)

### Overview

Preview: what's below? New algorithm for invisible facial encryption: the image looks identical to humans but is catastrophic to generative models, tested and tuned with Runpod Complex multi-agent orchestration, featuring local agents on the DGX Spark (Nemotron) collaborating with Claude Agent SDK for data-secure, high reasoning tasks Multi-agent feedback loops, using OpenAI API to enable agent self-verification Bright Data for complex web scraping tasks (tracking your identity across the web) Overview As the misuse of AI-generated media and data collection rapidly rises, individuals and organizations need a way to benefit from powerful models while keeping their identity and sensitive data under their own control. Cena is an invisible companion that travels the web with you and safeguards your digital identity. It does this as an embedded platform on your desktop consisting of 3 main features: Personal image protection: encrypt your photos before you post them so they look normal to people but aren’t usable for AI models to analyze or generate impersonations, using an agent feedback loop. Safeguarding personal data: a local-remote agent system intelligently de-references personal and sensitive identifiers in your LLM prompts and uploaded files before sending them to cloud AI models, ensuring utility without giving up raw personal information. Deepfake monitoring: scans the web for images and videos of your likeness and alerts you of likely AI impersonations.

### Inspiration

While the capabilities of AI assistants have expanded rapidly over the past few years, a tradeoff for users has emerged between the value they provide and the personal security risks that come with sharing sensitive data. What if we could ensure individual data security while still attaining the same, high-level chatbot utility for users? Enter Cena. Our inspiration for Cena originated from the exponential growth of the threat of deepfakes and personal data leakages. These threats can affect any one, at any time. Recently, deepfakes of public images have been exploited for blackmail, slander, and the nonconsensual production of sexual content. In fact, deepfake fraud attempts have surged by over 3,000% annually in recent years. Over the past two years, the number of deepfakes online have increased by 16-fold. As AI models grow in capability and ease of access improves, these effects will become all the more ubiquitous. When using LLMs, many people worry that the personal details they share can be stored or reused into future model training beyond their control, especially in settings such as HIPAA-regulated healthcare, legal and financial work, and internal company workflows. There has been a 57% increase in AI-driven attacks on user information within the last year. Additionally, 81% of users believe that information collected by AI companies will be used in ways they are uncomfortable with. What Cena Does 1. Encrypting your digital likeness to protect against deepfake generation. Applies undetectable transformations to images that seem identical to the human eye, but make generating convincing deepfakes impossible. Expanded on image processing techniques to perturb pixel distributions in existing facial images. Survives workarounds such as screenshotting, cropping and resolution altering. Workflow of the encryptor, generator and evaluator working in tandem to provide maximal security on input images. 2. Running multi-agent feedback loops before releasing images into the wild for maximum security. Coordinates a triple-agent model: 1) encryptor, 2) generator, 3) evaluator. The encryptor runs the algorithm described above to encrypt an image of a face, where the encrypted image looks identical to the human eye. This encrypted image is then passed to the locally-hosted generator, which attempts to generate deepfakes from this image. These deepfakes are passed to the evaluator, which determines how realistic they are. If the generated deepfakes are deemed convincing above a threshold, the encryption algorithm is re-run on the encrypted image once again. This process repeats until a sufficiently encrypted image is obtained. 3. Data de-referencing to prevent sensitive information from leaking into cloud-based LLMs. Assigned a utility score and sensitivity score to each phrase of text. Utility score measures importance of specificity to ensure the cloud LLM runs accurately. Sensitivity score measures importance of keeping text secure, including a multiplier for contextual inference. We use NVIDIA's Nemotron, hosted on a DGX Spark (using vLLM for fast inference!) to handle and de-reference all private data, aiming to stay cryptographically secure. These agents are then in collaboration with the Claude SDK which performs cloud-based heavy reasoning tasks. The combination of local and cloud agents enables secure, high reasoning workflows, and allows us to push the boundaries of what is possible with either agent alone! 4. Adversarial multi-agent system to safely stress-test your documents. Attacker model that tests cloud LLM’s performance on inferring information from de-referenced prompt to push local agent towards securing personal data. We use the OpenAI API to enable this agentic self-verification! Workflow of de-referencing personal information using local agents with access to remote cloud models for computationally-intensive tasks. 5. Web agent to identify deepfakes and AI-generated content online. Agent developed with Claude Agent SDK to search online images using Bright Data. Identifies images as AI generated from a collection of 3 independent signals: visual artifacts using Claude Vision, metadata inspection for AI tool signatures, and frequency analysis using FFT to detect spectral patterns that diffusion models leave behind. How We Built It Native macOS front-end (SwiftUI) Menu-bar app with translucent overlay HUD, agent chat window, and settings pane Real-time communication with the backend over WebSocket FastAPI + Uvicorn – main API server with WebSocket endpoints for the agent chat Flask – GPU-accelerated image encryption/glazing server Jinja2 templates + SSE for a deepfake-detection web UI Local AI model – NVIDIA Nemotron nvidia/NVIDIA-Nemotron-Nano-9B-v2 served locally via vLLM Handles PII redaction orchestration and privacy-preserving query rewriting so sensitive data never leaves the device Cloud AI Models Anthropic Claude (Sonnet, Haiku) via the Claude Agent SDK – used for the cloud relay chat agent and vision-based deepfake artifact analysis OpenAI GPT (gpt-4o, gpt-4-turbo) – alternative cloud LLM option Bright Data SERP API + Scraping Browser for reverse image search (Google Lens) in deepfake detection Image protection & computer vision (GPU) Stable Diffusion Inpainting (runwayml/stable-diffusion-inpainting via HuggingFace Diffusers) + a RunPod-tuned a PGD algorithm for adversarial attack InsightFace (buffalo_l, ArcFace 512-D embeddings) – face detection and identity matching OpenCV, Pillow, NumPy – general image processing and DCT frequency-domain forensics GPU compute & deployment Primary target: NVIDIA DGX Spark (ASUS Ascent GX10) via SSH + Docker RunPod GPU pods used for tuning the algorithm, testing it, and providing extra compute needed through their Flash instances PyTorch with CUDA; models run in FP16 Deployment automated via deploy.sh (Docker build & push to remote) Challenges We Ran Into Facial image encryption process: making the difference between original images and encrypted images imperceptible to humans but the encrypted images unusable by AI tools. Separation of local and cloud agents: navigating the dynamic between the local agent’s de-referencing of information before sending to remote cloud agents for higher computational analysis. Orchestration of agents: ensuring communication between agents with various roles. Latency: especially during multi-agent feedback loops, improving performance proved challenging. Accomplishments Proposing a new facial encryption algorithm to perform modifications to a face which are both undetectable by the human eye and also make your face immune to deepfakes. Pushing state-of-the-art techniques in image processing to achieve stronger performance in new contexts. Handling complex edge-cases in document dereferencing. Merging different expertises and working styles to form a cohesive team environment. What We Learned Interfacing with high-performance hardware like NVIDIA DGX Spark. Building a cohesive tech stack across cloud technologies like GCP and Runpod and LLM backends like the OpenAI API and Claude SDK. Coordinating complex, multi-agent systems that interact with real-time feedback to alter their course of action. What's Next for Cena Cross-platform + mobile support. Increasing number of data modalities (e.g., audio to prevent non-consensual voice cloning). More granular control over document data, including the kinds of PII that should be prioritized over others.

## README (from the GitHub repository)

# Cena — Personal Data Privacy in the Age of AI

> **TreeHacks '26** — A suite of tools that protect your personal data from AI exploitation.

Cena is a native macOS app with two core features:

1. **Automatic Likeness Encryption** — A translucent system overlay that intercepts images/videos before upload and encrypts your likeness to defeat deepfake generation and AI inpainting. A small loading indicator and checkmark appear in a translucent bubble, seamlessly replacing the original with an encrypted version.

2. **Cena Agent** — A native chat interface for talking to cloud LLMs with full privacy. Documents, images, and messages are dereferenced/redacted locally before being sent to the cloud. Images uploaded here also get likeness encryption. Personal information never leaves your device unprotected.

Both features are native SwiftUI, unified in a single menu-bar app.

**Key principle:** All personalized information is processed locally (on the DGX Spark) — the local agent, encryption, redaction — before being dereferenced/encrypted and sent to the cloud.

## Architecture

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                         YOUR MACHINE (DGX Spark / SSH)                      │
│                                                                             │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │  Cena (native macOS)                                                │   │
│  │  ├─ Automatic Likeness Encryption (translucent overlay)             │   │
│  │  │   ├─ Clipboard monitor → auto-encrypt on copy/upload             │   │
│  │  │   └─ Translucent HUD with progress                              │   │
│  │  └─ Agent Chat (native SwiftUI window)                              │   │
│  │      ├─ WebSocket → FastAPI backend                                 │   │
│  │      └─ Model picker (Claude / GPT)                                 │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
│                              │                                              │
│  ┌───────────────────────────▼──────────────────────────────────────────┐   │
│  │  Cena Backend (FastAPI :8000 + Flask :5000)                         │   │
│  │  ├─ Local Guardian (Nemotron via vLLM)                              │   │
│  │  │   ├─ PII Redactor                                                │   │
│  │  │   ├─ Likeness Encryptor (Cena Encryption)                        │   │
│  │  │   └─ Re-referencing engine                                       │   │
│  │  └─ Encryption Server (PGD + SD Inpainting + Fawkes)               │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────┬──────────────────────────────────┘
                                           │ redacted / encrypted data only
                                           ▼
                              ┌──────────────────────────┐
                              │  Cloud Relay              │
                              │  ├─ Claude (Agent SDK)    │
                              │  └─ OpenAI GPT (API)      │
                              └──────────────────────────┘
```

## Project Structure

```
.
├── Cena/                        # Native macOS app (SwiftUI)
│   └── Cena/
│       ├── App/                 # CenaApp, AppState, MenuBarController
│       ├── UI/                  # AgentChatView, OverlayWindow, EncryptionProgressView,
│       │                        #   ApprovalDialog, SettingsView
│       ├── Services/            # AgentWebSocket, BackendService, EncryptionQueue,
│       │                        #   MaskGenerator, PasteboardMonitor
│       └── Models/              # ChatMessage, EncryptionJob, Settings, BackendConfig
├── agents/
│   ├── local_guardian/          # Nemotron agent: redact, encrypt, re-reference
│   └── cloud_relay/             # Routes sanitized requests to Claude / GPT
├── server/
│   ├── app.py                   # Flask GPU server (encryption + Fawkes)
│   ├── fawkes_modern.py         # Fawkes facial recognition cloaking
│   ├── main.py                  # FastAPI server (agent WebSocket API)
│   └── routes.py                # WebSocket + REST endpoints
├── client/
│   ├── encrypt.py               # CLI image encryption
│   ├── agent_loop.py            # Adversarial encrypt → generate → judge loop
│   ├── rater_agent.py           # Claude vision deepfake rater
│   └── backends.py              # Backend resolver
├── config/settings.py           # All configuration
├── backends.json                # GPU backend definitions
├── deploy.sh                    # Deploy to GX10 / RunPod / SSH
├── .env.example                 # Environment variable template
└── requirements.txt             # Backend Python dependencies
```

## Quick Start

### 1. Deploy Encryption Server (on DGX Spark)

```bash
./deploy.sh gx10 nikhil@spark-abcd.local
ssh nikhil@spark-abcd.local
docker exec -it cena bash -c 'cd /workspace/project/server && python app.py'
```

### 2. Start Agent Backend

```bash
# On DGX Spark: start local Nemotron
vllm serve nvidia/NVIDIA-Nemotron-Nano-9B-v2 --port 8001 --trust-remote-code

# On your machine:
cp .env.example .env   # add your API keys
pip install -r requirements.txt
python -m server.main
```

### 3. Build & Run Cena

```bash
cd Cena && swift build -c release
.build/release/Cena
```

The shield icon appears in your menu bar with two main actions:

- **Automatic Likeness Encryption**: Copy an image → translucent bubble → encrypted → paste
- **Open Agent Chat** (Cmd+A): Native chat window connected to the privacy agent

## Configuration

Copy `.env.example` to `.env` and set:

| Variable | Purpose |
|----------|---------|
| `NEMOTRON_ENDPOINT` | vLLM server URL (default: `http://spark-abcd.local:8001/v1`) |
| `ENCRYPTION_SERVER_URL` | Encryption server (default: `http://spark-abcd.local:5000`) |
| `ANTHROPIC_API_KEY` | Cloud Claude access |
| `OPENAI_API_KEY` | Cloud GPT access |
| `ENCRYPTION_BACKEND` | Default backend name from `backends.json` |

## References

- [Adversarial Image Encryption (ICLR 2025)](https://arxiv.org/abs/2410.05694) — adversarial image protection
- [NVIDIA Nemotron](https://build.nvidia.com/nvidia/NVIDIA-Nemotron-Nano-9B-v2) — local LLM
- [Claude Agent SDK](https://docs.anthropic.com/en/docs/agents-and-tools/claude-agent-sdk) — agentic cloud relay


## Detected evidence (automated analysis)

Indexed codebase: 78 recognized source files, 501 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- Hugging Face (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- Swift (language) — detected in the code
- PyTorch (technology) — claimed on Devpost, not found in the code
- AI coding agent: Cursor — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (89 of 89)

```
.env.example
.gitignore
agents/__init__.py
agents/cloud_relay/__init__.py
agents/cloud_relay/agent.py
agents/cloud_relay/claude_client.py
agents/cloud_relay/openai_client.py
agents/local_guardian/__init__.py
agents/local_guardian/adversarial_analyzer.py
agents/local_guardian/agent.py
agents/local_guardian/blur_strategies.py
agents/local_guardian/image_transformer.py
agents/local_guardian/mapping_store.py
agents/local_guardian/nemotron_client.py
agents/local_guardian/pii_detector.py
agents/local_guardian/redactor.py
agents/local_guardian/rereferencer.py
agents/local_guardian/scorer.py
backends.json
Cena/Cena/App/AppState.swift
Cena/Cena/App/CenaApp.swift
Cena/Cena/App/MenuBarController.swift
Cena/Cena/Assets.xcassets/AppIcon.appiconset/Contents.json
Cena/Cena/Assets.xcassets/Contents.json
Cena/Cena/Cena.entitlements
Cena/Cena/Info.plist
Cena/Cena/Models/BackendConfig.swift
Cena/Cena/Models/ChatMessage.swift
Cena/Cena/Models/EncryptionJob.swift
Cena/Cena/Models/Settings.swift
Cena/Cena/Services/AgentWebSocket.swift
Cena/Cena/Services/BackendService.swift
Cena/Cena/Services/EncryptionQueue.swift
Cena/Cena/Services/MaskGenerator.swift
Cena/Cena/Services/PasteboardMonitor.swift
Cena/Cena/UI/AgentChatView.swift
Cena/Cena/UI/AgentPipelineWindow.swift
Cena/Cena/UI/ApprovalDialog.swift
Cena/Cena/UI/CenaLogo.swift
Cena/Cena/UI/CinematicDisplayView.swift
Cena/Cena/UI/DeepfakeScannerView.swift
Cena/Cena/UI/DemoView.swift
Cena/Cena/UI/EncryptionProgressView.swift
Cena/Cena/UI/MarkdownText.swift
Cena/Cena/UI/OverlayWindow.swift
Cena/Cena/UI/PipelineView.swift
Cena/Cena/UI/SettingsView.swift
Cena/create_xcode_project.sh
Cena/Makefile
Cena/Package.swift
Cena/README.md
client/agent_loop.py
client/backends.py
client/encrypt.py
client/rater_agent.py
client/requirements.txt
client/test_glazing.py
config/__init__.py
config/settings.py
deepfake/__init__.py
deepfake/agent/__init__.py
deepfake/agent/orchestrator.py
deepfake/agent/system_prompt.py
deepfake/agent/tools/__init__.py
deepfake/agent/tools/deepfake_analysis.py
deepfake/agent/tools/face_analysis.py
deepfake/agent/tools/image_download.py
deepfake/agent/tools/report_generator.py
deepfake/agent/tools/reverse_image_search.py
deepfake/agent/tools/serp_search.py
deepfake/core/__init__.py
deepfake/core/config.py
deepfake/core/deepfake_detector.py
deepfake/core/face_engine.py
deepfake/core/image_processor.py
deepfake/core/search_engine.py
deepfake/routes.py
deepfake/static/styles.css
deepfake/templates/index.html
deepfake/templates/report.html
deploy.sh
README.md
requirements.txt
server/__init__.py
server/app.py
server/fawkes_modern.py
server/main.py
server/requirements.txt
server/routes.py
```

### Dependencies

- client/requirements.txt: anthropic@>=0.18.0, pillow, requests
- requirements.txt: aiofiles@>=24.1.0, anthropic@>=0.42.0, claude-agent-sdk@>=0.1.0, fastapi@>=0.115.0, httpx@>=0.27.0, insightface@>=0.7.3, jinja2@>=3.1.3, numpy@>=1.26.0, onnxruntime@>=1.17.0, openai@>=1.60.0, opencv-python@>=4.9.0, Pillow@>=11.0.0, playwright@>=1.48.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.18, scipy@>=1.12.0, spacy@>=3.7.0, sse-starlette@>=2.1.0, uvicorn[standard]@>=0.34.0, websockets@>=14.0
- server/requirements.txt: datasets, diffusers@>=0.25.0, flask, huggingface-hub, hydra-core, numpy, omegaconf, opencv-contrib-python, pillow, scikit-learn, tqdm, transformers

### Recent commits (newest first)

- Codebase cleanup and consistency
- Simplify image display and release prep
- Add demos, pipeline UI, and scanner
- Pipeline visualization and UX improvements
- Fix approval dialog timing
- Fix approval dialog display
- Translucent glass aesthetic for all windows: approval dialog, settings, agent chat
- Fix pasteboard monitoring: explicit main RunLoop timer, debug logging
- Fix logo rendering: use Canvas instead of ZStack for correct tile positioning
- 3x3 logo: merged-single / 3 singles / single-merged, no gradient
- Add 4x4 grid logo with merged tiles, fix titlebar vibrancy
- Balanced glass UI: icons, accents, translucent vibrancy
- Minimal transparent UI, fix backend status, wider window
- Fix menu bar, liquid glass UI, input field, health check
- Replace web frontend with native SwiftUI agent chat
- Branding and Swift fixes
- Rebrand and fix Swift build
- Project rename
- Simplify codebase
- Integrate all branches into unified Cena platform

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

### requirements.txt

```
#── Core ──────────────────────────────────────────────────────────────────
fastapi>=0.115.0
uvicorn[standard]>=0.34.0
websockets>=14.0
python-dotenv>=1.0.0
anthropic>=0.42.0
openai>=1.60.0
claude-agent-sdk>=0.1.0
Pillow>=11.0.0
python-multipart>=0.0.18
jinja2>=3.1.3
httpx>=0.27.0

#── PII Detection (spaCy optional but recommended) ───────────────────────
#Install with:  pip install spacy && python -m spacy download en_core_web_sm
spacy>=3.7.0

#── Deepfake Detection Agent ─────────────────────────────────────────────
insightface>=0.7.3
onnxruntime>=1.17.0
numpy>=1.26.0
opencv-python>=4.9.0
scipy>=1.12.0
sse-starlette>=2.1.0
aiofiles>=24.1.0
playwright>=1.48.0

```

### client/requirements.txt

```
# Client-side dependencies (installed on your laptop)
requests
pillow
anthropic>=0.18.0

```

### server/requirements.txt

```
# Server-side dependencies (installed inside NGC container on GX10)
# NOTE: Do NOT install torch/torchvision here — use what's in the NGC container
diffusers>=0.25.0
transformers
datasets
huggingface-hub
numpy
omegaconf
opencv-contrib-python
scikit-learn
tqdm
hydra-core
flask
pillow

```

### server/main.py

```python
"""
Cena — FastAPI application entry point.

Serves:
  - WebSocket + REST API for the native Cena macOS agent chat
  - Deepfake Detection Agent web UI under /deepfake

Run with:
    python -m server.main
"""

from pathlib import Path

import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

from config.settings import HOST, PORT
from server.routes import router

app = FastAPI(
    title="Cena",
    description="Personal data privacy suite for the age of AI",
    version="0.1.0",
)

# ── Core agent routes (WebSocket chat, sessions) ─────────────────────────
app.include_router(router)

# ── Deepfake Detection Agent (optional — requires playwright) ────────────
try:
    from deepfake.routes import router as deepfake_router  # noqa: E402

    _deepfake_dir = Path(__file__).resolve().parent.parent / "deepfake"
    app.mount(
        "/deepfake/static",
        StaticFiles(directory=_deepfake_dir / "static"),
        name="deepfake-static",
    )
    _evidence_dir = Path(__file__).resolve().parent.parent / "output" / "deepfake" / "evidence"
    _evidence_dir.mkdir(parents=True, exist_ok=True)
    app.mount(
        "/deepfake/evidence",
        StaticFiles(directory=_evidence_dir),
        name="deepfake-evidence",
    )
    app.include_router(deepfake_router, prefix="/deepfake", tags=["deepfake"])
except ImportError as _e:
    import logging as _log
    _log.warning("Deepfake module unavailable (missing dependency: %s) — skipping", _e)


@app.get("/")
async def root():
    """API root — confirms the server is running."""
    return {
        "service": "cena",
        "status": "ok",
        "endpoints": {
            "health": "GET /health",
            "session": "POST /api/session",
            "chat": "WS /ws/{session_id}",
            "deepfake_scanner": "GET /deepfake/",
        },
    }


if __name__ == "__main__":
    uvicorn.run(
        "server.main:app",
        host=HOST,
        port=PORT,
        reload=True,
        log_level="info",
    )

```

### server/app.py

```python
"""
Cena Encryption + Fawkes API Server
====================================
Exposes HTTP endpoints to protect images against diffusion-based inpainting
and facial recognition.

Endpoints:
    GET  /health          - Check server status + GPU info
    POST /protect         - Encrypt an image (send image + mask)
    POST /fawkes          - Cloak an image with Fawkes (send image, no mask needed)
    POST /test-inpaint    - Run inpainting on an image to demonstrate protection effectiveness

Usage:
    python app.py
"""

import io
import os
import sys
import time
import logging

import torch
import numpy as np
from PIL import Image
from flask import Flask, request, send_file, jsonify
from omegaconf import OmegaConf
from diffusers import StableDiffusionInpaintPipeline

#encryption engine lives in a sibling dir (upstream implementation)
ENCRYPTION_REPO = os.environ.get(
    "ENCRYPTION_REPO",
    os.path.join(os.path.dirname(__file__), "..", "DiffusionGuard"),
)
if os.path.isdir(ENCRYPTION_REPO):
    sys.path.insert(0, ENCRYPTION_REPO)
else:
    print(f"WARNING: encryption engine repo not found at {ENCRYPTION_REPO}")
    print("Clone it:  git clone https://github.com/choi403/DiffusionGuard.git")
    sys.exit(1)

from attacks import protect_image  # noqa: E402
from utils import overlay_images, get_mask_radius_list, tensor_to_pil_image  # noqa: E402

#logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)

#flask app
app = Flask(__name__)

#model state (loaded once at startup)
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
MODEL_ID = "runwayml/stable-diffusion-inpainting"
IMG_SIZE = 512

pipe = None  # loaded in load_model

#default encryption config
DEFAULT_CONFIG = {
    "exp_name": "api",
    "method": "diffusionguard",
    "orig_image_name": "input.png",
    "mask_image_names": ["mask.png"],
    "model": {"inpainting": MODEL_ID},
    "training": {
        "size": IMG_SIZE,
        "iters": 500,        # stronger protection
        "grad_reps": 1,
        "batch_size": 1,
        "eps": 0.03137254901960784,        # 8/255 subtle
        "step_size": 0.00392156862745098,  # 1/255 step
        "num_inference_steps": 4,
        "mask": {
            "generation_method": "contour_shrink",
            "contour_strength": 1.1,
            "contour_iters": 15,
            "contour_smoothness": 0.1,
        },
    },
}


def load_model():
    """Load the Stable Diffusion Inpainting pipeline once."""
    global pipe
    logger.info("Loading %s on %s (%s)...", MODEL_ID, DEVICE, DTYPE)
    pipe = StableDiffusionInpaintPipeline.from_pretrained(
        MODEL_ID,
        variant="fp16" if DTYPE == torch.float16 else None,
        torch_dtype=DTYPE,
    ).to(DEVICE)
    logger.info("Model loaded successfully.")


#---------------------------------------------------------------------------
#Helpers
#---------------------------------------------------------------------------

def center_crop_square(img: Image.Image) -> Image.Image:
    """Center-crop an image to a square (no stretching)."""
    w, h = img.size
    side = min(w, h)
    left = (w - side) // 2
    top = (h - side) // 2
    return img.crop((left, top, left + side, top + side))


def read_image_from_request(field: str) -> Image.Image:
    """Read an image from a multipart form field (center-crop, no stretch)."""
    if field not in request.files:
        raise ValueError(f"Missing required file field: '{field}'")
    f = request.files[field]
    img = Image.open(f.stream).convert("RGB")
    img = center_crop_square(img)
    return img.resize((IMG_SIZE, IMG_SIZE), Image.LANCZOS)


def pil_to_bytes(img: Image.Image, fmt: str = "PNG") -> io.BytesIO:
    """Convert a PIL image to an in-memory bytes buffer."""
    buf = io.BytesIO()
    img.save(buf, format=fmt)
    buf.seek(0)
    return buf


#---------------------------------------------------------------------------
#Routes
#---------------------------------------------------------------------------

@app.route("/health", methods=["GET"])
def health():
    """Health check — returns GPU info."""
    gpu_name = torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU"
    gpu_mem = ""
    if torch.cuda.is_available():
        mem = torch.cuda.get_device_properties(0).total_memory
        gpu_mem = f"{mem / 1e9:.1f} GB"
    return jsonify({
        "status": "ok",
        "gpu": gpu_name,
        "gpu_memory": gpu_mem,
        "model_loaded": pipe is not None,
        "device": DEVICE,
    })


@app.route("/protect", methods=["POST"])
def protect():
    """
    Protect an image using adversarial encryption.

    Expects multipart form data:
        image  - The source image to protect (PNG/JPEG)
        mask   - Binary mask indicating the sensitive region (white = keep, black = edit)

    Optional query params:
        iters  - Number of PGD iterations (default: 200, max: 1000)

    Returns:
        The protected (glazed) image as PNG.
    """
    try:
        src_image = read_image_from_request("image")
        mask_image = read_image_from_request("mask")
    except ValueError as e:
        return jsonify({"error": str(e)}), 400

    #Allow callers to override iteration count
    iters = request.args.get("iters", DEFAULT_CONFIG["training"]["iters"], type=int)
    iters = min(max(iters, 10), 1000)

    logger.info("Protecting image (%d PGD iterations)...", iters)
    t0 = time.time()

    #Build config
    config = OmegaConf.create(DEFAULT_CONFIG)
    config.training.iters = iters

    mask_image_list = [mask_image]
    mask_image_combined = overlay_images(mask_image_list)
    mask_radius_list = get_mask_radius_list(mask_image_list)

    #Run encryption
    adv_tensor = protect_image(
        config.method,
        pipe,
        src_image,
        mask_image_list,
        mask_image_combined,
        mask_radius_list,
        config,
    )


[truncated — 4040 more characters]
```

### deploy.sh

```shell
#!/usr/bin/env bash
#
#Deploy Cena encryption server to a GPU backend
#===============================================
#
#Usage:
#  ./deploy.sh gx10   <user>@<host>             Deploy to ASUS Ascent GX10
#  ./deploy.sh runpod  <ssh-args>                Deploy to RunPod GPU pod
#  ./deploy.sh ssh     <user>@<host>             Deploy to any SSH-accessible GPU box
#
#Examples:
#  ./deploy.sh gx10   nikhil@spark-abcd.local
#  ./deploy.sh runpod  -p 22177 root@ssh.runpod.io
#  ./deploy.sh ssh     ubuntu@my-gpu-server.com
#
set -euo pipefail

usage() {
    cat <<'EOF'
Usage: ./deploy.sh <target-type> <connection-args...>

Target types:
  gx10    ASUS Ascent GX10 (uses Docker container 'cena')
  runpod  RunPod GPU pod (direct install, no Docker)
  ssh     Any SSH-accessible machine with NVIDIA GPU (direct install)

Examples:
  ./deploy.sh gx10   nikhil@spark-abcd.local
  ./deploy.sh runpod  -p 22177 root@ssh.runpod.io
  ./deploy.sh ssh     ubuntu@lambda-box.com
EOF
    exit 1
}

[ $# -lt 2 ] && usage

TARGET_TYPE="$1"
shift
SSH_ARGS="$@"
REMOTE_DIR="cena_encryption"
PIP_DEPS="diffusers==0.24.0 transformers datasets huggingface-hub numpy omegaconf opencv-contrib-python scikit-learn tqdm hydra-core flask pillow"

#-----------------------------------------------------------------------
#Helper: copy server code via SSH pipe (works with any SSH config)
#-----------------------------------------------------------------------
copy_server_code() {
    local ssh_args="$1"
    local remote_dir="$2"
    echo "[*] Copying server code..."
    ssh $ssh_args "mkdir -p $remote_dir/server"
    cat server/app.py          | ssh $ssh_args "cat > $remote_dir/server/app.py"
    cat server/requirements.txt | ssh $ssh_args "cat > $remote_dir/server/requirements.txt"
}

clone_encryption_engine() {
    local ssh_args="$1"
    local remote_dir="$2"
    echo "[*] Cloning encryption engine repo (if needed)..."
    ssh $ssh_args "cd $remote_dir && [ -d DiffusionGuard ] || git clone https://github.com/choi403/DiffusionGuard.git"
}

#-----------------------------------------------------------------------
#GX10 deploy (Docker-based)
#-----------------------------------------------------------------------
deploy_gx10() {
    local remote="$REMOTE_DIR"
    echo "=== Deploying to GX10 ($SSH_ARGS) ==="

    copy_server_code "$SSH_ARGS" "~/$remote"
    clone_encryption_engine  "$SSH_ARGS" "~/$remote"

    echo "[*] Checking Docker container 'cena'..."
    ssh $SSH_ARGS "docker ps -a --format '{{.Names}}' | grep -q cena" || {
        echo "ERROR: Docker container 'cena' not found."
        echo "Create it first — see SETUP_GX10.md Phase 3."
        exit 1
    }

    echo "[*] Installing dependencies inside Docker container..."
    ssh $SSH_ARGS "docker start cena 2>/dev/null; docker exec cena pip install -q $PIP_DEPS"

    echo ""
    echo "=== GX10 deploy complete! ==="
    echo ""
    echo "Start the server:"
    echo "  ssh $SSH_ARGS"
    echo "  docker exec -it cena bash -c 'cd /workspace/project/server && python app.py'"
    echo ""
    echo "Then from your laptop:"
    echo "  python client/encrypt.py --image photo.png --mask mask.png --backend gx10"
}

#-----------------------------------------------------------------------
#RunPod deploy (direct install, no Docker)
#-----------------------------------------------------------------------
deploy_runpod() {
    local remote="/workspace/$REMOTE_DIR"
    echo "=== Deploying to RunPod ($SSH_ARGS) ==="

    copy_server_code "$SSH_ARGS" "$remote"
    clone_encryption_engine  "$SSH_ARGS" "$remote"

    echo "[*] Installing dependencies..."
    ssh $SSH_ARGS "pip install -q $PIP_DEPS"

    echo "[*] Starting server in background..."
    ssh $SSH_ARGS "cd $remote/server && nohup python app.py > /workspace/cena_encryption.log 2>&1 &"

    echo ""
    echo "=== RunPod deploy complete! ==="
    echo ""
    echo "Server is starting on port 5000."
    echo "First run downloads the model (~4GB) — check logs:"
    echo "  ssh $SSH_ARGS 'tail -f /workspace/cena_encryption.log'"
    echo ""
    echo "Access URL: https://<POD_ID>-5000.proxy.runpod.net"
    echo ""
    echo "  1. Get your pod ID from runpod.io dashboard"
    echo "  2. export RUNPOD_POD_ID=<pod-id>"
    echo "  3. python client/encrypt.py --image photo.png --mask mask.png --backend runpod"
}

#-----------------------------------------------------------------------
#Generic SSH deploy (any machine with GPU)
#-----------------------------------------------------------------------
deploy_ssh() {
    local remote="~/$REMOTE_DIR"
    echo "=== Deploying to remote GPU ($SSH_ARGS) ==="

    copy_server_code "$SSH_ARGS" "$remote"
    clone_encryption_engine  "$SSH_ARGS" "$remote"

    echo "[*] Installing dependencies..."
    ssh $SSH_ARGS "pip install -q $PIP_DEPS"

    echo ""
    echo "=== SSH deploy complete! ==="
    echo ""
    echo "Start the server:"
    echo "  ssh $SSH_ARGS 'cd ~/$REMOTE_DIR/server && python app.py'"
    echo ""
    echo "Then from your laptop:"
    echo "  python client/encrypt.py --image photo.png --mask mask.png --server http://<host>:5000"
}

#-----------------------------------------------------------------------
#Dispatch
#-----------------------------------------------------------------------
case "$TARGET_TYPE" in
    gx10)   deploy_gx10   ;;
    runpod) deploy_runpod  ;;
    ssh)    deploy_ssh     ;;
    *)
        echo "ERROR: Unknown target type '$TARGET_TYPE'"
        usage
        ;;
esac

```

### Cena/Package.swift

```swift
//swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "Cena",
    platforms: [
        .macOS(.v14)
    ],
    products: [
        .executable(
            name: "Cena",
            targets: ["Cena"]
        )
    ],
    targets: [
        .executableTarget(
            name: "Cena",
            path: "Cena",
            exclude: ["Info.plist", "Cena.entitlements"],
            resources: [
                .process("Assets.xcassets")
            ]
        )
    ]
)

```

### Cena/create_xcode_project.sh

```shell
#!/bin/bash

# Create Xcode project for Cena
set -e

echo "🔧 Creating Xcode project for Cena..."

# Create Xcode project directory structure
PROJECT_DIR="Cena.xcodeproj"
mkdir -p "$PROJECT_DIR"

# Get all Swift source files
SOURCES=$(find Cena -name "*.swift" | sed 's/^/\t\t\t\t/' | sed 's/$/,/')

# Create project.pbxproj
cat > "$PROJECT_DIR/project.pbxproj" << 'EOF'
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 56;
	objects = {
		MAIN_GROUP /* Project object */ = {
			isa = PBXProject;
			attributes = {
				BuildIndependentTargetsInParallel = 1;
				LastSwiftUpdateCheck = 1500;
				LastUpgradeCheck = 1500;
			};
			buildConfigurationList = BUILD_CONFIGURATION_LIST;
			compatibilityVersion = "Xcode 14.0";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = MAIN_GROUP_REF;
			productRefGroup = PRODUCTS_GROUP;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				TARGET_CENA,
			);
		};
	};
	rootObject = MAIN_GROUP;
}
EOF

echo "✅ Xcode project structure created"
echo ""
echo "⚠️  For macOS apps with menu bars, it's best to use Xcode directly:"
echo ""
echo "  cd Cena"
echo "  open -a Xcode ."
echo ""
echo "Then in Xcode:"
echo "  1. File → New → Project"
echo "  2. Choose 'macOS → App'"
echo "  3. Name: Cena"
echo "  4. Interface: SwiftUI, Lifecycle: SwiftUI App"
echo "  5. Replace the generated files with our Swift files"
echo ""
echo "Or try the simpler command-line build:"
echo "  swift build"
echo ""

exit 0
EOF

chmod +x create_xcode_project.sh

```

### config/settings.py

```python
"""
config for cena — loads .env and exposes settings.
"""

import os
from pathlib import Path
from dotenv import load_dotenv

#.env from project root
_project_root = Path(__file__).resolve().parent.parent
load_dotenv(_project_root / ".env")

#local nemotron (vllm)
NEMOTRON_ENDPOINT: str = os.getenv("NEMOTRON_ENDPOINT", "http://localhost:8001/v1")
NEMOTRON_MODEL: str = os.getenv("NEMOTRON_MODEL", "nvidia/NVIDIA-Nemotron-Nano-9B-v2")

#cloud api keys
ANTHROPIC_API_KEY: str = os.getenv("ANTHROPIC_API_KEY", "")
OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", "")

#default cloud model
DEFAULT_CLOUD_MODEL: str = os.getenv("DEFAULT_CLOUD_MODEL", "claude-sonnet-4-20250514")

CLAUDE_MODELS = {
    "claude-sonnet-4-20250514",
    "claude-haiku-4-20250414",
    "claude-3-5-sonnet-20241022",
}
OPENAI_MODELS = {
    "gpt-4o",
    "gpt-4o-mini",
    "gpt-4-turbo",
}

#bright data (deepfake scanner)
BRIGHTDATA_API_TOKEN: str = os.getenv("BRIGHTDATA_API_TOKEN", "")
BRIGHTDATA_BROWSER_AUTH: str = os.getenv("BRIGHTDATA_BROWSER_AUTH", "")

#encryption server
ENCRYPTION_SERVER_URL: str = os.getenv("ENCRYPTION_SERVER_URL", os.getenv("GLAZE_SERVER_URL", "http://spark-abcd.local:5000"))
ENCRYPTION_DEFAULT_ITERS: int = int(os.getenv("ENCRYPTION_DEFAULT_ITERS", os.getenv("GLAZE_DEFAULT_ITERS", "200")))

#server
HOST: str = os.getenv("HOST", "127.0.0.1")
PORT: int = int(os.getenv("PORT", "8000"))


def get_provider(model: str) -> str:
    """Return 'claude' or 'openai' based on the cloud model name."""
    if model in CLAUDE_MODELS or model.startswith("claude"):
        return "claude"
    if model in OPENAI_MODELS or model.startswith("gpt"):
        return "openai"
    raise ValueError(f"Unknown cloud model: {model}. Must be a Claude or OpenAI GPT model.")

```

### client/backends.py

```python
"""
Backend resolver — picks the right GPU server URL from config or CLI args.
===========================================================================
Supports:
    --backend gx10       Look up named backend from backends.json
    --backend runpod     Look up RunPod backend (substitutes pod_id into URL)
    --server http://...  Direct URL override (ignores backends.json)

Environment variable overrides:
    ENCRYPTION_SERVER    Fallback URL if neither --backend nor --server given
    RUNPOD_POD_ID        RunPod pod ID (overrides backends.json pod_id)
    RUNPOD_API_KEY       RunPod API key
"""

import json
import os
import sys

#Path to backends.json (at repo root)
_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "..", "backends.json")


def load_backends_config() -> dict:
    """Load backends.json, return empty structure if missing."""
    path = os.path.abspath(_CONFIG_PATH)
    if not os.path.isfile(path):
        return {"backends": {}, "default": "local"}
    with open(path) as f:
        return json.load(f)


def resolve_backend(backend_name: str | None, server_url: str | None) -> str:
    """
    Resolve a server URL from the given arguments.

    Priority:
        1. --server <url>         (explicit URL, always wins)
        2. --backend <name>       (look up in backends.json)
        3. ENCRYPTION_SERVER env  (fallback)
        4. default from config    (last resort)

    Returns the fully-resolved HTTP URL string.
    """
    #1. Explicit URL
    if server_url:
        return server_url.rstrip("/")

    #2. Named backend
    config = load_backends_config()
    name = backend_name or os.environ.get("ENCRYPTION_BACKEND") or config.get("default", "local")
    backends = config.get("backends", {})

    if name not in backends:
        #Maybe it's a raw URL passed as --backend
        if name.startswith("http://") or name.startswith("https://"):
            return name.rstrip("/")
        available = ", ".join(backends.keys()) or "(none configured)"
        print(f"ERROR: Unknown backend '{name}'. Available: {available}")
        print(f"  Edit backends.json to add it, or use --server <url> directly.")
        sys.exit(1)

    entry = backends[name]
    url = entry.get("url", "")

    #Handle RunPod URL template
    if entry.get("type") == "runpod":
        pod_id = os.environ.get("RUNPOD_POD_ID") or entry.get("pod_id", "")
        if not pod_id:
            print(f"ERROR: RunPod backend '{name}' requires a pod_id.")
            print(f"  Set RUNPOD_POD_ID env var, or edit pod_id in backends.json.")
            sys.exit(1)
        url = url.replace("{POD_ID}", pod_id)

    if not url:
        print(f"ERROR: Backend '{name}' has no URL configured.")
        sys.exit(1)

    return url.rstrip("/")


def add_backend_args(parser):
    """
    Add --backend and --server arguments to an argparse parser.
    These are mutually supportive (--server overrides --backend).
    """
    config = load_backends_config()
    available = list(config.get("backends", {}).keys())
    default_name = config.get("default", "local")

    backend_help = f"Named backend from backends.json (available: {', '.join(available) or 'none'}; default: {default_name})"
    parser.add_argument(
        "--backend", "-b",
        default=None,
        help=backend_help,
    )
    parser.add_argument(
        "--server",
        default=None,
        help="Direct server URL (overrides --backend)",
    )


def get_server_url(args) -> str:
    """
    Convenience: resolve backend from parsed argparse args.
    Expects args to have .backend and .server attributes (from add_backend_args).
    """
    url = resolve_backend(
        getattr(args, "backend", None),
        getattr(args, "server", None),
    )
    return url


def print_backend_info(url: str, name: str | None = None):
    """Print which backend is being used."""
    label = f"'{name}' " if name else ""
    print(f"  Backend: {label}{url}")

```

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