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