Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: release

on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
publish:
description: "Publish to PyPI"
required: true
default: "false"
type: choice
options: ["false", "true"]

jobs:
quality:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Run tests
run: python -m pytest -q

- name: Run security checks
run: python -m bandit -q -r src/predicate_secure/

- name: Run pre-commit checks
run: |
python -m pip install pre-commit
pre-commit run --all-files

publish:
runs-on: ubuntu-latest
needs: [quality]
if: (github.event_name == 'workflow_dispatch' && inputs.publish == 'true') || startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install build tooling
run: python -m pip install --upgrade pip build twine

- name: Validate version matches tag
if: startsWith(github.ref, 'refs/tags/v')
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "Tag version ($TAG_VERSION) does not match package version ($PKG_VERSION)"
exit 1
fi
echo "Version validated: $PKG_VERSION"

- name: Build package
run: python -m build

- name: Validate distribution metadata
run: twine check dist/*

- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN_PREDICATE_SECURE }}
run: twine upload dist/*
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# predicate-secure

[![License](https://img.shields.io/badge/License-MIT%2FApache--2.0-blue.svg)](LICENSE)
[![PyPI - predicate-secure](https://img.shields.io/pypi/v/predicate-secure.svg)](https://pypi.org/project/predicate-secure/)

Drop-in security wrapper for AI agents. Adds authorization, verification, and audit to any agent framework in 3 lines of code.

## Features
Expand Down Expand Up @@ -67,8 +70,8 @@ secure_agent.run()

`predicate-secure` is a thin orchestration layer that combines:

- **predicate** (sdk-python) - Snapshot engine, DOM pruning, verification predicates
- **predicate-authority** (AgentIdentity) - Policy engine, mandate signing, audit logging
- **[predicate-runtime](https://github.com/PredicateSystems/sdk-python)** - Snapshot engine, DOM pruning, verification predicates
- **[predicate-authority](https://github.com/PredicateSystems/predicate-authority)** - Policy engine, mandate signing, audit logging

```
SecureAgent
Expand Down
Loading
Loading