7.1 KiB
7.1 KiB
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 refsdeploy.stella.script.dll: Compiled C# script (or hash reference)release.evidence.json: Decision recordstella.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
-- 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
// 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)