# Policy Studio API and Rule Syntax > **Sprint:** SPRINT_20251226_017_AI_policy_copilot > **Task:** POLICY-26 This guide documents the Policy Studio API for AI-powered policy authoring, converting natural language to lattice rules. ## Overview Policy Studio enables: 1. **Natural Language → Policy Intent**: Parse human intent from plain English 2. **Intent → Lattice Rules**: Generate K4 lattice-compatible rules 3. **Validation**: Detect conflicts, unreachable conditions, loops 4. **Test Synthesis**: Auto-generate test cases for policy validation 5. **Compilation**: Bundle rules into signed, versioned policy packages ## API Endpoints ### Parse Natural Language Convert natural language to structured policy intent. ```http POST /api/v1/policy/studio/parse Content-Type: application/json { "input": "Block all critical vulnerabilities in production services unless they have a vendor VEX stating not affected", "scope": "production" } ``` **Response:** ```json { "intent": { "intentId": "intent-20251226-001", "intentType": "OverrideRule", "originalInput": "Block all critical vulnerabilities in production services unless they have a vendor VEX stating not affected", "conditions": [ { "field": "severity", "operator": "equals", "value": "critical", "connector": "and" }, { "field": "scope", "operator": "equals", "value": "production", "connector": "and" }, { "field": "has_vex", "operator": "equals", "value": false, "connector": null } ], "actions": [ { "actionType": "set_verdict", "parameters": { "verdict": "block", "reason": "Critical vulnerability without VEX exception" } } ], "scope": "production", "scopeId": null, "priority": 100, "confidence": 0.92, "alternatives": null, "clarifyingQuestions": null }, "success": true, "modelId": "claude-sonnet-4-20250514", "parsedAt": "2025-12-26T10:30:00Z" } ``` ### Clarifying Questions When intent is ambiguous, the API returns clarifying questions: ```json { "intent": { "intentId": "intent-20251226-002", "intentType": "ThresholdRule", "confidence": 0.65, "clarifyingQuestions": [ "Should this rule apply to all environments or just production?", "What should happen when the threshold is exceeded: block or escalate?" ], "alternatives": [ { "...alternative interpretation 1..." }, { "...alternative interpretation 2..." } ] }, "success": true } ``` ### Generate Rules Convert policy intent to K4 lattice rules. ```http POST /api/v1/policy/studio/generate Content-Type: application/json { "intentId": "intent-20251226-001" } ``` **Response:** ```json { "rules": [ { "ruleId": "rule-20251226-001", "name": "block-critical-no-vex", "description": "Block critical vulnerabilities in production without VEX exception", "latticeExpression": "Present ∧ ¬Mitigated ∧ severity=critical ∧ scope=production → Block", "conditions": [ { "field": "severity", "operator": "equals", "value": "critical" }, { "field": "scope", "operator": "equals", "value": "production" }, { "field": "has_vex", "operator": "equals", "value": false } ], "disposition": "Block", "priority": 100, "scope": "production", "enabled": true } ], "success": true, "warnings": [], "intentId": "intent-20251226-001", "generatedAt": "2025-12-26T10:30:00Z" } ``` ### Validate Rules Check rules for conflicts and issues. ```http POST /api/v1/policy/studio/validate Content-Type: application/json { "rules": [ { "ruleId": "rule-20251226-001", "..." }, { "ruleId": "rule-20251226-002", "..." } ], "existingRuleIds": ["rule-existing-001", "rule-existing-002"] } ``` **Response:** ```json { "valid": false, "conflicts": [ { "ruleId1": "rule-20251226-001", "ruleId2": "rule-existing-002", "description": "Both rules match critical vulnerabilities but produce different dispositions (Block vs Allow)", "suggestedResolution": "Add priority ordering or more specific conditions to disambiguate", "severity": "error" } ], "unreachableConditions": [ "Rule rule-20251226-002 condition 'severity=low AND severity=high' is always false" ], "potentialLoops": [], "coverage": 0.85 } ``` ### Compile Policy Bundle Bundle validated rules into a signed policy package. ```http POST /api/v1/policy/studio/compile Content-Type: application/json { "rules": [ { "ruleId": "rule-20251226-001", "..." } ], "bundleName": "production-security-policy", "version": "1.0.0", "sign": true } ``` **Response:** ```json { "bundleId": "bundle-20251226-001", "bundleName": "production-security-policy", "version": "1.0.0", "ruleCount": 5, "digest": "sha256:bundledigest...", "signed": true, "signatureKeyId": "stellaops-policy-signer-2025", "compiledAt": "2025-12-26T10:30:00Z", "downloadUrl": "/api/v1/policy/bundle/bundle-20251226-001" } ``` ## Policy Intent Types | Type | Description | Example | |------|-------------|---------| | `OverrideRule` | Override default verdict | "Block all critical CVEs" | | `EscalationRule` | Escalate findings | "Escalate CVSS ≥9.0 to security team" | | `ExceptionCondition` | Bypass rules | "Except internal-only services" | | `MergePrecedence` | Priority ordering | "VEX takes precedence over CVSS" | | `ThresholdRule` | Automatic thresholds | "Allow max 10 high-severity per service" | | `ScopeRestriction` | Scope limits | "Only apply to production" | ## Rule Syntax ### Lattice Expression Format Rules use K4 lattice logic: ``` ``` #### Security Atoms | Atom | Meaning | |------|---------| | `Present` | Vulnerability is present in artifact | | `Applies` | Vulnerability applies to this context | | `Reachable` | Vulnerable code is reachable | | `Mitigated` | Mitigation exists (VEX, WAF, etc.) | | `Fixed` | Fix is available | | `Misattributed` | False positive | #### Operators | Operator | Symbol | Example | |----------|--------|---------| | AND | `∧` | `Present ∧ Reachable` | | OR | `∨` | `Fixed ∨ Mitigated` | | NOT | `¬` | `¬Mitigated` | | Implies | `→` | `Present → Block` | #### Dispositions | Disposition | Meaning | |-------------|---------| | `Block` | Fail the build/gate | | `Warn` | Warning only | | `Allow` | Pass with no action | | `Review` | Require human review | | `Escalate` | Escalate to security team | ### Examples ``` # Block critical unmitigated vulnerabilities Present ∧ Reachable ∧ ¬Mitigated ∧ severity=critical → Block # Allow if vendor says not affected Present ∧ Mitigated ∧ vex_status=not_affected → Allow # Escalate CVSS ≥9.0 Present ∧ cvss_score>=9.0 → Escalate # Warn on high severity with fix available Present ∧ severity=high ∧ Fixed → Warn ``` ## Condition Fields | Field | Type | Values | |-------|------|--------| | `severity` | string | `critical`, `high`, `medium`, `low`, `none` | | `cvss_score` | number | 0.0 - 10.0 | | `reachable` | boolean | `true`, `false` | | `has_vex` | boolean | `true`, `false` | | `vex_status` | string | `not_affected`, `affected`, `fixed`, `under_investigation` | | `has_fix` | boolean | `true`, `false` | | `fix_version` | string | Version string | | `scope` | string | `production`, `staging`, `development` | | `age_days` | number | Days since disclosure | | `exploit_available` | boolean | `true`, `false` | | `in_kev` | boolean | In CISA KEV catalog | ## Condition Operators | Operator | Description | Example | |----------|-------------|---------| | `equals` | Exact match | `severity equals critical` | | `not_equals` | Not equal | `scope not_equals development` | | `greater_than` | Greater than | `cvss_score greater_than 7.0` | | `less_than` | Less than | `age_days less_than 30` | | `greater_or_equal` | ≥ | `cvss_score greater_or_equal 9.0` | | `less_or_equal` | ≤ | `cvss_score less_or_equal 3.9` | | `contains` | String contains | `component contains lodash` | | `in` | In list | `severity in [critical, high]` | | `not_in` | Not in list | `scope not_in [development, test]` | ## Test Case Format ### Generated Test Cases Policy Studio auto-generates test cases: ```json { "testCases": [ { "testId": "test-001", "type": "positive", "description": "Critical unmitigated vulnerability should be blocked", "input": { "severity": "critical", "reachable": true, "has_vex": false, "scope": "production" }, "expectedDisposition": "Block", "matchedRuleId": "rule-20251226-001" }, { "testId": "test-002", "type": "negative", "description": "Critical vulnerability with VEX should not match block rule", "input": { "severity": "critical", "reachable": true, "has_vex": true, "vex_status": "not_affected", "scope": "production" }, "expectedDisposition": "Allow", "shouldNotMatch": "rule-20251226-001" }, { "testId": "test-003", "type": "boundary", "description": "CVSS exactly at threshold", "input": { "cvss_score": 9.0, "severity": "critical" }, "expectedDisposition": "Escalate" }, { "testId": "test-004", "type": "conflict", "description": "Input matching multiple conflicting rules", "input": { "severity": "high", "reachable": true, "has_fix": true }, "possibleDispositions": ["Warn", "Block"], "conflictingRules": ["rule-001", "rule-002"] } ] } ``` ### Test Types | Type | Purpose | Auto-Generated | |------|---------|---------------| | `positive` | Should match rule and produce expected disposition | Yes | | `negative` | Should NOT match rule (boundary conditions) | Yes | | `boundary` | Edge cases at thresholds | Yes | | `conflict` | Triggers multiple rules | Yes | | `manual` | User-defined custom cases | No | ## Natural Language Examples ### Override Rules ``` Input: "Block all critical vulnerabilities" → Present ∧ severity=critical → Block Input: "Allow vulnerabilities with VEX not_affected status" → Present ∧ vex_status=not_affected → Allow Input: "Block exploitable vulnerabilities older than 30 days" → Present ∧ exploit_available=true ∧ age_days>30 → Block ``` ### Escalation Rules ``` Input: "Escalate anything in the KEV catalog to security team" → Present ∧ in_kev=true → Escalate Input: "Escalate CVSS 9.0 or above" → Present ∧ cvss_score>=9.0 → Escalate ``` ### Exception Conditions ``` Input: "Except for development environments" → Adds: ∧ scope!=development to existing rules Input: "Unless there's a VEX from the vendor" → Adds: ∧ ¬(has_vex=true ∧ vex_status=not_affected) ``` ### Threshold Rules ``` Input: "Allow maximum 5 high-severity vulnerabilities per service" → Creates threshold counter with Block when exceeded ``` ## CLI Commands ```bash # Parse natural language stella policy parse "Block all critical CVEs in production" # Generate rules from intent stella policy generate intent-20251226-001 # Validate rules stella policy validate rules.yaml # Run test cases stella policy test rules.yaml --cases tests.yaml # Compile bundle stella policy compile rules.yaml \ --name production-policy \ --version 1.0.0 \ --sign # Apply policy stella policy apply bundle-20251226-001.tar.gz ``` ## Configuration ```yaml policyStudio: # Maximum conditions per rule maxConditionsPerRule: 10 # Auto-generate test cases autoGenerateTests: true # Test case types to generate testTypes: - positive - negative - boundary - conflict # Minimum test coverage minTestCoverage: 0.80 # Require human approval for production policies requireApproval: production: true staging: false development: false # Number of approvers required requiredApprovers: 2 # Sign compiled bundles signBundles: true ``` ## Policy Bundle Format Compiled policy bundles are tar.gz archives: ``` production-policy-1.0.0.tar.gz ├── manifest.json # Bundle metadata ├── rules/ │ ├── rule-001.yaml # Individual rule files │ ├── rule-002.yaml │ └── ... ├── tests/ │ ├── test-001.yaml # Test cases │ └── ... ├── signature.dsse.json # DSSE signature └── checksums.sha256 # File checksums ``` ### Manifest Schema ```json { "bundleId": "bundle-20251226-001", "bundleName": "production-security-policy", "version": "1.0.0", "createdAt": "2025-12-26T10:30:00Z", "createdBy": "policy-studio", "rules": [ { "ruleId": "rule-001", "name": "block-critical", "file": "rules/rule-001.yaml" } ], "testCount": 15, "coverage": 0.92, "signed": true, "signatureKeyId": "stellaops-policy-signer-2025" } ``` ## Attestation Format Policy drafts are attested using DSSE: ```json { "_type": "https://stellaops.org/attestation/policy-draft/v1", "bundleId": "bundle-20251226-001", "bundleName": "production-security-policy", "version": "1.0.0", "authority": "Validated", "rules": { "count": 5, "ruleIds": ["rule-001", "rule-002", "..."] }, "validation": { "valid": true, "conflictCount": 0, "testsPassed": 15, "coverage": 0.92 }, "model": { "modelId": "claude-sonnet-4-20250514", "parseConfidence": 0.95 }, "createdAt": "2025-12-26T10:30:00Z" } ``` ## Error Handling ### Parse Errors ```json { "success": false, "error": "ambiguous_intent", "message": "Could not determine whether 'block' means verdict or action", "suggestions": [ "Try: 'Set verdict to block for critical vulnerabilities'", "Try: 'Fail the build for critical vulnerabilities'" ] } ``` ### Validation Errors ```json { "valid": false, "conflicts": [ { "severity": "error", "description": "Rule A and Rule B have contradicting dispositions for the same conditions" } ] } ``` ### Compilation Errors ```json { "success": false, "error": "compilation_failed", "message": "Cannot compile bundle with unresolved conflicts", "unresolvedConflicts": 2 } ``` ## Related Documentation - [Trust Lattice Engine](../../policy/trust-lattice.md) - [K4 Lattice Reference](../../policy/k4-lattice.md) - [AI Attestations](./ai-attestations.md) - [Advisory AI Architecture](../architecture.md)