Files
git.stella-ops.org/docs/contracts/export-bundle.md
master cc69d332e3
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Add unit tests for RabbitMq and Udp transport servers and clients
- 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.
2025-12-05 19:01:12 +02:00

325 lines
6.0 KiB
Markdown

# Export Bundle Scheduler Contract
**Contract ID:** `CONTRACT-EXPORT-BUNDLE-009`
**Version:** 1.0
**Status:** Published
**Last Updated:** 2025-12-05
## Overview
This contract defines the export bundle job scheduling and manifest format used by the Export Center. It covers job definitions, scheduling, output formats, and attestation integration.
## Implementation References
- **Export Center:** `src/ExportCenter/`
- **API Spec:** `src/Api/StellaOps.Api.OpenApi/export-center/openapi.yaml`
## Data Models
### ExportBundleJob
Job definition for scheduled exports.
```json
{
"job_id": "job-001",
"tenant_id": "default",
"name": "daily-vex-export",
"description": "Daily VEX advisory export",
"query": {
"type": "vex",
"filters": {
"severity": ["critical", "high"],
"providers": ["github", "redhat"]
}
},
"format": "openvex",
"schedule": "0 0 * * *",
"destination": {
"type": "s3",
"config": {
"bucket": "exports",
"prefix": "vex/daily/"
}
},
"signing": {
"enabled": true,
"predicate_type": "stella.ops/vex@v1"
},
"enabled": true,
"created_at": "2025-12-05T10:00:00Z",
"last_run_at": "2025-12-05T00:00:00Z",
"next_run_at": "2025-12-06T00:00:00Z"
}
```
### Export Formats
| Format | Description | MIME Type |
|--------|-------------|-----------|
| `openvex` | OpenVEX JSON | application/json |
| `csaf` | CSAF VEX | application/json |
| `cyclonedx` | CycloneDX VEX | application/json |
| `spdx` | SPDX document | application/json |
| `ndjson` | Newline-delimited JSON | application/x-ndjson |
| `json` | Standard JSON array | application/json |
### Schedule Format
Cron expressions (5 fields):
```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
```
Examples:
| Schedule | Description |
|----------|-------------|
| `0 0 * * *` | Daily at midnight |
| `0 */6 * * *` | Every 6 hours |
| `0 0 * * 0` | Weekly on Sunday |
| `0 0 1 * *` | Monthly on the 1st |
### Destination Types
#### S3 Destination
```json
{
"type": "s3",
"config": {
"bucket": "my-exports",
"prefix": "vex/",
"region": "us-east-1",
"endpoint": "https://s3.amazonaws.com"
}
}
```
#### File Destination
```json
{
"type": "file",
"config": {
"path": "/exports/vex/"
}
}
```
#### Webhook Destination
```json
{
"type": "webhook",
"config": {
"url": "https://example.com/webhook",
"headers": {
"Authorization": "Bearer ${SECRET}"
}
}
}
```
### ExportBundleManifest
Manifest for completed export.
```json
{
"bundle_id": "bundle-001",
"job_id": "job-001",
"tenant_id": "default",
"created_at": "2025-12-05T00:00:00Z",
"format": "openvex",
"artifact_digest": "sha256:abc123...",
"artifact_size_bytes": 1048576,
"query_signature": "sha256:def456...",
"item_count": 150,
"policy_digest": "sha256:...",
"consensus_digest": "sha256:...",
"score_digest": "sha256:...",
"attestation": {
"predicate_type": "stella.ops/vex@v1",
"rekor_uuid": "24296fb24b8ad77a...",
"rekor_index": 12345,
"signed_at": "2025-12-05T00:00:01Z"
}
}
```
## API Endpoints
### Job Management
#### Create Export Job
```
POST /api/v1/export/jobs
Content-Type: application/json
Authorization: Bearer <token>
{
"name": "daily-vex-export",
"query": {...},
"format": "openvex",
"schedule": "0 0 * * *",
"destination": {...}
}
Response: 201 Created
{
"job_id": "job-001",
...
}
```
#### Update Job
```
PUT /api/v1/export/jobs/{job_id}
Content-Type: application/json
{
"schedule": "0 */12 * * *",
"enabled": true
}
Response: 200 OK
```
#### Delete Job
```
DELETE /api/v1/export/jobs/{job_id}
Response: 204 No Content
```
#### List Jobs
```
GET /api/v1/export/jobs?tenant_id=default
Response: 200 OK
{
"items": [...],
"total": 5
}
```
### Manual Execution
#### Trigger Job
```
POST /api/v1/export/jobs/{job_id}/run
Response: 202 Accepted
{
"execution_id": "exec-001",
"status": "running"
}
```
#### Get Execution Status
```
GET /api/v1/export/jobs/{job_id}/executions/{execution_id}
Response: 200 OK
{
"execution_id": "exec-001",
"status": "completed",
"bundle_id": "bundle-001",
"started_at": "2025-12-05T00:00:00Z",
"completed_at": "2025-12-05T00:00:05Z"
}
```
### Bundle Retrieval
#### Get Bundle Manifest
```
GET /api/v1/export/bundles/{bundle_id}
Response: 200 OK
{
"bundle_id": "bundle-001",
"artifact_digest": "sha256:...",
...
}
```
#### Download Bundle
```
GET /api/v1/export/bundles/{bundle_id}/download
Response: 200 OK
Content-Type: application/json
Content-Disposition: attachment; filename="vex-export-2025-12-05.json"
[bundle content]
```
## Signing Configuration
### Enable Signing
```json
{
"signing": {
"enabled": true,
"predicate_type": "stella.ops/vex@v1",
"key_id": "signing-key-001",
"include_rekor": true
}
}
```
### Predicate Types
| Type | Description |
|------|-------------|
| `stella.ops/vex@v1` | VEX export attestation |
| `stella.ops/sbom@v1` | SBOM export attestation |
| `stella.ops/policy@v1` | Policy result export |
## Job Status
| Status | Description |
|--------|-------------|
| `idle` | Job is waiting for next scheduled run |
| `running` | Job is currently executing |
| `completed` | Last run completed successfully |
| `failed` | Last run failed |
| `disabled` | Job is disabled |
## Error Codes
| Code | Message |
|------|---------|
| `ERR_EXP_001` | Invalid schedule expression |
| `ERR_EXP_002` | Invalid destination config |
| `ERR_EXP_003` | Export failed |
| `ERR_EXP_004` | Signing failed |
| `ERR_EXP_005` | Job not found |
## Unblocks
This contract unblocks the following tasks:
- EXPORT-CONSOLE-23-001
## Related Contracts
- [Mirror Bundle Contract](./mirror-bundle.md) - Bundle format for air-gap
- [Risk Scoring Contract](./risk-scoring.md) - Score digest in exports