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
14 changes: 14 additions & 0 deletions sema-policies/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 0.2.0 — 2026-08-01

### Added

- Semantic subject allowlists and reusable file, network, command, and external-action rule builders.
- Configurable input controls and workflow evidence requirements.
- Safe coding-agent, draft-only customer-support, employment-assistance, human-review, and change-control profiles.
- Human-oversight documentation, reviewable-output, certainty-audit, and placeholder-output profiles.
- Composable deny-only profiles for file writes, network requests, commands, and external actions requested through tools.

### Fixed

- Constructors reject extra or unknown options instead of silently ignoring them.

## 0.1.0 — 2026-07-31

### Added
Expand Down
245 changes: 159 additions & 86 deletions sema-policies/README.md
Original file line number Diff line number Diff line change
@@ -1,97 +1,151 @@
# sema-policies

Reusable least-privilege, content-safety, output, and workflow-evidence policies.
Reusable least-privilege, content-safety, human-review, output, and workflow-evidence policies.

These policies are deterministic runtime controls, not legal or regulatory
certifications. Content profiles cover Sema's documented detectors; they do not
classify arbitrary sensitive information.

Version 0.1 intentionally excludes approval workflows, model rerouting,
domain-specific semantic classifiers, and the third-party HeartFlow rule set.
Those controls need dedicated runtime support or licensed rule definitions;
generic literal and regex output rules are available through
`policies/output-contract`.
classify arbitrary sensitive information or prove that a statement is true.

## Install

```bash
sema pkg add sema-policies
```

Requires Sema 1.34.0 or newer.
Version 0.2.0 requires Sema 1.34.0 or newer.

## Quick start
## Safe coding agent

```sema
(import "sema-policies")

(define project-policy
(list
(policies/model-allowlist ["openai/gpt-5"])
(policies/read-only-repository ["src/**" "Cargo.toml"])
policies/no-sensitive-data-to-models))

(defworkflow inspect "Inspect a repository"
(policies/safe-code-agent
{:models ["openai/gpt-5" "ollama/*"]
:read ["src/**" "tests/**" "Cargo.toml"]
:write ["src/**" "tests/**"]
:commands ["cargo test" "git diff"]
:domains ["docs.rs"]}))

(defworkflow inspect-and-test "Inspect a repository under a strict policy."
{:policy project-policy}
(phase "Inspect")
(step "Inspect the project and run its tests." {:tools [read-file write-file run-command]})
{:status :success})
```

Commands are exact strings. Network access defaults to `GET` and HTTPS is still
subject to the core domain selector. Tool definitions must declare semantic
policy subjects; an undeclared tool is denied by this profile.

`:network-methods` is valid only with a non-empty `:domains` list. An explicitly
empty method list is rejected instead of being interpreted as unrestricted.

Policy lists compose as an intersection: every layer must allow an operation,
and the strictest content action wins.

## Human review

`policies/human-reviewed-run` makes a successful run require an applied,
signature-validated approval gate:

```sema
(import "sema-policies")

(defworkflow publish-report "Review before publication."
{:policy policies/human-reviewed-run}

(phase "Draft")
(define report (checkpoint :report (build-report)))

(phase "Review")
(approval :editor-signoff
{:reason "Publish a public report"
:subject {:kind :external-action
:target "public-site"
:report-digest (hash/sha256 report)}
:preview "Publish the reviewed report"})

(phase "Publish")
(publish-report report)
{:status :success})
```

Place the explicit gate immediately before the protected action. The profile
requires that some `approval.applied` event occurred before success; it does not
automatically attach a gate to a matching tool call or prove that a particular
gate authorized a particular later action.

`policies/change-controlled` also requires `:owner`, `:change-id`, and
`:environment` workflow metadata.

## API

| Function or value | Description |
|---|---|
| `(policies/model-allowlist identities opts?)` | Allow specific `provider/model` identities |
| `(policies/tool-allowlist rules opts?)` | Allow named tools with argument constraints |
| `(policies/read-only-repository paths)` | Allow declared file reads under selected paths |
| `(policies/output-contract contract)` | Enforce LLM-output schema, required fields, limits, patterns, or detectors |
| `policies/no-tools` | Deny every model-requested tool call |
| `policies/no-sensitive-data-to-models` | Block secrets/cards and redact supported personal-data patterns before dispatch |
| `policies/public-content` | Block every supported sensitive-content detector on input and output |
| `policies/public-sector-rag` | Require ownership/source metadata, structured cited LLM output, content controls, and a checkpoint |
| `policies/ai-act-docs-lite` | Require basic ownership/risk/purpose metadata, structured LLM decision records, and a checkpoint |
### Constructors and rule builders

