Policy Engine — Deep Dive
The Arbitex Policy Engine is the enforcement core of the platform. Every AI request — whether routed through the cloud gateway or an on-premises Outpost — passes through the Policy Engine before the prompt reaches a model and again when the model response is returned. This document is the comprehensive technical reference for the Policy Engine. For a user-focused overview, see Policy Engine — User Guide. For admin configuration steps, see Policy Engine admin guide.
Source: backend/app/services/policy_engine.py
Rule model
Section titled “Rule model”The Policy Engine uses a Palo Alto firewall-style rule model: rules are organized into packs, packs are organized into chains, and evaluation proceeds sequentially through the chain until a terminal action is reached (in first_applicable mode) or all rules have been evaluated (in deny_overrides mode).
Chain └─ Pack 1 │ └─ Rule 1 (sequence: 10) │ └─ Rule 2 (sequence: 20) └─ Pack 2 └─ Rule 3 (sequence: 10) └─ Rule 4 (sequence: 20)An organization has exactly one org chain (the primary enforcement chain). Users may optionally have a user chain (personal overrides). The two chains interact in a defined evaluation order (see Chain evaluation order).
If no rule matches anywhere in the chain, the default action is ALLOW.
Combining algorithms
Section titled “Combining algorithms”The combining algorithm controls how the Policy Engine responds to conflicting rule outcomes within a chain.
first_applicable
Section titled “first_applicable”The engine evaluates rules in sequence order and stops at the first matching rule. The action of that rule is the final enforcement decision.
This is the default algorithm and the most commonly used. It mirrors how stateless firewalls process ACLs: rules are ordered by specificity or priority, and the most-specific matching rule wins.
Use when: You want predictable, ordered evaluation where rule order is explicit governance intent.
deny_overrides
Section titled “deny_overrides”The engine evaluates all rules regardless of matches. If any matching rule produces a block action, that action overrides any allow actions from other matching rules. Non-blocking actions accumulate (e.g., multiple log actions all fire).
Use when: You have multiple packs that might independently match and you want a conservative posture — any block anywhere kills the request.
{ "combining_algorithm": "deny_overrides"}Set the algorithm on the chain object via the admin API. Org chains default to first_applicable.
Condition types
Section titled “Condition types”The Policy Engine supports 10 condition types. All conditions are evaluated against the request context at the time of evaluation. Multiple conditions within a single rule are combined with AND logic — all must match for the rule to fire.
1. content_regex
Section titled “1. content_regex”Matches when the request text (prompt or response, depending on direction) satisfies a regular expression.
{ "conditions": { "content_regex": "\\b(?:sk-[a-zA-Z0-9]{48})\\b" }}The value is a RE2-compatible regular expression applied via re.search(). Backtrack-unsafe patterns are rejected at rule creation time.
2. entity_types
Section titled “2. entity_types”Matches when the DLP pipeline detects one or more entity types in the request or response. Any detected entity whose type appears in the list (with sufficient confidence) causes the condition to match.
{ "conditions": { "entity_types": ["pii_name", "org_name", "financial_amount"], "entity_confidence_min": 0.75 }}entity_confidence_min sets the minimum confidence threshold (0.0–1.0) for a detection to count. Defaults to 0.0 (all detections count). Entity type labels are the Arbitex canonical types produced by the DLP pipeline — spaCy NER produces pii_name, org_name, location, financial_amount, date. See DLP Pipeline Configuration for the full label taxonomy.
3. user_groups
Section titled “3. user_groups”Matches when the requesting user belongs to at least one of the listed groups. Groups are SCIM-synced or directory-provisioned group names or IDs.
{ "conditions": { "user_groups": ["compliance-officers", "legal-team"] }}The user must be a member of any (not all) of the listed groups. Changes to group membership take effect immediately on the next request.
4. providers
Section titled “4. providers”Matches when the request targets one of the listed AI provider identifiers.
{ "conditions": { "providers": ["openai", "anthropic"] }}5. models
Section titled “5. models”Matches when the request targets one of the listed model identifiers.
{ "conditions": { "models": ["gpt-4o", "gpt-4o-mini"] }}6. model_risk_tier
Section titled “6. model_risk_tier”Matches based on the model’s registered risk tier in the Model Registry. The condition accepts a list of tier values and checks whether the request model’s tier is a member of that list.
{ "conditions": { "model_risk_tier": ["critical", "high"] }}The tier for the (model, provider) pair is looked up from the model registry before evaluation. A model with no registry entry has its tier treated as "unclassified" — it will not match any explicit tier in the list.
7. user_risk_score_min
Section titled “7. user_risk_score_min”Matches when the requesting user’s risk score (from CredInt/GeoIP enrichment) is at or above the specified threshold.
{ "conditions": { "user_risk_score_min": 0.7 }}Risk scores range from 0.0 to 1.0. Higher values indicate greater risk.
8. intent_complexity
Section titled “8. intent_complexity”Matches when the request’s computed intent complexity matches the specified value. Complexity is computed by the intake pipeline before policy evaluation.
{ "conditions": { "intent_complexity": "complex" }}Valid values: "simple", "medium", "complex". If complexity has not been computed for the request, the condition does not match.
9. channel
Section titled “9. channel”Matches when the request channel is one of the listed values. Useful for applying different governance to browser-based interactive users versus programmatic API callers.
{ "conditions": { "channel": ["interactive"] }}Valid values: "interactive" (browser/SSE callers), "api" (programmatic API callers).
10. content_categories
Section titled “10. content_categories”Matches when the DLP scan classifies content into one or more of the specified semantic categories. This condition operates at a higher level of abstraction than entity_types — rather than detecting individual named entity spans, it classifies the overall semantic domain and data type of the content.
{ "conditions": { "content_categories": ["financial.credit-cards", "personal.national-ids"], "content_category_confidence_min": 0.8 }}content_category_confidence_min sets the minimum classifier confidence (0.0–1.0) required for a category match to count. Defaults to 0.5. Categories are expressed as {domain}.{subcategory} dot-notation strings.
Category taxonomy
Section titled “Category taxonomy”The Policy Engine recognizes 8 top-level domains with 27 subcategories:
| Domain | Subcategories |
|---|---|
financial |
credit-cards, bank-accounts, tax-ids, financial-statements |
healthcare |
medical-records, prescriptions, insurance-claims |
legal |
contracts, litigation, regulatory-filings |
personal |
addresses, phone-numbers, emails, national-ids |
corporate |
trade-secrets, m-and-a, board-materials, earnings |
technology |
source-code, api-keys, infrastructure-configs |
data-engineering |
database-schemas, etl-pipelines, data-lineage |
workplace-safety |
incident-reports, osha-filings, safety-audits |
You may specify either a full domain.subcategory path (e.g., "financial.credit-cards") or just a domain root (e.g., "financial") to match any subcategory within that domain.
Domain-level matching
Section titled “Domain-level matching”To block any content classified into the corporate domain regardless of subcategory:
{ "conditions": { "content_categories": ["corporate"], "content_category_confidence_min": 0.75 }}Combining with entity_types
Section titled “Combining with entity_types”content_categories and entity_types can be combined in the same rule using AND logic. This creates a highly specific condition: the content must both be classified in a given category and contain a specific detected entity type:
{ "conditions": { "content_categories": ["healthcare.medical-records"], "entity_types": ["pii_name"], "entity_confidence_min": 0.8, "content_category_confidence_min": 0.85 }, "action": { "type": "BLOCK" }}This rule fires only when the content is classified as a medical record and a patient name is detected — providing more precise blocking than either condition alone.
Action types
Section titled “Action types”When a rule matches, the engine applies the rule’s action. There are 7 action types. Action names are uppercase as they appear in the policy engine.
1. ALLOW
Section titled “1. ALLOW”Permit the request or response to proceed. No modification is made.
{ "type": "ALLOW" }In first_applicable mode, ALLOW is a terminal action — it stops evaluation and forwards the request. Use ALLOW rules to create explicit exemptions before more-restrictive rules in the chain.
2. BLOCK
Section titled “2. BLOCK”Reject the request or response. The user receives a policy violation message.
{ "type": "BLOCK", "message": "This request was blocked by your organization's AI use policy."}message is returned in the API error body. If omitted, the default block message is shown. The audit log records the matched rule, pack, and chain. BLOCK is a terminal action.
3. CANCEL
Section titled “3. CANCEL”Cancel the request silently without forwarding it to the model. Unlike BLOCK, CANCEL does not return an explicit policy violation message to the caller. Used when the desired behavior is to drop the request without disclosing the blocking reason.
{ "type": "CANCEL" }CANCEL is a terminal action. In deny_overrides mode, CANCEL is treated as a deny action alongside BLOCK.
4. REDACT
Section titled “4. REDACT”Redact matched sensitive content before forwarding to the model (on input) or before returning to the user (on output). Requires an entity_types or content_regex condition to identify what to redact.
{ "type": "REDACT", "redact_replacement": "[REDACTED]"}redact_replacement is the string substituted for each detected span. Defaults to [REDACTED].
REDACT is a non-terminal action — it accumulates redactions and evaluation continues. Multiple REDACT rules in a chain can each redact different entity types before a terminal action is reached. The original pre-redaction text is available in the audit log.
5. ROUTE_TO
Section titled “5. ROUTE_TO”Route the request to a different model or model tier instead of the originally requested model.
{ "type": "ROUTE_TO", "route_to_model": "gpt-4o-mini", "route_to_tier": "sonnet"}| Field | Description |
|---|---|
route_to_model |
Exact model identifier to route to (e.g., "gpt-4o-mini") |
route_to_tier |
Tier name to route to (e.g., "haiku", "sonnet", "opus") |
Either route_to_model or route_to_tier may be specified. Use route_to_tier to route to a tier without pinning an exact model. ROUTE_TO is a terminal action.
6. PROMPT
Section titled “6. PROMPT”Present a governance challenge to the user before allowing the request to proceed. The user must acknowledge or respond to the challenge. Only applies to interactive (channel: "interactive") callers.
{ "type": "PROMPT", "prompt_message": "This request may involve sensitive data. Please confirm you have authorization to share this information."}prompt_message is the challenge text shown to the user. PROMPT is a terminal action. Combine with a channel condition targeting ["interactive"] to avoid issuing challenges to API callers that cannot respond.
7. ALLOW_WITH_OVERRIDE
Section titled “7. ALLOW_WITH_OVERRIDE”Allow the request while displaying an informational override message to the user. Used for soft governance — the request proceeds but the user is notified of the policy consideration.
{ "type": "ALLOW_WITH_OVERRIDE", "override_message": "This request matched a sensitive data policy. It has been allowed under your elevated permissions, and this access has been logged."}override_message is shown to the user after the request completes. ALLOW_WITH_OVERRIDE is a terminal action.
Chain evaluation order
Section titled “Chain evaluation order”Each request is evaluated against chains in the following order:
1. User chain (if present and enabled for the org)2. Org chainUser chain
Section titled “User chain”A user chain is a personal policy chain attached to a specific user. User chains allow personal overrides — for example, a user may have a stricter personal policy than the org default, or an admin may grant elevated permissions to a specific user.
User chains are evaluated first. In first_applicable mode (the default), if a user chain rule matches and produces a terminal action, org chain evaluation is skipped entirely.
User chains are created via POST /api/v1/admin/policy-chains with chain_type: "user" and a user_id.
Org chain
Section titled “Org chain”The org chain is the primary enforcement chain applied to all requests in the organization. It is evaluated after the user chain (or on its own, if no user chain is configured or if the user chain did not match).
Every organization has exactly one org chain. It cannot be deleted, only modified.
Evaluation example
Section titled “Evaluation example”Request: user "alice", model "gpt-4o", prompt contains credit card number
1. Alice's user chain (first_applicable): - Rule 1: user_groups in [finance-power-users] → ALLOW ← alice is in this group → Terminal: ALLOW. Org chain skipped.
Request: user "bob", model "gpt-4o", prompt contains credit card number
1. Bob's user chain: (not configured)2. Org chain (first_applicable): - Rule 1: user_groups in [finance-power-users] → ALLOW ← bob is NOT in this group. No match. - Rule 2: entity_types contains [financial_amount] → BLOCK → Terminal: BLOCK.Evaluation flow
Section titled “Evaluation flow”Every request that enters the Policy Engine follows a deterministic evaluation path. The flow below describes the full lifecycle from request arrival to enforcement decision and audit persistence.
┌─────────────────────────────────────────────────────────────────┐│ Request arrives │└──────────────────────────────┬──────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Extract context ││ • user identity + group memberships (SCIM/directory) ││ • user risk score (CredInt/GeoIP enrichment) ││ • target model ID + provider ││ • model risk tier (model registry lookup) ││ • request channel (interactive vs. api) ││ • intent complexity (intake pipeline output) ││ • DLP scan results: entity_types + content_categories │└──────────────────────────────┬──────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ User chain present? ││ YES ──────────────────────────────────────┐ ││ │ ││ Evaluate user chain rules in sequence order │ ││ (combining algorithm: first_applicable by │ ││ default, or deny_overrides if configured) │ ││ ▼ ││ Terminal action matched? ││ YES ──────────────────────────────────────┐ ││ NO ── fall through to org chain │ ││ │ │└──────────────────────────────┬──────────────────────────┼──────┘ │ (no user chain, or │ │ no user chain match) │ ▼ │┌─────────────────────────────────────────────────────────────────┐│ Evaluate org chain rules in sequence order ││ (combining algorithm: first_applicable by default) ││ ││ Non-terminal actions (e.g., REDACT) accumulate ││ Terminal action ends evaluation │└──────────────────────────────┬──────────────────────────────────┘ │ ▼ ┌────────────┴────────────┐ │ │ No match Match found │ │ ▼ ▼ Default: ALLOW Apply action: ALLOW / BLOCK / CANCEL / REDACT / ROUTE_TO / PROMPT / ALLOW_WITH_OVERRIDE │ ▼ Audit log entry created (rule_id, pack_id, chain_id, action, matched conditions, pre-redaction text if REDACT)Context extraction detail
Section titled “Context extraction detail”The context extraction phase runs before any rule evaluation begins. All fields are resolved once and cached for the duration of the evaluation pass:
| Context field | Source |
|---|---|
| User identity | JWT sub claim, resolved against user store |
| Group memberships | SCIM group sync or IdP directory (cached TTL: 60s) |
| User risk score | CredInt enrichment result (0.0–1.0) |
| Model ID + provider | Request routing header |
| Model risk tier | Model registry lookup by (model_id, provider) |
| Request channel | X-Arbitex-Channel header or connection type |
| Intent complexity | Intake pipeline classification result |
| Entity types | DLP scan (spaCy NER) over prompt or response text |
| Content categories | DLP classifier over prompt or response text |
Non-terminal action accumulation
Section titled “Non-terminal action accumulation”In first_applicable mode, non-terminal actions from earlier rules accumulate as evaluation continues:
Rule 1 (sequence: 10): REDACT entity_types=[pii_name] → matched, REDACT applied, continueRule 2 (sequence: 20): REDACT entity_types=[financial_amount] → matched, REDACT applied, continueRule 3 (sequence: 30): entity_types=[financial_amount] → BLOCK → matched, BLOCK applied, stopThe final request carries both redactions from rules 1 and 2 even though rule 3 blocked it. The audit log records all three rule matches with their respective actions.
Policy simulation (dry-run)
Section titled “Policy simulation (dry-run)”Before deploying policy changes to production, you can test them against a simulated request.
POST /api/v1/admin/policy/simulateRequest body:
{ "prompt": "Please send me the credit card number on file for customer 12345.", "model_id": "gpt-4o", "user_id": "user_abc", "direction": "input", "chain_id": "org"}Response 200 OK:
{ "outcome": "BLOCK", "matched_rule": { "id": "rule_xyz", "name": "Block credit card in prompts", "pack": "PCI-DSS v4.0 Compliance Bundle", "condition_type": "entity_types", "action": "BLOCK" }, "evaluation_trace": [ { "rule_id": "rule_aaa", "name": "Finance power user exemption", "matched": false, "reason": "User not in group finance-power-users" }, { "rule_id": "rule_xyz", "name": "Block credit card in prompts", "matched": true, "reason": "DLP detected entity_type=financial_amount" } ], "dry_run": true}The evaluation_trace lists every rule evaluated in sequence order, whether it matched, and why. This is the primary debugging tool for unexpected policy behavior.
Using dry_run to test before deploying:
- Create or modify rules on a staging chain.
- Run simulate with representative test cases.
- Verify the
outcomeandevaluation_tracematch your intent. - Promote the chain configuration to the active org chain.
Admin UI walkthrough
Section titled “Admin UI walkthrough”The Cloud Portal provides a full administrative interface for policy management. All operations available via the API are also available through the admin UI. This section walks through the major screens.
Policy Dashboard
Section titled “Policy Dashboard”The Policy Dashboard is the entry point for policy administration. Navigate to Admin → Policy Engine in the Cloud Portal.
The dashboard displays:
- Active chain summary — the org chain name, combining algorithm, pack count, and total rule count
- Pack list — all packs attached to the org chain in sequence order, with rule counts and enabled/disabled status per pack
- Recent evaluations chart — a 24-hour time-series chart showing evaluation outcomes (ALLOW / BLOCK / REDACT / ROUTE_TO) segmented by hour
- Top blocked rules — the 5 rules that have triggered the most BLOCK/CANCEL actions in the past 7 days, with match counts
The dashboard refreshes automatically every 60 seconds. Click any pack name to navigate to the pack’s rule list.
Creating a policy chain
Section titled “Creating a policy chain”-
Navigate to Admin → Policy Engine → Chains.
-
Click New Chain.
-
Enter the chain name (e.g.,
"Acme Corp Org Chain") and an optional description. -
Select the combining algorithm: First Applicable or Deny Overrides. For most organizations, First Applicable is the correct choice.
-
Select the chain type:
- Org chain — applies to all users in the organization
- User chain — applies to a specific user (select the user from the dropdown)
-
Click Create Chain. The new chain is created in a disabled state.
-
Add packs to the chain (see next section), then click Activate to make it the active chain for the org or user.
Adding rules to a pack
Section titled “Adding rules to a pack”-
Navigate to Admin → Policy Engine → Packs and select the target pack, or click New Pack to create one.
-
Click Add Rule to open the rule editor.
-
In the Conditions panel, use the condition builder to add one or more conditions:
- Click + Add Condition and select the condition type from the dropdown (e.g.,
content_categories). - Configure the condition parameters in the form fields that appear. For
content_categories, select domains and subcategories from the multi-select picker. Forentity_types, select entity labels from the searchable checklist. - Set the confidence threshold slider if applicable.
- Add additional conditions with + Add Condition — all conditions are AND-combined.
- Click + Add Condition and select the condition type from the dropdown (e.g.,
-
In the Action panel, select the action type from the dropdown:
ALLOW,BLOCK,CANCEL,REDACT,ROUTE_TO,PROMPT, orALLOW_WITH_OVERRIDE- Fill in any action-specific fields (e.g., block message text, redact replacement string, route target model).
-
Set the Direction: Input, Output, or Both.
-
Set the Sequence number within the pack (integer; rules evaluate in ascending order).
-
Optionally add a human-readable Rule name and Description.
-
Click Save Rule. The rule is added to the pack immediately. If the pack is attached to an active chain, the rule takes effect on the next request.
Policy Simulator
Section titled “Policy Simulator”The Policy Simulator is the built-in UI equivalent of the POST /api/v1/admin/policy/simulate API endpoint. It provides a visual evaluation trace without writing any audit log entries.
-
Navigate to Admin → Policy Engine → Simulator.
-
In the User context panel:
- Select a User from the dropdown, or enter a user ID manually. The simulator resolves the user’s group memberships and risk score automatically.
- Optionally override Group memberships to test hypothetical group assignments without changing directory data.
-
In the Request panel:
- Enter a Test prompt in the text area. This is the text that will be run through the DLP pipeline and evaluated against policy rules.
- Select the Target model from the dropdown.
- Select the Direction: Input or Output.
- Select the Channel: Interactive or API.
-
Click Run Simulation.
-
Review the results in the Evaluation trace panel:
- The Outcome badge shows the final action (ALLOW / BLOCK / REDACT / etc.) in color-coded format.
- The Trace table lists every rule evaluated in sequence order, with columns for Rule name, Pack, Matched (yes/no), and Reason.
- Click any row in the trace table to expand the full condition evaluation detail, showing which specific conditions matched and which did not.
- If DLP was invoked, the DLP results section shows all detected entity types and content categories with their confidence scores.
-
Iterate on test prompts and user contexts to cover your intended rule coverage before deploying changes.
Effective policy view
Section titled “Effective policy view”The Effective Policy view shows the merged policy that would be applied to a specific user, combining their user chain (if any) with the org chain into a single ordered rule list.
-
Navigate to Admin → Policy Engine → Effective Policy.
-
Select a User from the search dropdown.
-
Click View Effective Policy.
-
The read-only view displays:
- User chain rules (if a user chain exists) — shown at the top in sequence order with a “User Chain” badge
- Org chain rules — shown below in sequence order with an “Org Chain” badge
- Each rule shows its sequence, name, conditions summary, action, and direction
-
Use the Export button to download the effective policy as JSON for offline review or audit documentation.
The Effective Policy view is read-only. To modify rules, navigate to the individual pack or chain editors.
Policy versioning
Section titled “Policy versioning”Policy bundles are versioned to enable auditable rollback and safe incremental deployment. Versioning applies at the bundle (chain snapshot) level.
Version format
Section titled “Version format”Policy bundle versions follow the format v{date}-{seq}:
| Component | Description |
|---|---|
v |
Literal prefix |
{date} |
ISO 8601 date of bundle creation (YYYYMMDD) |
{seq} |
Monotonically increasing sequence number (zero-padded to 3 digits) |
Example: v20260314-007 — the 7th bundle created on 2026-03-14.
Bundle contents
Section titled “Bundle contents”A policy bundle is a self-contained snapshot of a chain and all its packs and rules at a point in time. It includes:
- Chain metadata (name, combining algorithm, chain type)
- All packs in sequence order
- All rules within each pack, with full condition and action payloads
- Bundle version identifier
- Creation timestamp and creating principal
- HMAC-SHA256 signature computed over the bundle JSON payload using the org’s policy signing key
The HMAC signature allows the Outpost to verify that a received bundle has not been tampered with in transit or at rest. The Outpost rejects any bundle whose signature fails verification and continues enforcing the previously cached valid bundle.
Outpost caching and sync
Section titled “Outpost caching and sync”The Outpost maintains a local policy bundle cache to enable enforcement even during network interruptions:
| Behavior | Detail |
|---|---|
| Initial sync | Outpost downloads the current active bundle on startup |
| Sync interval | Configurable; default 60 seconds. The Outpost polls GET /api/outpost/policy-bundle |
| Cache persistence | Bundle is persisted to local disk (policy_bundle_cache.json) and loaded on restart |
| Integrity check | HMAC verified on every load (startup, sync, and disk read) |
| Stale bundle behavior | If sync fails, the Outpost continues enforcing the last valid cached bundle |
| Maximum stale age | Configurable; default 24 hours. After this threshold, the Outpost enters degraded mode and logs a warning |
Creating a new bundle version
Section titled “Creating a new bundle version”Bundle versions are created automatically when:
- A chain is activated (promoted to active) in the Cloud Portal
- Any rule, pack, or chain attribute is modified on an active chain via the API or admin UI
- A pack is added to or removed from an active chain
To manually snapshot the current chain state without activating it:
POST /api/v1/admin/policy-chains/{chain_id}/bundles{ "note": "Pre-release snapshot before Q1 compliance review"}Response 201 Created:
{ "bundle_id": "bundle_abc123", "version": "v20260314-007", "chain_id": "chain_xyz", "created_at": "2026-03-14T10:22:00Z", "hmac_signature": "sha256:4f3a9b...", "rule_count": 42, "pack_count": 5}Rollback
Section titled “Rollback”To revert to a previous bundle version:
POST /api/v1/admin/policy-chains/{chain_id}/activate{ "bundle_id": "bundle_prev_abc"}This activates the specified bundle as the current active policy for the chain. Outposts will pick up the rollback on their next sync interval.
Policy templates and pack management
Section titled “Policy templates and pack management”System bundles
Section titled “System bundles”Arbitex ships pre-configured policy packs (bundles) for common compliance standards. Bundles are read-only and updated by Arbitex when standards change.
| Bundle | Standard | Default rule count |
|---|---|---|
pci-dss-v4 |
PCI-DSS v4.0 | 14 |
hipaa |
HIPAA Privacy + Security Rules | 11 |
gdpr |
GDPR Article 5 data minimization | 9 |
glba |
Gramm–Leach–Bliley Act | 7 |
sox |
Sarbanes-Oxley Act | 6 |
ccpa |
California Consumer Privacy Act | 8 |
sec_reg_fd |
SEC Regulation FD (material non-public information) | 6 |
occ-sr-11-7 |
OCC SR 11-7 model risk management | 8 |
To add a bundle to your org chain:
POST /api/v1/admin/policy-chains/{chain_id}/packs{ "pack_id": "pci-dss-v4", "sequence": 100}Custom packs
Section titled “Custom packs”Create a custom pack to group org-specific rules:
POST /api/v1/admin/policy-packs{ "name": "Internal Data Classification Policy", "description": "Enforces Acme Corp data classification rules for AI interactions", "pack_type": "custom"}Add rules to the pack via POST /api/v1/admin/policy-packs/{pack_id}/rules.
Pack ordering
Section titled “Pack ordering”Packs within a chain are evaluated in ascending sequence order. Convention:
| Sequence range | Purpose |
|---|---|
| 1–99 | High-priority user exemptions or overrides |
| 100–299 | Compliance bundles (PCI-DSS, HIPAA, etc.) |
| 300–499 | Custom org rules |
| 500–699 | Model governance rules (model_risk_tier, model_id) |
| 700–899 | Content policy rules |
| 900–999 | Default catch-all rules |
This ordering ensures compliance bundles fire before custom rules, which fire before model governance rules. Adjust to suit your org’s risk posture.
Rule direction
Section titled “Rule direction”All conditions and actions support a direction field that specifies when the rule is evaluated:
| Direction | Evaluated when |
|---|---|
input |
Before the prompt is sent to the model |
output |
Before the model response is returned to the user |
both |
On both prompt and response |
Most blocking rules target input to prevent sensitive content from reaching the model. Redaction and DLP detection rules often target both.
Reference: condition and action summary
Section titled “Reference: condition and action summary”Conditions
Section titled “Conditions”| Condition | Type | AND-combinable | Requires DLP |
|---|---|---|---|
content_regex |
string (RE2 pattern) | Yes | No |
entity_types |
string[] | Yes | Yes |
user_groups |
string[] | Yes | No |
providers |
string[] | Yes | No |
models |
string[] | Yes | No |
model_risk_tier |
string[] | Yes | No |
user_risk_score_min |
float (0.0–1.0) | Yes | No |
intent_complexity |
enum | Yes | No |
channel |
string[] | Yes | No |
content_categories |
string[] (domain.subcategory) | Yes | Yes |
Actions
Section titled “Actions”| Action | Terminal | Interactive only | Notes |
|---|---|---|---|
ALLOW |
Yes | No | Explicit permit; stops evaluation |
BLOCK |
Yes | No | Rejects request with message |
CANCEL |
Yes | No | Silent drop; no policy message |
REDACT |
No | No | Accumulates; evaluation continues |
ROUTE_TO |
Yes | No | Redirects to different model/tier |
PROMPT |
Yes | Yes | Challenge dialog; combine with channel condition |
ALLOW_WITH_OVERRIDE |
Yes | No | Permits with informational notice |
Conflict resolution by sequencing
Section titled “Conflict resolution by sequencing”The Policy Engine never silently resolves conflicts between rules. If two rules could apply to the same request, the rule that appears earlier in the sequence wins (under first_applicable) — full stop. Your organization owns the sequence, and therefore owns the outcome.
Example: You have a Compliance Bundle at sequence=100 and a Custom Pack at sequence=200. Both contain rules that would match a specific request. The bundle rule at sequence=100 fires first; the custom pack rule at sequence=200 is never evaluated for that request.
If you want your Custom Pack rule to take precedence over the bundle rule for specific cases, move the Custom Pack to a lower sequence number. This is deliberate — compliance teams understand priority ordering, and making it explicit and auditable is preferable to a conflict-resolution algorithm that would itself introduce surprises.
The audit log records exactly which pack and rule matched, at which sequence position, and why. There is no ambiguity in the audit trace.
PROMPT governance flow — end-to-end
Section titled “PROMPT governance flow — end-to-end”When a PROMPT rule fires on a live interactive request:
- Arbitex returns
HTTP 449 Retry Withto the frontend, which triggers theGovernancePromptDialog. - The user enters a justification and clicks Submit.
- The original request re-submits with an
X-Governance-Justificationheader containing the justification text and aX-Governance-Challenge-Idlinking the re-submission to the original audit entry. - The re-submitted request passes through the full policy chain again. The PROMPT rule is bypassed on re-submission — if all other rules pass, the request proceeds.
- If the user clicks Cancel in the dialog, the request is silently dropped with no error shown.
For API callers (channel: "api"), PROMPT rules should be excluded using the channel condition. If a PROMPT rule fires on an API caller, the caller receives HTTP 449 with a machine-readable body explaining the governance requirement.
Custom DLP patterns
Section titled “Custom DLP patterns”The Pattern Browser under Admin → Policy → Patterns shows all active DLP detection patterns and allows you to create org-specific regex-based patterns.
Browse patterns
Section titled “Browse patterns”Patterns are organized by category:
- secret — API keys, tokens, credentials
- pii — names, emails, phone numbers, government IDs
- financial — card numbers, bank accounts, routing numbers
- medical — diagnoses, drug names, patient identifiers
- infrastructure — IP addresses, hostnames, internal URLs
Use the category filter chips and search box to locate patterns. Each PatternCard shows the pattern name, entity type, confidence threshold, and action tier badge.
Action tiers
Section titled “Action tiers”| Tier | Behavior |
|---|---|
| log_only | Log the detection event; allow the request to proceed unmodified |
| redact | Replace the matched content with a redaction marker |
| block | Block the request |
| prompt | Surface a challenge to the user before proceeding |
Create a custom pattern
Section titled “Create a custom pattern”-
Navigate to Admin → Policy → Patterns.
-
Click New Pattern.
-
Fill in the fields:
Field Description Detector name Human-readable identifier for this pattern Entity type The semantic category this pattern detects (e.g., internal_project_code)Action tier What happens when the pattern matches (log_only / redact / block / prompt) Confidence threshold Minimum match confidence (0–1, step 0.05) required to trigger the action Regex pattern A valid Python-compatible regular expression -
Click Save Pattern.
# Create a custom regex DLP patternPOST /api/v1/admin/dlp-rules/{ "detector_name": "Project codename detector", "detector_type": "regex", "entity_type": "internal_project_code", "action_tier": "redact", "enabled": true, "confidence_threshold": 0.9, "config_json": { "pattern": "\\bPROJ-[A-Z]{2,6}-\\d{3,6}\\b" }}Policy chain group filter
Section titled “Policy chain group filter”In the PolicyChainEditor (Admin → Policy Engine → Policy Chain), use the Group filter dropdown to preview how the chain applies to a specific group. When a group is selected:
- Packs containing rules that match the group are highlighted with a Has rules for this group badge.
- Non-matching packs are dimmed.
- A posture summary shows the count of ALLOW, DENY (BLOCK/CANCEL), and REDACT rules from matching packs.
The selected group is saved to sessionStorage and used to pre-fill the group field in the Policy Simulator.
Policy chain API reference
Section titled “Policy chain API reference”Save/reorder the org chain
Section titled “Save/reorder the org chain”PUT /api/v1/admin/policy-chains/org{ "packs": [ { "id": "<pack-uuid>", "sequence": 1 }, { "id": "<pack-uuid>", "sequence": 2 } ], "combining_algorithm": "first_applicable"}Test a regex condition
Section titled “Test a regex condition”POST /api/v1/admin/dlp-rules/test{ "pattern": "\\b\\d{9}\\b", "sample": "My SSN is 123456789" }Related pages
Section titled “Related pages”- Policy Engine — User Guide — user-facing overview
- Policy Engine admin guide — admin configuration walkthrough
- Model Risk Management — model registry and
model_risk_tiercondition - DLP Pipeline Configuration — DLP label taxonomy
- Human-in-the-Loop Governance — PROMPT governance workflow
- API Reference Batch 10 — policy engine API endpoints
- Outpost Policy Simulator — simulating policies on the Outpost
- Content Categories Guide — full content category taxonomy and classifier configuration