Skip to main content
CTPF Research Harness is a local Python harness with one preferred public operator entry point: the ctpf CLI. The former qai executable remains a compatibility alias. This page matches the durable invariants in the repository docs/Architecture.md after the Phase 1 shape cut.

System shape

Centered substrate:
AreaResponsibility
proxyCapture, intercept, live modify, export MCP traffic (Textual TUI)
mcpMCP transports and sessions (stdio, SSE, streamable HTTP)
coreShared models, SQLite persistence, config, credentials, providers
Library modules (not public CLI pillars; fixtures / research code):
AreaResponsibility
auditCapability enumeration / scanners; SARIF export
ipiDocument generators + headless callback listener
cxpCoding-assistant context-file generators
injectMalicious MCP fixture servers (build_server + payload templates)
Removed in Phase 1 (do not restore without explicit instruction): Web UI (server/), assist/, rxp/, chain/, orchestrator/, imports/, and the inject campaign/scoring path.

Public CLI (transitional)

ctpf proxy          # Intercept / modify / export MCP traffic
ctpf experiment     # Run controlled CTPF experiments
ctpf targets        # Register MCP targets
ctpf runs           # Inspect stored runs
ctpf findings       # Inspect stored findings
ctpf config         # Settings and OS-keyring credentials
ctpf db             # Local database maintenance
ctpf --version
New verbs such as inspect / evidence are deferred until a CTPF experiment defines a real interface. Library Typer apps may remain for fixture workflows (python -m q_ai.ipi, python -m q_ai.inject) but are not root ctpf pillars.

Shared backbone

Persistence is a local SQLite database (~/.qai/qai.db). The common schema centers on targets, runs, findings, evidence, and settings, with additional tables retained for historical module data (proxy sessions, IPI hits, legacy chain/inject/RXP tables may still exist for old DBs even when writers are gone). core/db.py provides shared database access used by the transitional CLI (get_connection, target/run/finding helpers, and the default DB path). services/db_service.py covers backup, reset, and delete operations only. Former UI/workflow service helpers were removed with the Web UI and orchestrator.

Boundaries

Core

core owns durable cross-cutting contracts: database access, schema migration, shared data models, configuration, credential lookup (OS keyring), and provider/model abstractions.

MCP

mcp centralizes client connections to MCP servers. Proxy adapters and other callers build on that shared async transport boundary.

Proxy

proxy is the CTPF observation center: bidirectional message capture, optional intercept with forward / modify / drop, session persistence, and export. Live mutation of server→client tool results is a first-class research path; full agent counterfactual replay is not assumed.

Operator surface

cli.py is the only public product surface.

LLM boundary

Provider-facing code stays behind shared core interfaces (core.llm, core.providers, LiteLLM-backed implementation). Modules that need models consume that boundary rather than embedding provider SDKs directly.

Security and trust invariants

  • Any local HTTP listener (IPI headless callback, proxy listen adapters) binds to 127.0.0.1 only — never 0.0.0.0 or external interfaces for product surfaces.
  • API keys go in the OS keyring only — never config files or source code.
  • The IPI callback listener may optionally expose itself via a tunnel adapter (--tunnel cloudflare) for testing remote/cloud AI targets, with tunnel-mode hardening documented in the IPI library pages.

Configuration precedence

CLI flags (highest priority)
  → Environment variables
    → Database settings (ctpf config)
      → YAML config file (~/.qai/config.yaml)
        → Built-in defaults (lowest priority)
Credentials follow a separate chain: environment variable → OS keyring → error (prefer keyring for durable storage).

Next steps