Refactor code structure and optimize performance across multiple modules
This commit is contained in:
605
docs/modules/advisory-ai/guides/policy-studio-api.md
Normal file
605
docs/modules/advisory-ai/guides/policy-studio-api.md
Normal file
@@ -0,0 +1,605 @@
|
||||
# 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:
|
||||
|
||||
```
|
||||
<atoms> → <disposition>
|
||||
```
|
||||
|
||||
#### 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)
|
||||
Reference in New Issue
Block a user