# Highflame Policy - Python Package

[![PyPI version](https://badge.fury.io/py/highflame-policy.svg)](https://badge.fury.io/py/highflame-policy)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Cedar policy engine and typed constants for the Highflame security platform. Ensures entity/action consistency across all Highflame services.

## Features

- 🔒 **Cedar Policy Evaluation** - Wraps `cedarpy` with Highflame-specific types
- 📝 **Typed Constants** - Auto-generated entity types, actions, and context keys (prevents typos!)
- 🔄 **Cedar Parser** - Convert Cedar text to structured PolicyRule JSON for UI editing
- ✅ **Schema Validation** - Validate policies against embedded Cedar schemas
- 🎯 **Service-Specific Schemas** - Overwatch (Guardian) and Palisade schemas included
- 🌐 **Namespace Support** - Generic support for namespaced entities and actions

## Installation

```bash
pip install highflame-policy
```

## Quick Start

### Policy Evaluation (Palisade Example)

```python
from highflame_policy import (
    PolicyEngine,
    EntityType,
    ActionType,
    schemas,
)
from highflame_policy.schemas import PalisadeContextKey

# Create engine with Palisade schema
engine = PolicyEngine(schema=schemas.palisade_schema)
engine.load_policies_from_file("palisade_policy.cedar")

# Evaluate with typed constants (no typos!)
decision = engine.evaluate(
    principal_type=EntityType.SCANNER,
    principal_id="palisade",
    action=ActionType.SCAN_ARTIFACT,
    resource_type=EntityType.ARTIFACT,
    resource_id="/model.safetensors",
    context={
        PalisadeContextKey.ARTIFACT_FORMAT: "safetensors",
        PalisadeContextKey.SEVERITY: "HIGH",
        PalisadeContextKey.ENVIRONMENT: "production",
    },
)

if decision.is_denied():
    print(f"Blocked by policies: {decision.determining_policies}")
```

### Service-Specific Schemas

```python
from highflame_policy import PolicyEngine, schemas
from highflame_policy.schemas import OverwatchContextKey

# Use Overwatch (Guardian) schema for IDE security
engine = PolicyEngine(schema=schemas.overwatch_schema)
engine.load_policies(policy)

decision = engine.evaluate(
    principal_type="Overwatch::User",
    principal_id="mcp_client",
    action='Overwatch::Action::"call_tool"',
    resource_type="Overwatch::Tool",
    resource_id="shell",
    context={
        OverwatchContextKey.THREAT_COUNT: 3,
        OverwatchContextKey.TOOL_NAME: "shell",
    },
)
```

### Cedar Parser (Text → JSON)

```python
from highflame_policy import parse_cedar_to_rules

cedar_text = '''
    @id("allow-read")
    permit(
        principal is User,
        action == Action::"read_file",
        resource is FilePath
    )
    when { context.environment == "production" };
'''

result = parse_cedar_to_rules(cedar_text)

for rule in result.rules:
    print(f"Rule: {rule['id']}, Effect: {rule['effect']}")
    # Use in UI for editing
```

## Available Constants

### Entity Types (17 total)
- `EntityType.USER`, `EntityType.AGENT`, `EntityType.SCANNER`, `EntityType.SERVICE`
- `EntityType.ARTIFACT`, `EntityType.TOOL`, `EntityType.SERVER`, `EntityType.FILE_PATH`
- `EntityType.MODEL`, `EntityType.REPOSITORY`, `EntityType.PACKAGE`
- And more...

### Actions (38 total)
- `ActionType.SCAN_ARTIFACT`, `ActionType.CALL_TOOL`, `ActionType.LOAD_MODEL`
- `ActionType.PROCESS_PROMPT`, `ActionType.PROCESS_RESPONSE`
- `ActionType.READ_FILE`, `ActionType.WRITE_FILE`, `ActionType.DELETE_FILE`
- `ActionType.HTTP_REQUEST`, `ActionType.EXECUTE_CODE`
- And more...

### Context Keys (Service-Specific)

**Overwatch (Guardian) Context:**
```python
from highflame_policy.schemas import OverwatchContextKey

# 20+ context attributes for IDE security
OverwatchContextKey.THREAT_COUNT
OverwatchContextKey.TOOL_NAME
OverwatchContextKey.USER_EMAIL
OverwatchContextKey.SOURCE
# And more...
```

**Palisade Context:**
```python
from highflame_policy.schemas import PalisadeContextKey

# 15+ context attributes for ML security
PalisadeContextKey.ENVIRONMENT
PalisadeContextKey.SEVERITY
PalisadeContextKey.ARTIFACT_FORMAT
PalisadeContextKey.PICKLE_EXEC_PATH_DETECTED
# And more...
```

## Service-Specific Schemas

### Overwatch (Guardian) - IDE Security
```python
from highflame_policy import PolicyEngine, schemas
from highflame_policy.schemas import OverwatchContextKey

# Schema: schemas.overwatch_schema
# Context: schemas.overwatch_context (JSON metadata for UI)

# Namespaced entities and actions
engine = PolicyEngine(schema=schemas.overwatch_schema)
decision = engine.evaluate(
    principal_type="Overwatch::User",
    principal_id="claude-code-user",
    action='Overwatch::Action::"call_tool"',
    resource_type="Overwatch::Tool",
    resource_id="bash",
    context={
        OverwatchContextKey.THREAT_COUNT: 0,
        OverwatchContextKey.TOOL_NAME: "bash",
        OverwatchContextKey.SOURCE: "claude-code",
    },
)
```

### Palisade - ML Supply Chain Security
```python
from highflame_policy import PolicyEngine, schemas
from highflame_policy.schemas import PalisadeContextKey

# Schema: schemas.palisade_schema
# Context: schemas.palisade_context (JSON metadata for UI)

engine = PolicyEngine(schema=schemas.palisade_schema)
decision = engine.evaluate(
    principal_type="Palisade::Scanner",
    principal_id="palisade",
    action='Palisade::Action::"scan_artifact"',
    resource_type="Palisade::Artifact",
    resource_id="/model.safetensors",
    context={
        PalisadeContextKey.SEVERITY: "HIGH",
        PalisadeContextKey.ARTIFACT_FORMAT: "safetensors",
        PalisadeContextKey.ENVIRONMENT: "production",
    },
)
```

## Input Validation

Protect against DoS attacks with built-in validation:

```python
from highflame_policy import (
    PolicyEngine,
    EngineOptions,
    ValidationLimits,
    InputValidationError,
)

engine = PolicyEngine(
    options=EngineOptions(
        limits=ValidationLimits(
            max_context_keys=100,
            max_string_length=1_000_000,
            max_nesting_depth=10,
        )
    )
)

try:
    decision = engine.evaluate(...)
except InputValidationError as e:
    print(f"Validation failed: {e}")
```

## Why Typed Constants?

**Without typed constants (error-prone):**
```python
context = {
    "enviroment": "production",  # Typo! Policy won't match
    "severety": "HIGH",           # Typo! Policy won't match
}
```

**With typed constants (compile-time safety):**
```python
from highflame_policy.schemas import PalisadeContextKey

context = {
    PalisadeContextKey.ENVIRONMENT: "production",  # ✓ Autocomplete + type checking
    PalisadeContextKey.SEVERITY: "HIGH",           # ✓ Can't typo!
}
```

## Architecture

This package wraps the official Cedar Python engine ([cedarpy](https://pypi.org/project/cedarpy/)) with Highflame-specific types generated from the Cedar schema. All services use identical entity/action names, ensuring policy consistency.

```
┌─────────────────────────────────────────┐
│  schema/highflame.cedarschema           │  ← Source of truth
│  (Cedar schema)                         │
└─────────────────────────────────────────┘
                    │
         ┌──────────┴──────────┐
         │  Rust codegen tool  │
         └──────────┬──────────┘
                    │
    ┌───────────────┼───────────────┐
    ▼               ▼               ▼
 Python          Go          TypeScript
cedarpy      cedar-go     cedar-wasm
    │               │               │
    ▼               ▼               ▼
Palisade      Guardrails      Guardian
(scanner)      (proxy)          (IDE)
```

## Related Packages

- **Go**: `github.com/highflame-ai/highflame-policy/packages/go`
- **TypeScript**: `@highflame/policy` on npm
- **Rust**: `highflame-policy` on crates.io

## Documentation

Full documentation: [CLAUDE.md](https://github.com/highflame-ai/highflame-policy/blob/main/CLAUDE.md)

## License

Apache 2.0 - See [LICENSE](https://github.com/highflame-ai/highflame-policy/blob/main/LICENSE)
