> ## Documentation Index
> Fetch the complete documentation index at: https://ctpf.q-uestionable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# IPI Module Architecture

> Document generation, callback tracking, and deployment playbooks

The IPI (Indirect Prompt Injection) module generates adversarial documents with hidden instructions, tracks execution via authenticated HTTP callbacks, and produces deployment playbooks for guided testing.

## Module Structure

```
ipi/
├── generators/          # Format-specific document generators
│   ├── pdf.py           # Phase 1 + Phase 2 PDF techniques
│   ├── docx.py          # DOCX hiding techniques
│   ├── image.py         # Image/VLM techniques
│   ├── markdown.py      # Markdown hiding techniques
│   ├── html.py          # HTML hiding techniques
│   ├── ics.py           # Calendar invite techniques
│   └── eml.py           # Email techniques
├── generate_service.py  # generate_documents() — orchestrates generation
├── models.py            # Format, Technique, PayloadStyle, PayloadType, Campaign, Hit enums/dataclasses
├── listener.py          # start_server() — callback HTTP listener
├── server.py            # IPI callback server (FastAPI)
├── guidance_builder.py  # build_ipi_guidance() — deployment playbook generation
├── db.py                # IPI-specific SQLite operations (campaigns, hits)
├── cli.py               # generate, listen, techniques, formats, status, export, reset
├── adapter.py           # IPIAdapter for orchestrator integration
├── mapper.py            # persist_generate() — bridges campaigns to core DB
├── api.py               # Internal HTTP endpoints for bridge notifications
└── ui.py                # Web UI route handlers
```

## Supported Formats and Techniques

7 document formats, each with format-specific hiding techniques:

| Format       | Techniques                                                                                                                                     |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **PDF**      | Phase 1: white\_ink, off\_canvas, metadata. Phase 2: tiny\_text, white\_rect, form\_field, annotation, javascript, embedded\_file, incremental |
| **Image**    | visible\_text, subtle\_text, exif\_metadata                                                                                                    |
| **Markdown** | html\_comment, link\_reference, zero\_width, hidden\_block                                                                                     |
| **HTML**     | script\_comment, css\_offscreen, data\_attribute, meta\_tag                                                                                    |
| **DOCX**     | docx\_hidden\_text, docx\_tiny\_text, docx\_white\_text, docx\_comment, docx\_metadata, docx\_header\_footer                                   |
| **ICS**      | ics\_description, ics\_location, ics\_valarm, ics\_x\_property                                                                                 |
| **EML**      | eml\_x\_header, eml\_html\_hidden, eml\_attachment                                                                                             |

## Payload System

**PayloadStyle** controls the social engineering framing: `obvious`, `citation`, `reviewer`, `helpful`, `academic`, `compliance`, `datasource`.

**PayloadType** controls the attack objective: `callback` (default, benign proof of execution), `exfil_summary`, `exfil_context`, `ssrf_internal`, `instruction_override`, `tool_abuse`, `persistence`. Non-callback types require the `--dangerous` flag.

## Generation Pipeline

`generate_documents()` is the core function:

1. For each technique in the request, call the format-specific generator
2. Each generator embeds the payload instruction using the hiding technique
3. A unique UUID and authentication token are generated per document
4. The callback URL is embedded in the payload (`{callback_url}/c/{uuid}/{token}`)
5. Campaign records are created in the IPI database
6. `GenerateResult` returned with list of campaigns and any errors

## Callback Listener

`qai ipi listen` starts a FastAPI server that receives HTTP callbacks when AI systems execute the hidden payload.

**Hit model fields:** uuid (campaign match), source\_ip, user\_agent, timestamp, token\_valid (boolean), confidence (HIGH/MEDIUM/LOW).

**Confidence scoring:**

* **HIGH** — Valid campaign token present in the callback URL
* **MEDIUM** — No token but User-Agent matches programmatic HTTP clients (python-requests, httpx, curl)
* **LOW** — No token and browser/scanner User-Agent

## WebSocket Bridge

The IPI listener runs as a separate process. When a hit arrives, it notifies the main qai web server via an internal HTTP POST to `/api/ipi/internal/notify`. Authentication uses a shared bridge token from `~/.qai/bridge.token`.

The `--notify-url` flag on `qai ipi listen` controls the target (defaults to `http://127.0.0.1:8899`). The web server broadcasts the hit via WebSocket so the IPI tab in the run results view updates in real time.

## Guidance Builder

`build_ipi_guidance()` generates a `RunGuidance` with four blocks:

* **INVENTORY** — Lists generated files with technique, callback URL, and token
* **TRIGGER\_PROMPTS** — Format-aware, profile-specific prompts (AnythingLLM, Open WebUI, Generic) designed to cause the target to ingest the document
* **DEPLOYMENT\_STEPS** — Ordered instructions for uploading and triggering
* **MONITORING** — Confidence level explanations for interpreting hits

The web UI renders these as collapsible cards in the IPI run results tab.

## Adapter

`IPIAdapter` wraps generation for orchestrator workflows. It creates a child run, calls `generate_documents()` via `asyncio.to_thread()`, persists results, builds guidance, and transitions to `WAITING_FOR_USER` status (since deployment is a manual step).

## Database

IPI maintains its own tables (`ipi_campaigns`, `ipi_hits`) in the shared `~/.qai/qai.db` SQLite database, accessed through `ipi/db.py`. Campaign data is also bridged to the core runs/findings tables via `mapper.py`.
