diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 420c9b4..226f3c9 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -8,6 +8,8 @@ on:
- "mkdocs.yml"
- "scripts/gen_ref_pages.py"
- "src/provena/**"
+ - "pyproject.toml"
+ - ".github/workflows/docs.yml"
pull_request:
branches: [main]
paths:
@@ -15,33 +17,48 @@ on:
- "mkdocs.yml"
- "scripts/gen_ref_pages.py"
- "src/provena/**"
+ - "pyproject.toml"
+ - ".github/workflows/docs.yml"
+ workflow_dispatch:
permissions:
- contents: write
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: false
jobs:
build:
- if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
+ - name: Setup Pages
+ if: github.event_name != 'pull_request'
+ uses: actions/configure-pages@v5
- name: Install dependencies
run: pip install -e ".[docs]"
- name: Build docs (strict)
run: mkdocs build --strict
+ - name: Upload Pages artifact
+ if: github.event_name != 'pull_request'
+ uses: actions/upload-pages-artifact@v5
+ with:
+ path: site
deploy:
- if: github.event_name == 'push'
+ if: github.event_name != 'pull_request'
+ needs: build
runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
- with:
- python-version: "3.12"
- - name: Install dependencies
- run: pip install -e ".[docs]"
- name: Deploy to GitHub Pages
- run: mkdocs gh-deploy --force
+ id: deployment
+ uses: actions/deploy-pages@v5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 989b697..49174c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
## [Unreleased]
+### Changed
+
+- Documentation now publishes to GitHub Pages with Actions artifact deploy (`upload-pages-artifact` + `deploy-pages`) instead of `mkdocs gh-deploy`
+- Docs homepage is a project landing page with feature cards, comparison table, and CTAs
+
### Fixed
- **`PolicyEngine.from_config()` now accepts a `_signed_ref` to wire `require_signing` to the trail's real signing state.** Previously, calling `from_config()` standalone (without a `ContextTrail` to patch it afterward) built a `require_signing` policy stuck on its `[False]` default, so a `block`-level `require_signing` check would deny every record regardless of whether the trail was signed. `ContextTrail(config=...)` now passes its own signing state through directly instead of relying solely on the post-construction patch (#141)
diff --git a/docs/.nojekyll b/docs/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/docs/index.md b/docs/index.md
index 631e9b5..a0df737 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,10 +1,18 @@
+---
+title: Provena
+description: Context governance for agentic AI systems — tamper-evident audit trails in 3 lines of Python.
+hide:
+ - navigation
+ - toc
+---
+
# Provena
-**Context governance for agentic AI systems.**
+**Govern what your agents know.**
Your AI agent just made a decision based on data from 6 different sources.
Can you tell me which ones? Can you prove the data wasn't tampered with?
-Can you verify it was still current?
+Can you verify it was still current when the LLM saw it?
Provena adds tamper-evident audit trails to any AI agent's context pipeline — in 3 lines of Python.
@@ -19,32 +27,78 @@ def search(query):
return retriever.search(query)
```
-Every call to `search()` is now logged with a SHA-256 content hash, provenance validation,
-and a hash-chained audit trail that detects tampering.
+Every call to `search()` is logged with a SHA-256 content hash, provenance validation,
+freshness checking, and a hash-chained audit trail that detects tampering.
+
+
+
+[Get started](getting-started.md){ .md-button .md-button--primary }
+[GitHub](https://github.com/rajfirke/provena){ .md-button }
+[PyPI](https://pypi.org/project/provena/){ .md-button }
+
+
+
+```bash
+pip install provena
+```
## Why Provena?
> **AGT governs what agents DO. Guardrails AI governs what agents SAY. Provena governs what agents KNOW.**
-No existing tool governs the context input layer. Provena fills this gap with:
+
-- **Tamper-evident audit trails** — SHA-256 hash-chained (Merkle-style) logging with optional HMAC signing
-- **Provenance validation** — Verify that context carries proper source metadata (VALID / MISSING / INCOMPLETE)
-- **Freshness checking** — Detect stale context via metadata timestamps and regex temporal detection (FRESH / STALE / UNKNOWN)
-- **Any context source** — RAG retrievers, tool outputs, agent messages, memory recalls, MCP resources
-- **Sub-1ms overhead** — Pure Python, no ML models, no downloads
-- **Zero dependencies** — Core library uses only the Python standard library
+- :material-shield-lock:{ .lg .middle } **Tamper-evident trails**
-## Install
+ ---
-```bash
-pip install provena # core (zero dependencies)
-pip install provena[cli] # + CLI tools (click, rich)
-pip install provena[otel] # + OpenTelemetry export
-pip install provena[langchain] # + LangChain adapter
-pip install provena[llamaindex] # + LlamaIndex adapter
-pip install provena[all] # everything
-```
+ SHA-256 hash-chained (Merkle-style) logging with optional HMAC signing.
+ If a record is edited, the chain breaks.
+
+ [:octicons-arrow-right-24: Chain verification](guide/verification.md)
+
+- :material-source-branch:{ .lg .middle } **Provenance validation**
+
+ ---
+
+ Verify that context carries source metadata.
+ Statuses: `VALID` / `MISSING` / `INCOMPLETE`.
+
+ [:octicons-arrow-right-24: Provenance guide](guide/provenance.md)
+
+- :material-clock-check:{ .lg .middle } **Freshness checking**
+
+ ---
+
+ Detect stale context from timestamps and temporal patterns.
+ Statuses: `FRESH` / `STALE` / `UNKNOWN`.
+
+ [:octicons-arrow-right-24: Freshness guide](guide/freshness.md)
+
+- :material-gavel:{ .lg .middle } **EU AI Act & ASI06**
+
+ ---
+
+ Maps to Articles 10, 12, 13, and 14, and covers
+ [OWASP ASI06](compliance/owasp-asi06.md) context poisoning.
+
+ [:octicons-arrow-right-24: EU AI Act mapping](compliance/eu-ai-act.md)
+
+
+
+## How it compares
+
+No existing tool governs the context input layer — the data your agent retrieves and acts on.
+
+| | Provena | LangSmith | Guardrails AI | OpenTelemetry |
+|---|---|---|---|---|
+| Context tamper detection | ✅ | ❌ | ❌ | ❌ |
+| Provenance validation | ✅ | ❌ | ❌ | ❌ |
+| Freshness checking | ✅ | ❌ | ❌ | ❌ |
+| EU AI Act compliance reports | ✅ | ❌ | ❌ | ❌ |
+| Policy enforcement (block/warn) | ✅ | ❌ | ✅ (output) | ❌ |
+| Multi-agent handoff tracking | ✅ | ✅ | ❌ | ❌ |
+| Zero core dependencies | ✅ | ❌ | ❌ | ❌ |
## Architecture
@@ -65,22 +119,42 @@ Your Application
| +------------------------+
```
-## Compliance
+Pure Python, sub-1ms overhead, no model downloads. The core library uses only the standard library.
+
+## Next steps
+
+
+
+- :material-rocket-launch:{ .lg .middle } **Getting started**
+
+ ---
+
+ Install, log a first trail, and verify the chain in 5 minutes.
+
+ [:octicons-arrow-right-24: Start here](getting-started.md)
+
+- :material-book-open-variant:{ .lg .middle } **Guide**
+
+ ---
+
+ Tracking, provenance, freshness, verification, configuration, and testing.
+
+ [:octicons-arrow-right-24: Read the guide](guide/tracking.md)
+
+- :material-puzzle:{ .lg .middle } **Integrations**
+
+ ---
+
+ LangChain, LlamaIndex, OpenTelemetry, MCP, and the CLI.
+
+ [:octicons-arrow-right-24: Wire it in](integrations/langchain.md)
-Provena maps directly to EU AI Act requirements:
+- :material-code-braces:{ .lg .middle } **API reference**
-| Article | Requirement | Provena Feature |
-|---------|------------|-----------------|
-| Art. 10 | Data lineage | Provenance validation for every context input |
-| Art. 12 | Tamper-evident logging | SHA-256 hash-chained audit trail with HMAC signing |
-| Art. 13 | Transparency | `trail.summary()` and source tracking |
-| Art. 14 | Human oversight | `trail.annotate()` for reviewer decisions |
+ ---
-Also addresses [OWASP ASI06](compliance/owasp-asi06.md) (Memory & Context Poisoning).
+ Auto-generated from the public Python API.
-## Next Steps
+ [:octicons-arrow-right-24: Browse the API](api/provena/index.md)
-- [Getting Started](getting-started.md) — Install, first trail, verify chain in 5 minutes
-- [Guide](guide/tracking.md) — Deep-dive into tracking, provenance, freshness, and verification
-- [Integrations](integrations/langchain.md) — LangChain, LlamaIndex, OpenTelemetry, CLI
-- [API Reference](api/provena/index.md) — Auto-generated from docstrings
+
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css
new file mode 100644
index 0000000..e7ee1e4
--- /dev/null
+++ b/docs/stylesheets/extra.css
@@ -0,0 +1,8 @@
+.md-typeset .md-button {
+ margin-right: 0.4rem;
+ margin-bottom: 0.4rem;
+}
+
+.md-typeset .hero-actions {
+ margin: 1.2rem 0 1.6rem;
+}
diff --git a/mkdocs.yml b/mkdocs.yml
index 30ad773..db3941e 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -4,17 +4,22 @@ site_description: Context governance for agentic AI systems
repo_url: https://github.com/rajfirke/provena
repo_name: rajfirke/provena
edit_uri: edit/main/docs/
+copyright: Copyright © 2026 Raj Firke — Apache 2.0
theme:
name: material
+ icon:
+ logo: material/shield-lock
palette:
- scheme: default
primary: indigo
+ accent: indigo
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
primary: indigo
+ accent: indigo
toggle:
icon: material/brightness-4
name: Switch to light mode
@@ -22,11 +27,22 @@ theme:
- navigation.sections
- navigation.expand
- navigation.top
+ - navigation.footer
- content.code.copy
- content.code.annotate
- search.highlight
- search.suggest
+extra_css:
+ - stylesheets/extra.css
+
+extra:
+ social:
+ - icon: fontawesome/brands/github
+ link: https://github.com/rajfirke/provena
+ - icon: fontawesome/brands/python
+ link: https://pypi.org/project/provena/
+
plugins:
- search
- gen-files:
@@ -71,12 +87,16 @@ nav:
markdown_extensions:
- admonition
+ - attr_list
+ - md_in_html
- pymdownx.details
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- - attr_list
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
- toc:
permalink: true