Metadata-Version: 2.4
Name: signalforge-firewall
Version: 0.1.1
Summary: SignalForge helps local AI agents check claims, find evidence, and answer with the right level of confidence
Author: Karim Baidar, SignalForge contributors
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/karimbaidar/signalforge
Project-URL: Repository, https://github.com/karimbaidar/signalforge
Project-URL: Issues, https://github.com/karimbaidar/signalforge/issues
Project-URL: Documentation, https://github.com/karimbaidar/signalforge/tree/main/docs
Keywords: ai,ai-safety,agent-security,evidence,fact-checking,firewall,graphrag,llm,local-ai,mcp,neo4j,ollama,qdrant,rag,searxng,web-search
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.27
Requires-Dist: typer>=0.12
Requires-Dist: pydantic>=2.6
Requires-Dist: pydantic-settings>=2.2
Requires-Dist: httpx>=0.27
Requires-Dist: beautifulsoup4>=4.12
Requires-Dist: trafilatura>=1.8
Requires-Dist: neo4j>=5.17
Requires-Dist: qdrant-client>=1.8
Requires-Dist: python-dotenv>=1.0
Requires-Dist: rich>=13.7
Requires-Dist: pillow>=10.0
Provides-Extra: local-models
Requires-Dist: sentence-transformers>=2.7; extra == "local-models"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"
Provides-Extra: mcp
Requires-Dist: mcp>=1.0.0; extra == "mcp"
Dynamic: license-file

# SignalForge Firewall: Receipts for AI answers.

**SignalForge is a local-first Evidence Firewall for AI answers: it gives local models live web context, then stops them from repeating claims that are unsupported, contradicted, stale, or sourced from weak evidence.**

SignalForge is not a generic chatbot and not a generic RAG app. It is a claim-level evidence control layer for Ollama, Open WebUI, AnythingLLM, MCP tools, and local agent workflows.

Core loop:

```text
Answer -> Receipt -> Snapshot -> Replay
```

## Why This Exists

Local models are useful, private, and cheap to run. The moment you give them web access, they inherit the web's problems: copied rumors, stale pages, thin sources, prompt injection, private-network fetch risks, and confident claims that trace back to one weak origin.

Normal RAG retrieves context. SignalForge decides what the model is allowed to say.

The product promise is simple:

- Receipts for AI answers
- Git commits for AI answers
- Evidence Firewall for local AI
- Local models can now refuse unsupported claims
- MCP needs a firewall

## What It Does

SignalForge takes a claim or model answer and produces a signed Evidence Receipt:

- normalizes the claim
- classifies risk domain and verifiability
- searches through local SearXNG
- optionally fetches, extracts, hashes, sanitizes, and redacts source text
- scores support strength, source independence, source reputation, freshness, copy-chain risk, prompt-injection risk, and contradiction pressure
- assigns a FIRE permission
- stores a replay snapshot
- renders JSON, Markdown, share text, receipt card data, and a downloadable receipt bundle
- exposes graph, replay, policy, receipt, OpenAI-compatible proxy, browser extension, and MCP surfaces

FIRE permissions:

```text
VERIFIED
SUPPORTED
WEAKLY_SUPPORTED
RUMOR_ONLY
UNSUPPORTED
CONTRADICTED
EXPIRED
BLOCKED
```

## 60-Second Demo

Start the stack:

```bash
docker compose up -d --build
docker exec signalforge-firewall-ollama-1 ollama pull qwen2.5:3b-instruct
open http://localhost:4011
```

Verify a claim:

```bash
curl -X POST http://localhost:4010/v1/firewall/verify-claim \
  -H "Content-Type: application/json" \
  -d '{"claim":"Company X officially confirmed a partnership with Company Y","mode":"strict"}'
```

Then open:

```bash
curl http://localhost:4010/v1/firewall/receipt/<run_id>/card
curl http://localhost:4010/v1/firewall/receipt/<run_id>/markdown
curl http://localhost:4010/v1/firewall/replay/<run_id>
```

Screenshot placeholders for launch assets:

- `docs/assets/dashboard-claim-verifier.png`
- `docs/assets/receipt-card.png`
- `docs/assets/evidence-graph.png`
- `docs/assets/replay-snapshot.png`

## Quickstart With Docker

```bash
cp .env.example .env
docker compose up -d --build
open http://localhost:4011
```

Services:

- API: <http://localhost:4010>
- Dashboard: <http://localhost:4011>
- SearXNG: <http://localhost:8089>
- Ollama: <http://localhost:11434>
- Qdrant: <http://localhost:6333>
- Neo4j Browser: <http://localhost:7474>
- Optional Open WebUI profile: <http://localhost:3000>

