release orchestrator pivot, architecture and planning

This commit is contained in:
2026-01-10 22:37:22 +02:00
parent c84f421e2f
commit d509c44411
130 changed files with 70292 additions and 721 deletions

View File

@@ -0,0 +1,221 @@
# Design Principles & Invariants
> These principles are **inviolable** and MUST be reflected in all code, UI, documentation, and audit artifacts.
## Core Principles
### Principle 1: Release Identity via Digest
```
INVARIANT: A release is a set of OCI image digests (component → digest mapping), never tags.
```
- Tags are convenience inputs for resolution
- Tags are resolved to digests at release creation time
- All downstream operations (promotion, deployment, rollback) use digests
- Digest mismatch at pull time = deployment failure (tamper detection)
**Implementation Requirements:**
- Release creation API accepts tags but immediately resolves to digests
- All internal references use `sha256:` prefixed digests
- Agent deployment verifies digest at pull time
- Rollback targets specific digest, not "previous tag"
### Principle 2: Determinism and Evidence
```
INVARIANT: Every deployment/promotion produces an immutable evidence record.
```
Evidence record contains:
- **Who**: User identity (from Authority)
- **What**: Release bundle (digests), target environment, target hosts
- **Why**: Policy evaluation result, approval records, decision reasons
- **How**: Generated artifacts (compose files, scripts), execution logs
- **When**: Timestamps for request, decision, execution, completion
Evidence enables:
- Audit-grade compliance reporting
- Deterministic replay (same inputs + policy → same decision)
- "Why blocked?" explainability
**Implementation Requirements:**
- Evidence is generated synchronously with decision
- Evidence is signed before storage
- Evidence table is append-only (no UPDATE/DELETE)
- Evidence includes hash of all inputs for replay verification
### Principle 3: Pluggable Everything, Stable Core
```
INVARIANT: Integrations are plugins; the core orchestration engine is stable.
```
**Plugins contribute:**
- Configuration screens (UI)
- Connector logic (runtime)
- Step node types (workflow)
- Doctor checks (diagnostics)
- Agent types (deployment)
**Core engine provides:**
- Workflow execution (DAG processing)
- State machine management
- Evidence generation
- Policy evaluation
- Credential brokering
**Implementation Requirements:**
- Core has no hard-coded integrations
- Plugin interface is versioned and stable
- Plugin failures cannot crash core
- Core provides fallback behavior when plugins unavailable
### Principle 4: No Feature Gating
```
INVARIANT: All plans include all features. Limits are only:
- Number of environments
- Number of new digests analyzed per day
- Fair use on deployments
```
This prevents:
- "Pay for security" anti-pattern
- Per-project/per-seat billing landmines
- Feature fragmentation across tiers
**Implementation Requirements:**
- No feature flags tied to billing tier
- Quota enforcement is transparent (clear error messages)
- Usage metrics exposed for customer visibility
- Overage handling is graceful (soft limits with warnings)
### Principle 5: Offline-First Operation
```
INVARIANT: All core operations MUST work in air-gapped environments.
```
Implications:
- No runtime calls to external APIs for core decisions
- Vulnerability data synced via mirror bundles
- Plugins may require connectivity; core does not
- Evidence packets exportable for external audit
**Implementation Requirements:**
- Core decision logic has no external HTTP calls
- All external data is pre-synced and cached
- Plugin connectivity requirements are declared in manifest
- Offline mode is explicit configuration, not degraded fallback
### Principle 6: Immutable Generated Artifacts
```
INVARIANT: Every deployment generates and stores immutable artifacts.
```
Generated artifacts:
- `compose.stella.lock.yml`: Pinned digests, resolved env refs
- `deploy.stella.script.dll`: Compiled C# script (or hash reference)
- `release.evidence.json`: Decision record
- `stella.version.json`: Version sticker placed on target
Version sticker enables:
- Drift detection (expected vs actual)
- Audit trail on target host
- Rollback reference
**Implementation Requirements:**
- Artifacts are content-addressed (hash in filename or metadata)
- Artifacts are stored before deployment execution
- Artifact storage is immutable (no overwrites)
- Version sticker is atomic write on target
---
## Architectural Invariants (Enforced by Design)
These invariants are enforced through database constraints, code architecture, and operational controls.
| Invariant | Enforcement Mechanism |
|-----------|----------------------|
| Digests are immutable | Database constraint: digest column is unique, no updates |
| Evidence packets are append-only | Evidence table has no UPDATE/DELETE permissions |
| Secrets never in database | Vault integration; only references stored |
| Plugins cannot bypass policy | Policy evaluation in core, not plugin |
| Multi-tenant isolation | `tenant_id` FK on all tables; row-level security |
| Workflow state is auditable | State transitions logged; no direct state manipulation |
| Approvals are tamper-evident | Approval records are signed and append-only |
### Database Enforcement
```sql
-- Example: Evidence table with no UPDATE/DELETE
CREATE TABLE release.evidence_packets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
promotion_id UUID NOT NULL REFERENCES release.promotions(id),
content_hash TEXT NOT NULL,
content JSONB NOT NULL,
signature TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
-- No updated_at column; immutable by design
);
-- Revoke UPDATE/DELETE from application role
REVOKE UPDATE, DELETE ON release.evidence_packets FROM app_role;
```
### Code Architecture Enforcement
```csharp
// Policy evaluation is ALWAYS in core, never delegated to plugins
public sealed class PromotionDecisionEngine
{
// Plugins provide gate implementations, but core orchestrates evaluation
public async Task<DecisionResult> EvaluateAsync(
Promotion promotion,
IReadOnlyList<IGateProvider> gates,
CancellationToken ct)
{
// Core controls evaluation order and aggregation
var results = new List<GateResult>();
foreach (var gate in gates)
{
// Plugin provides evaluation logic
var result = await gate.EvaluateAsync(promotion, ct);
results.Add(result);
// Core decides how to aggregate (plugins cannot override)
if (result.IsBlocking && _policy.FailFast)
break;
}
// Core makes final decision
return _decisionAggregator.Aggregate(results);
}
}
```
---
## Document Conventions
Throughout the Release Orchestrator documentation:
- **MUST**: Mandatory requirement; non-compliance is a bug
- **SHOULD**: Recommended but not mandatory; deviation requires justification
- **MAY**: Optional; implementation decision
- **Entity names**: `PascalCase` (e.g., `ReleaseBundle`)
- **Table names**: `snake_case` (e.g., `release_bundles`)
- **API paths**: `/api/v1/resource-name`
- **Module names**: `kebab-case` (e.g., `release-manager`)
---
## References
- [Key Architectural Decisions](decisions.md)
- [Module Architecture](../modules/overview.md)
- [Security Architecture](../security/overview.md)