### `policies/model-allowlist`
| Function | Description |
|---|---|
| `(policies/model-allowlist identities opts?)` | Allow exact `provider/model` identities or `provider/*` |
| `(policies/tool-allowlist rules opts?)` | Allow named tools with path, domain, or exact-command constraints |
| `(policies/subject-allowlist rules opts?)` | Allow only matching semantic tool subjects; `:deny` rules take precedence |
| `(policies/file-read-rule paths)` | Build a `:file-read` subject rule |
| `(policies/file-write-rule paths)` | Build a `:file-write` subject rule |
| `(policies/file-delete-rule paths)` | Build a `:file-delete` subject rule |
| `(policies/network-rule domains opts?)` | Build a network rule; `:methods` restricts HTTP methods |
| `(policies/command-rule commands)` | Build an exact-command rule |
| `(policies/external-action-rule actions)` | Build a rule for exact declared action names |
| `(policies/input-controls detectors opts?)` | Configure deterministic input detectors and actions |
| `(policies/evidence-requirements requirements)` | Require workflow metadata and/or event kinds |
| `(policies/read-only-repository paths)` | Allow declared file reads under selected paths and deny other subject kinds |
| `(policies/output-contract contract)` | Enforce an arbitrary core output policy map |

Use one combined `policies/subject-allowlist` when several subject kinds must be
allowed. Two separate default-deny subject policies intersect and can deny each
other's otherwise valid operations.

```sema
(policies/model-allowlist
["openai/gpt-5" "ollama/*"]
{:on-deny :skip})
(policies/subject-allowlist
[(policies/file-read-rule ["src/**" "Cargo.toml"])
(policies/file-write-rule {:allow ["src/**"]
:deny ["src/generated/**"]})
(policies/network-rule ["api.example.com"] {:methods ["GET"]})
(policies/command-rule ["cargo test"])
(policies/external-action-rule ["ticket-read"])])
```

`identities` is a non-empty list or vector. Exact `provider/model` identities
and the `provider/*` wildcard are supported. `:on-deny :skip` is useful inside
fallback routing; the default is `:fail`.
Path and domain arguments accept either a non-empty shorthand sequence or the
core selector map with `:allow` and `:deny`. Domain selectors may also specify
`:schemes` and `:ports`.

### `policies/tool-allowlist`
### Configurable input controls

```sema
(policies/tool-allowlist
{"read-file" {:paths ["src/**" "Cargo.toml"]}
"fetch-url" {:domains {:allow ["docs.example.com"]
:schemes ["https"]
:ports [443]}}})
(policies/input-controls
[:secret :payment-card :email]
{:actions {:secret :block
:payment-card :block
:email :redact}})
```

Map each allowed tool name to its path, domain, or exact-command constraints.
The default denial becomes a tool-visible error; pass `{:on-deny :fail}` to
abort the run instead.
Supported detector families are `:secret`, `:payment-card`, `:email`, `:phone`,
and `:ipv4`. Actions are `:audit`, `:redact`, or `:block`; a detector without an
explicit action blocks.

### `policies/read-only-repository`
### Evidence requirements

```sema
(policies/read-only-repository ["src/**" "crates/**" "Cargo.toml"])
(policies/evidence-requirements
{:metadata [:owner :intended-purpose]
:events [:checkpoint :approval.applied]})
```

This profile evaluates semantic subjects declared by `deftool`, so it is
independent of tool names. It permits matching `:file-read` subjects and denies
file writes/deletes, commands, network requests, external actions, undeclared
subjects, and paths outside the workspace.
Metadata values must be present and non-empty. Completion requirements match
event kinds, not event fields. They cannot yet require a particular checkpoint
key, tool name, command, or approval key.

### Output controls

### `policies/output-contract`
`policies/output-contract` exposes the core `:output` map:

```sema
(policies/output-contract
Expand All @@ -102,58 +156,77 @@ subjects, and paths outside the workspace.
:forbid [{:id :no-placeholder :contains "TODO"}]})
```

The contract is the core `:output` policy map. Supported field types are
`:string`, `:number`, `:boolean`, and `:list`. Structural checks run on the
terminal LLM response; detector and forbidden-pattern checks also guard agent
rounds and buffered streams. This does not validate the value returned by the
workflow body.
Supported field types are `:string`, `:number`, `:boolean`, and `:list`.
Structural checks run on the terminal LLM response. Detector and forbidden
pattern checks also guard agent rounds and buffered streams. They do not
validate the value returned directly by the workflow body.

### `policies/no-tools`
The fixed output profiles are:

```sema
{:policy policies/no-tools}
```

