add release orchestrator docs and sprints gaps fills
This commit is contained in:
239
docs/modules/release-orchestrator/security/audit-trail.md
Normal file
239
docs/modules/release-orchestrator/security/audit-trail.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Audit Trail
|
||||
|
||||
> Audit event structure and audited operations for compliance and forensics.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 8.5](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Evidence Module](../modules/evidence.md), [Security Overview](overview.md)
|
||||
**Sprints:** [109_001 Evidence Collector](../../../../implplan/SPRINT_20260110_109_001_RELEVI_evidence_collector.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Release Orchestrator maintains a tamper-evident audit trail of all security-relevant operations. Audit events are cryptographically chained to detect tampering.
|
||||
|
||||
---
|
||||
|
||||
## Audit Event Structure
|
||||
|
||||
### TypeScript Interface
|
||||
|
||||
```typescript
|
||||
interface AuditEvent {
|
||||
id: UUID;
|
||||
timestamp: DateTime;
|
||||
tenantId: UUID;
|
||||
|
||||
// Actor
|
||||
actorType: "user" | "agent" | "system" | "plugin";
|
||||
actorId: UUID;
|
||||
actorName: string;
|
||||
actorIp?: string;
|
||||
|
||||
// Action
|
||||
action: string; // "promotion.approved", "deployment.started"
|
||||
resource: string; // "promotion"
|
||||
resourceId: UUID;
|
||||
|
||||
// Context
|
||||
environmentId?: UUID;
|
||||
releaseId?: UUID;
|
||||
promotionId?: UUID;
|
||||
|
||||
// Details
|
||||
before?: object; // State before (for updates)
|
||||
after?: object; // State after
|
||||
metadata?: object; // Additional context
|
||||
|
||||
// Integrity
|
||||
previousEventHash: string; // Hash chain for tamper detection
|
||||
eventHash: string;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audited Operations
|
||||
|
||||
| Category | Operations |
|
||||
|----------|------------|
|
||||
| **Authentication** | Login, logout, token refresh, failed attempts |
|
||||
| **Authorization** | Permission denied events |
|
||||
| **Environments** | Create, update, delete, freeze window changes |
|
||||
| **Releases** | Create, deprecate, archive |
|
||||
| **Promotions** | Request, approve, reject, cancel |
|
||||
| **Deployments** | Start, complete, fail, rollback |
|
||||
| **Targets** | Register, update, delete, health changes |
|
||||
| **Agents** | Register, heartbeat gaps, capability changes |
|
||||
| **Integrations** | Create, update, delete, test |
|
||||
| **Plugins** | Enable, disable, config changes |
|
||||
| **Evidence** | Create (never update/delete) |
|
||||
|
||||
---
|
||||
|
||||
## Hash Chain
|
||||
|
||||
### Chain Verification
|
||||
|
||||
The audit trail uses SHA-256 hash chaining for tamper detection:
|
||||
|
||||
```typescript
|
||||
interface HashChainEntry {
|
||||
eventId: UUID;
|
||||
eventHash: string;
|
||||
previousEventHash: string;
|
||||
}
|
||||
|
||||
function computeEventHash(event: AuditEvent): string {
|
||||
const payload = JSON.stringify({
|
||||
id: event.id,
|
||||
timestamp: event.timestamp,
|
||||
tenantId: event.tenantId,
|
||||
actorType: event.actorType,
|
||||
actorId: event.actorId,
|
||||
action: event.action,
|
||||
resource: event.resource,
|
||||
resourceId: event.resourceId,
|
||||
previousEventHash: event.previousEventHash,
|
||||
});
|
||||
|
||||
return sha256(payload);
|
||||
}
|
||||
|
||||
function verifyChain(events: AuditEvent[]): VerificationResult {
|
||||
for (let i = 1; i < events.length; i++) {
|
||||
const current = events[i];
|
||||
const previous = events[i - 1];
|
||||
|
||||
if (current.previousEventHash !== previous.eventHash) {
|
||||
return {
|
||||
valid: false,
|
||||
brokenAt: i,
|
||||
reason: "Hash chain broken"
|
||||
};
|
||||
}
|
||||
|
||||
const computed = computeEventHash(current);
|
||||
if (computed !== current.eventHash) {
|
||||
return {
|
||||
valid: false,
|
||||
brokenAt: i,
|
||||
reason: "Event hash mismatch"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example Audit Events
|
||||
|
||||
### Promotion Approved
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt-123",
|
||||
"timestamp": "2026-01-09T14:32:15Z",
|
||||
"tenantId": "tenant-uuid",
|
||||
"actorType": "user",
|
||||
"actorId": "user-uuid",
|
||||
"actorName": "jane@example.com",
|
||||
"actorIp": "192.168.1.100",
|
||||
"action": "promotion.approved",
|
||||
"resource": "promotion",
|
||||
"resourceId": "promo-uuid",
|
||||
"environmentId": "env-uuid",
|
||||
"releaseId": "rel-uuid",
|
||||
"promotionId": "promo-uuid",
|
||||
"before": {
|
||||
"status": "pending"
|
||||
},
|
||||
"after": {
|
||||
"status": "approved",
|
||||
"approvals": 2
|
||||
},
|
||||
"metadata": {
|
||||
"comment": "LGTM"
|
||||
},
|
||||
"previousEventHash": "sha256:abc...",
|
||||
"eventHash": "sha256:def..."
|
||||
}
|
||||
```
|
||||
|
||||
### Deployment Started
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt-124",
|
||||
"timestamp": "2026-01-09T14:32:20Z",
|
||||
"tenantId": "tenant-uuid",
|
||||
"actorType": "system",
|
||||
"actorId": "system",
|
||||
"actorName": "deployment-orchestrator",
|
||||
"action": "deployment.started",
|
||||
"resource": "deployment",
|
||||
"resourceId": "deploy-uuid",
|
||||
"environmentId": "env-uuid",
|
||||
"releaseId": "rel-uuid",
|
||||
"promotionId": "promo-uuid",
|
||||
"after": {
|
||||
"status": "deploying",
|
||||
"strategy": "rolling",
|
||||
"targetCount": 5
|
||||
},
|
||||
"previousEventHash": "sha256:def...",
|
||||
"eventHash": "sha256:ghi..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Retention Policy
|
||||
|
||||
| Environment | Retention Period |
|
||||
|-------------|------------------|
|
||||
| All tenants | 7 years (compliance) |
|
||||
| After tenant deletion | 7 years (legal hold) |
|
||||
| Archive format | NDJSON, signed |
|
||||
|
||||
---
|
||||
|
||||
## Export Format
|
||||
|
||||
Audit events can be exported for compliance reporting:
|
||||
|
||||
```bash
|
||||
# Export audit trail for a date range
|
||||
GET /api/v1/audit/export?
|
||||
start=2026-01-01T00:00:00Z&
|
||||
end=2026-01-31T23:59:59Z&
|
||||
format=ndjson
|
||||
```
|
||||
|
||||
Response includes signed digest for verification:
|
||||
|
||||
```json
|
||||
{
|
||||
"export": {
|
||||
"startDate": "2026-01-01T00:00:00Z",
|
||||
"endDate": "2026-01-31T23:59:59Z",
|
||||
"eventCount": 15234,
|
||||
"firstEventHash": "sha256:abc...",
|
||||
"lastEventHash": "sha256:xyz...",
|
||||
"downloadUrl": "https://..."
|
||||
},
|
||||
"signature": "base64-signature",
|
||||
"signedAt": "2026-02-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Security Overview](overview.md)
|
||||
- [Evidence](../modules/evidence.md)
|
||||
- [Logging](../operations/logging.md)
|
||||
- [Evidence Schema](../appendices/evidence-schema.md)
|
||||
Reference in New Issue
Block a user