Optional Open WebUI profile:

```bash
docker compose --profile openwebui up -d --build
```

## Quickstart With Python

```bash
pnpm install
uv sync --extra dev
uv run pytest
uv run signalforge serve
```

API: <http://localhost:4010>

Dashboard in another shell:

```bash
cd dashboard
npm install
npm run dev
```

Dashboard: <http://localhost:4011>

## How agents should use SignalForge

SignalForge is not only a yes/no checker. It tells an agent how strongly it may speak.

- `SUPPORTED` or `VERIFIED`: the agent can answer normally and include the source.
- `WEAKLY_SUPPORTED`: the agent should use attribution, for example “DW reports that...”.
- `UNSUPPORTED`, `CONTRADICTED`, or `BLOCKED`: the agent should not state the claim as fact.

A single strong source should count as useful evidence, but multiple independent sources are still better for high-confidence claims. See [docs/AGENT_USE_CASES_AND_SCORING.md](docs/AGENT_USE_CASES_AND_SCORING.md).

## CLI Usage

The package installs both `signalforge` and `sf`:

```bash
sf verify "Company X confirmed a partnership with Company Y"
sf search "Company X Company Y official confirmation"
sf answer "Did Company X confirm a partnership with Company Y?" --with-receipt
sf receipt <run_id>
sf replay <run_id>
sf inspect examples/sample_answer.md
sf doctor
sf policy list
sf policy show finance
```

## REST API Examples

Verify a claim:

```bash
curl -X POST http://localhost:4010/v1/firewall/verify-claim \
  -H "Content-Type: application/json" \
  -d '{"claim":"The company officially confirmed the partnership.","mode":"strict"}'
```

Search evidence:

```bash
curl -X POST http://localhost:4010/v1/firewall/search \
  -H "Content-Type: application/json" \
  -d '{"query":"official source partnership confirmation","mode":"research","max_results":5}'
```

Inspect a model answer:

```bash
curl -X POST http://localhost:4010/v1/firewall/inspect-answer \
  -H "Content-Type: application/json" \
  -d '{"answer":"Company X confirmed the deal. Analysts expect the stock to double.","mode":"strict"}'
```

Receipt exports:

```bash
curl http://localhost:4010/v1/firewall/receipt/<run_id>
curl http://localhost:4010/v1/firewall/receipt/<run_id>/card
curl http://localhost:4010/v1/firewall/receipt/<run_id>/markdown
curl -OJ http://localhost:4010/v1/firewall/receipt/<run_id>/bundle
curl http://localhost:4010/v1/firewall/replay/<run_id>
```

Policy packs:

```bash
curl http://localhost:4010/v1/firewall/policies
curl http://localhost:4010/v1/firewall/policies/medical
```

## OpenAI-Compatible Proxy

SignalForge exposes an OpenAI-compatible chat endpoint:

```text
POST http://localhost:4010/v1/chat/completions
```

Point Open WebUI, AnythingLLM, or an OpenAI-compatible local client at:

```text
Base URL: http://localhost:4010/v1
API key: local
Model: your local upstream model name
```

SignalForge forwards to `OPENAI_PROXY_UPSTREAM_URL`, inspects the upstream answer claim by claim, and rewrites the output when claims are downgraded or blocked.

## Open WebUI / Ollama

Default Docker wiring:

```env
OPENAI_PROXY_UPSTREAM_URL=http://ollama:11434/v1
OLLAMA_BASE_URL=http://ollama:11434
```

Open WebUI should use:

```text
OpenAI-compatible base URL: http://signalforge-firewall:4010/v1
API key: local
```

See [docs/integrations/OPEN_WEBUI.md](docs/integrations/OPEN_WEBUI.md).

## MCP Firewall

SignalForge includes an optional MCP server and a tool-call firewall. The firewall provides:

- allowlist and denylist controls
- private IP, localhost, metadata IP, and `.local` blocking
- URL validation
- basic argument schema validation
- risk labels
- clear denial reasons

Run:

```bash
sf mcp
```

See [docs/MCP_TOOLS.md](docs/MCP_TOOLS.md).

## Evidence Map

SignalForge includes an Evidence Map that explains why a claim received its FIRE permission. The default view is now **Why this verdict?**, which shows the conclusion path instead of dumping every relationship at once.

The map supports:

- guided conclusion layout
- support, contradiction, independence, receipt, replay, and full explorer modes
- mouse wheel zoom
- drag-to-pan
- minimap overview
- keyboard shortcuts: `+`, `-`, `f`, `0`
- plain-language verdict explanation panel

See [docs/GRAPH_REDESIGN_SPEC.md](docs/GRAPH_REDESIGN_SPEC.md).

## Browser Extension

The alpha browser extension supports:

- right-click selected text -> Verify with SignalForge
- local API verification
- notification with permission and proof score/share text
- popup with copy proof text
- open dashboard receipt

Load `integrations/browser-extension` as an unpacked Manifest V3 extension. See [docs/integrations/BROWSER_EXTENSION.md](docs/integrations/BROWSER_EXTENSION.md).

## Receipt Card Example

```json
{
  "title": "SignalForge FIRE Receipt",
  "subtitle": "Evidence-limited proof card",
  "run_id": "sf_1234",
  "claim": "Company X officially confirmed a partnership with Company Y",
  "permission": "RUMOR_ONLY",
  "confidence": 0.42,
  "independent_source_count": 1,
  "contradiction_count": 0,
  "replay_url": "/v1/firewall/replay/sf_1234",
  "markdown_url": "/v1/firewall/receipt/sf_1234/markdown",
  "bundle_url": "/v1/firewall/receipt/sf_1234/bundle",
  "share_text": "Evidence-limited proof card: ...",
  "signed_metadata": {
    "signature_algorithm": "hmac-sha256"
  }
}
```

## Security And Privacy Notes

SignalForge is local-first and does not require paid APIs. It can run with Ollama, SearXNG, Neo4j, Qdrant, and local storage.

Alpha safety controls include:

- local/metadata/private-IP blocking in fetch and MCP tool paths
- bounded fetch size, timeout, content-type checks, and redirect limits
- prompt-injection warning and sanitizer heuristics
- optional minimized snapshots
- optional PII redaction for stored extracted text
- domain allowlist and blocklist settings
- robots/opt-out placeholder hooks for teams to wire into their own source policy

Careful wording: SignalForge helps teams apply source policies. It does not provide legal advice.

## Roadmap

- stronger deterministic claim extraction
- optional local NLI/cross-encoder contradiction profile
- richer replay comparison with live source refetching
- PNG receipt cards
- signed release artifacts
- better browser extension UX
- larger benchmark set
- policy-pack enforcement inside the verifier
- team review and audit workflows

## Contributing

Contributions are welcome, but every change must protect the evidence-firewall mission: claim-level evidence control, receipts, snapshots, replay, contradiction detection, source independence, local-first operation, and MCP/tool safety.

### Contribution Rules

- All changes must go through a pull request. Direct pushes to `main` are blocked after the initial repository upload.
- `main` is protected. A pull request must pass required CI before it can merge.
- At least one approving review is required before merge.
- Reviews are dismissed when new commits are pushed, so reviewers always approve the latest code.
- Force pushes and branch deletion are disabled for `main`.
- `CODEOWNERS` assigns repository ownership to `@karimbaidar`; security-sensitive or product-direction changes should wait for owner review.
- Keep the project local-first and zero-dollar by default. Do not add paid API dependencies or hosted LLM requirements.
- Do not turn SignalForge into a generic chatbot or generic RAG app.
- Do not rename SignalForge, FIRE receipts, or the FIRE permission model without an explicit product decision.
- Keep public API, receipt, replay, and graph schemas stable unless the pull request clearly documents a breaking change.
- Tests must not call external networks or hosted APIs. Mock SearXNG, Neo4j, Qdrant, Ollama, MCP, and browser-extension integrations.
- Keep pull requests focused. Separate unrelated refactors, feature work, documentation, and release chores.
- Update documentation when behavior, commands, APIs, policies, receipts, or dashboard workflows change.

### Required CI

Every pull request must satisfy the repository CI workflow:

```bash
python -m pip install -e ".[dev]"
python -m pip check
python -m compileall -q src tests
python -m pytest
cd dashboard && npm ci && npm run build
python -m build
docker compose -f compose.yaml config
```

The protected branch requires these GitHub Actions checks:

- `Python 3.11`
- `Python 3.12`
- `Dashboard build`
- `Package build`
- `Docker compose config`

Start with [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, product boundaries, and pull request expectations.

## Star The Repo

If SignalForge helps your local AI workflow, please star the GitHub repo i.e. https://github.com/karimbaidar/signalforge. Stars make it easier for builders working on local AI safety, agent security, and open-source evidence tooling to find the project.

## License

Apache-2.0. See [LICENSE](LICENSE).