Denies all model-requested tools. It does not remove ordinary Sema capabilities;
use workflow `:permissions` for the outer sandbox ceiling.

### `policies/no-sensitive-data-to-models`
| Policy | Behavior |
|---|---|
| `policies/reviewable-output` | Require non-empty `answer`, `sources`, and `limitations`; allow optional numeric `confidence` |
| `policies/certainty-audit` | Journal a small, independently authored set of absolute-certainty and unnamed-consensus patterns without blocking |
| `policies/no-placeholder-output` | Block objective unfinished-template markers |

Blocks detected secrets and payment-card numbers before provider dispatch.
Detected email addresses, phone numbers, and IPv4 addresses are replaced with
typed redaction markers. Detectors are deterministic patterns and may have
false positives or false negatives.
`certainty-audit` is intentionally advisory. Quoted text and valid contractual
language can match its patterns. It is not a port of HeartFlow and does not
implement semantic truth, fallacy, manipulation, or factuality classification.

### `policies/public-content`
### Deny-only profiles

Blocks the supported secret, payment-card, email, phone, and IPv4 detectors on
input and output. The name describes the intended data boundary, not an
automatic proof that otherwise-unmatched content is public.
These policies use `:subjects {:default :allow ...}` so they can tighten a
separate allowlist without denying unrelated subject kinds:

### `policies/public-sector-rag`
| Policy | Denies through model-invoked/direct `deftool` dispatch |
|---|---|
| `policies/no-file-write-tools` | File writes and deletes |
| `policies/no-network-tools` | Network requests |
| `policies/no-command-tools` | Commands |
| `policies/no-external-action-tools` | External actions |

Requires non-empty workflow metadata keys `:owner`, `:data-classification`, and
`:source`; a terminal LLM JSON object with non-empty `answer` and `sources`; the
standard content controls; and at least one checkpoint event. It is a practical
baseline for auditable RAG, not a public-sector compliance certification.
The names include `tools` because semantic policy subjects govern declared
tool dispatch. Ordinary Sema filesystem, HTTP, shell, and MCP calls remain
governed by workflow `:permissions` and the outer sandbox.

### `policies/ai-act-docs-lite`
### Fixed baselines and domain profiles

Requires non-empty `:owner`, `:risk-tier`, and `:intended-purpose` metadata; a
terminal LLM decision record with `decision`, `rationale`, and `sources`; and
at least one checkpoint. It supports documentation workflows but does not by
itself establish EU AI Act compliance.
| Policy | Behavior |
|---|---|
| `policies/no-tools` | Deny every model-requested tool call |
| `policies/no-sensitive-data-to-models` | Block detected secrets/cards and redact supported personal-data patterns before provider dispatch |
| `policies/public-content` | Block every supported sensitive-content detector on LLM input and output |
| `(policies/safe-code-agent options)` | Combine model, semantic subject, and input controls for coding agents |
| `(policies/customer-support-safe options)` | Draft-only support profile that permits exact read-only external-action names and requires structured drafts |
| `policies/human-reviewed-run` | Require an applied approval before workflow success |
| `policies/change-controlled` | Require change metadata and an applied approval |
| `policies/public-sector-rag` | Require ownership/source metadata, structured cited output, content controls, and a checkpoint |
| `policies/ai-act-docs-lite` | Require basic ownership/risk/purpose metadata, structured decision records, and a checkpoint |
| `policies/ai-act-human-oversight` | Require fuller purpose/affected-person/oversight metadata, structured limitations, a checkpoint, and approval |
| `policies/employment-assist` | Disable model tools, require neutral evidence/limitations/review output and metadata, and require approval |

`customer-support-safe` is deliberately draft-only. Its `:read-actions` must
match the `:external-action` values declared by the permitted read tools. Any
additional subject declared by those tools must also be allowed by a different,
carefully designed profile; policy composition cannot loosen this profile.

`employment-assist` does not provide protected-attribute or health detectors.
It blocks model tools and enforces a review-shaped output and explicit approval;
it is not a candidate-ranking or employment-decision system.

The AI documentation profiles generate runtime evidence requirements. They do
not establish EU AI Act compliance.

## Evidence export

Export a completed workflow's generic evidence bundle with:

```bash
sema workflow export <run-id>
```

The command writes a JSON event ledger, Markdown summary, and SHA-256 manifest
under the run directory by default.
The command writes a JSON ledger, Markdown summary, and SHA-256 manifest under
the run directory by default. Approval request and decision summaries are read
through Sema's digest and Ed25519 signature validation. The authoritative
approval sidecars are included in the integrity manifest.

## Testing

Expand Down
Loading