Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling. - Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options. - Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation. - Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios. - Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling. - Included tests for UdpTransportOptions to verify default values and modification capabilities. - Enhanced service registration tests for Udp transport services in the dependency injection container.
This commit is contained in:
335
docs/contracts/policy-studio.md
Normal file
335
docs/contracts/policy-studio.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# Policy Studio API Contract
|
||||
|
||||
**Contract ID:** `CONTRACT-POLICY-STUDIO-007`
|
||||
**Version:** 1.0
|
||||
**Status:** Published
|
||||
**Last Updated:** 2025-12-05
|
||||
|
||||
## Overview
|
||||
|
||||
This contract defines the Policy Studio API used for creating, editing, and managing security policies. Policy Studio extends the Policy Engine REST API with DSL compilation and draft management capabilities.
|
||||
|
||||
## Implementation References
|
||||
|
||||
- **Policy Engine:** `src/Policy/StellaOps.Policy.Engine/`
|
||||
- **Policy API:** `src/Api/StellaOps.Api.OpenApi/policy/openapi.yaml`
|
||||
- **Documentation:** `docs/api/policy.md`
|
||||
|
||||
## Policy Lifecycle
|
||||
|
||||
```
|
||||
Draft → Submitted → Approved → Active → Archived
|
||||
```
|
||||
|
||||
| State | Description |
|
||||
|-------|-------------|
|
||||
| `draft` | Policy is being edited, not enforced |
|
||||
| `submitted` | Policy submitted for review |
|
||||
| `approved` | Policy approved, ready to activate |
|
||||
| `active` | Policy is currently enforced |
|
||||
| `archived` | Policy is no longer active |
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Draft Management
|
||||
|
||||
#### Create Draft
|
||||
|
||||
```
|
||||
POST /api/v1/policy/drafts
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer <token>
|
||||
|
||||
{
|
||||
"tenant_id": "default",
|
||||
"name": "security-policy-v2",
|
||||
"description": "Enhanced security policy with KEV checks",
|
||||
"source_format": "stelladsl",
|
||||
"source": "package policy\n\ndefault allow := false\n\nallow if {\n input.severity != \"critical\"\n}"
|
||||
}
|
||||
|
||||
Response: 201 Created
|
||||
{
|
||||
"draft_id": "draft-001",
|
||||
"name": "security-policy-v2",
|
||||
"state": "draft",
|
||||
"created_at": "2025-12-05T10:00:00Z",
|
||||
"created_by": "user@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Draft
|
||||
|
||||
```
|
||||
GET /api/v1/policy/drafts/{draft_id}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"draft_id": "draft-001",
|
||||
"name": "security-policy-v2",
|
||||
"description": "Enhanced security policy with KEV checks",
|
||||
"state": "draft",
|
||||
"source_format": "stelladsl",
|
||||
"source": "...",
|
||||
"compiled_rego": "...",
|
||||
"validation_errors": [],
|
||||
"created_at": "2025-12-05T10:00:00Z",
|
||||
"updated_at": "2025-12-05T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### Update Draft
|
||||
|
||||
```
|
||||
PUT /api/v1/policy/drafts/{draft_id}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"source": "updated policy source..."
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
```
|
||||
|
||||
#### Delete Draft
|
||||
|
||||
```
|
||||
DELETE /api/v1/policy/drafts/{draft_id}
|
||||
|
||||
Response: 204 No Content
|
||||
```
|
||||
|
||||
### DSL Compilation
|
||||
|
||||
#### Compile DSL to Rego
|
||||
|
||||
```
|
||||
POST /api/v1/policy/dsl/compile
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"source": "package policy\n\ndefault allow := false\n\nallow if { input.severity != \"critical\" }",
|
||||
"format": "stelladsl"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"rego": "package policy\n\ndefault allow := false\n\nallow = true {\n input.severity != \"critical\"\n}",
|
||||
"errors": [],
|
||||
"warnings": [
|
||||
{
|
||||
"line": 5,
|
||||
"column": 1,
|
||||
"message": "Consider adding documentation comment"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Validate Policy
|
||||
|
||||
```
|
||||
POST /api/v1/policy/dsl/validate
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"source": "...",
|
||||
"format": "stelladsl"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"valid": true,
|
||||
"errors": [],
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
### Submission & Approval
|
||||
|
||||
#### Submit Draft for Review
|
||||
|
||||
```
|
||||
POST /api/v1/policy/drafts/{draft_id}/submit
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"comment": "Ready for review"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"draft_id": "draft-001",
|
||||
"state": "submitted",
|
||||
"submitted_at": "2025-12-05T10:00:00Z",
|
||||
"submitted_by": "user@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Approve Policy
|
||||
|
||||
```
|
||||
POST /api/v1/policy/drafts/{draft_id}/approve
|
||||
Authorization: Bearer <token with policy:approve scope>
|
||||
|
||||
{
|
||||
"comment": "Approved after review"
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"draft_id": "draft-001",
|
||||
"state": "approved",
|
||||
"approved_at": "2025-12-05T10:00:00Z",
|
||||
"approved_by": "admin@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Activate Policy
|
||||
|
||||
```
|
||||
POST /api/v1/policy/drafts/{draft_id}/activate
|
||||
Authorization: Bearer <token with policy:activate scope>
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"policy_id": "policy-001",
|
||||
"version": "1.0.0",
|
||||
"state": "active",
|
||||
"activated_at": "2025-12-05T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Policy Versions
|
||||
|
||||
#### List Policy Versions
|
||||
|
||||
```
|
||||
GET /api/v1/policy/{policy_id}/versions
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"state": "active",
|
||||
"activated_at": "2025-12-05T10:00:00Z"
|
||||
},
|
||||
{
|
||||
"version": "0.9.0",
|
||||
"state": "archived",
|
||||
"archived_at": "2025-12-05T09:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Specific Version
|
||||
|
||||
```
|
||||
GET /api/v1/policy/{policy_id}/versions/{version}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"policy_id": "policy-001",
|
||||
"version": "1.0.0",
|
||||
"rego": "...",
|
||||
"hash": "sha256:...",
|
||||
"state": "active"
|
||||
}
|
||||
```
|
||||
|
||||
## Policy Evaluation
|
||||
|
||||
#### Evaluate Policy
|
||||
|
||||
```
|
||||
POST /api/v1/policy/{policy_id}/evaluate
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"input": {
|
||||
"finding_id": "finding-001",
|
||||
"severity": "high",
|
||||
"cvss": 7.5,
|
||||
"kev": true
|
||||
}
|
||||
}
|
||||
|
||||
Response: 200 OK
|
||||
{
|
||||
"result": {
|
||||
"allow": false,
|
||||
"deny": true,
|
||||
"reasons": ["KEV vulnerability detected"]
|
||||
},
|
||||
"policy_version": "1.0.0",
|
||||
"policy_hash": "sha256:...",
|
||||
"evaluated_at": "2025-12-05T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## DSL Format
|
||||
|
||||
### StellaOps DSL (stelladsl)
|
||||
|
||||
```rego
|
||||
package policy
|
||||
|
||||
import future.keywords.if
|
||||
import future.keywords.in
|
||||
|
||||
# Default deny
|
||||
default allow := false
|
||||
default deny := false
|
||||
|
||||
# Allow low severity findings
|
||||
allow if {
|
||||
input.severity in ["low", "informational"]
|
||||
}
|
||||
|
||||
# Deny KEV vulnerabilities
|
||||
deny if {
|
||||
input.kev == true
|
||||
}
|
||||
|
||||
# Deny critical CVSS
|
||||
deny if {
|
||||
input.cvss >= 9.0
|
||||
}
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
| Code | Message |
|
||||
|------|---------|
|
||||
| `ERR_POL_001` | Invalid policy syntax |
|
||||
| `ERR_POL_002` | Compilation failed |
|
||||
| `ERR_POL_003` | Validation failed |
|
||||
| `ERR_POL_004` | Policy not found |
|
||||
| `ERR_POL_005` | Invalid state transition |
|
||||
| `ERR_POL_006` | Insufficient permissions |
|
||||
|
||||
## Authority Scopes
|
||||
|
||||
| Scope | Description |
|
||||
|-------|-------------|
|
||||
| `policy:read` | Read policies and drafts |
|
||||
| `policy:write` | Create and edit drafts |
|
||||
| `policy:submit` | Submit drafts for review |
|
||||
| `policy:approve` | Approve submitted policies |
|
||||
| `policy:activate` | Activate approved policies |
|
||||
| `policy:archive` | Archive active policies |
|
||||
|
||||
## Unblocks
|
||||
|
||||
This contract unblocks the following tasks:
|
||||
|
||||
- CONCELIER-RISK-68-001
|
||||
- POLICY-RISK-68-001
|
||||
- POLICY-RISK-68-002
|
||||
|
||||
## Related Contracts
|
||||
|
||||
- [Risk Scoring Contract](./risk-scoring.md) - Policy affects scoring
|
||||
- [Authority Effective Write Contract](./authority-effective-write.md) - Policy attachment
|
||||
Reference in New Issue
Block a user