@interven/policy-cli
v0.2.0
Published
Policy-as-Code CLI for Interven. Validate, diff, and apply YAML policy files against a tenant. Designed for Git-managed policy workflows + CI/CD.
Maintainers
Readme
@interven/policy-cli
Policy-as-Code CLI for Interven. Validate, diff, and apply YAML/JSON policy files against your tenant. Designed for Git-managed policy workflows + CI/CD.
Install
npm install -g @interven/policy-cliOr run on demand:
npx @interven/policy-cli validate policies/Usage
interven-policy validate policies/*.yaml # syntax + schema check
interven-policy diff policies/*.yaml # show drift vs server
interven-policy apply policies/*.yaml # idempotent upsert
interven-policy fmt policies/*.yaml # canonical formattingPolicy YAML shape
The CLI accepts two interchangeable shapes — pick whichever you prefer.
validate, diff, and apply all work identically with either; the simple
shape is converted to the canonical shape internally at load time.
Shape 1 — Simple (recommended)
One file can hold many policies under a top-level policies: list. This is the
shape used by all the starter packs:
policies:
- name: secrets-egress-block
description: Block any outbound Slack/email/webhook carrying SECRETS.
rules:
- rule_id: slack-secrets-deny
action: DENY # ALLOW | DENY | SANITIZE | REQUIRE_APPROVAL
priority: 100
match:
tool_name: slack
operations: ["post_message", "upload_file"]
condition:
has_data_class: ["SECRETS"]Shape 2 — Canonical / K8s-style (engine-native)
apiVersion: interven.security/v1
kind: Policy
metadata:
name: secrets-egress-block
description: Block any outbound Slack/email/webhook carrying SECRETS.
env: production # optional; defaults to CLI's --env
spec:
rules:
- rule_id: slack-secrets-deny
description: Slack post containing SECRETS → DENY
action: DENY # ALLOW | DENY | SANITIZE | REQUIRE_APPROVAL
priority: 100
match:
tool_name: slack
operations: ["post_message", "upload_file"]
condition:
has_data_class: ["SECRETS"]Field reference:
| Section | Field | Notes |
|---------|-------|-------|
| match | tool_name | Exact match against tool (slack, github, ...) |
| match | operations | Patterns: exact name, *, method:GET, category:foo |
| match | verbs | READ / WRITE / ADMIN |
| match | org_patterns / repo_patterns / channel_patterns | Wildcard supported |
| condition | has_data_class | Array of SECRETS / PII / INTERNAL |
| condition | is_external_principal | Boolean |
| condition | volume_burst | Boolean (agent >20 ops/hr) |
| condition | body_contains_any / body_contains_all | Substring patterns in body |
Legacy flat shape also accepted:
# Older docs used this — gateway transparently normalizes:
- decision: DENY
data_classes: ["SECRETS"]
tool_name: slackThe CLI's validate accepts both. apply sends them as-is; the gateway translates flat → nested before storing.
See templates/policies/ for production-grade examples (HIPAA, SOC2, PCI-DSS, GDPR).
CI/CD
# .github/workflows/policies.yml
on: [push, pull_request]
jobs:
policy-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx @interven/policy-cli validate policies/
- if: github.event_name == 'pull_request'
run: npx @interven/policy-cli diff policies/ --env staging
env:
INTERVEN_API_KEY: ${{ secrets.INTERVEN_API_KEY_STAGING }}
- if: github.ref == 'refs/heads/main'
run: npx @interven/policy-cli apply policies/ --env production
env:
INTERVEN_API_KEY: ${{ secrets.INTERVEN_API_KEY_PROD }}Env vars
| Var | Default | Purpose |
|-----|---------|---------|
| INTERVEN_API_KEY | required for diff/apply | Bearer token (parent iv_live_*) |
| INTERVEN_GATEWAY | https://api.intervensecurity.com | Override for self-hosted |
License
MIT
