Orca ORCA v0.174.2
Documentation navigation

Platform Standards and Guidelines

This document captures the platform engineering team's conventions and requirements for authoring Helm charts and managing infrastructure. They apply to all charts published or maintained by the team, including common-chart and any service-specific charts.

Chart Design & Structure

Charts must be self-contained

Charts must not depend on resources created by other charts (e.g. ServiceAccounts, Secrets, ConfigMaps) unless those resources are explicitly declared as prerequisites in the chart documentation.

Why: Cross-chart coupling introduces hidden deployment ordering dependencies. If Chart B silently assumes Chart A has already run, deployments fail in non-obvious ways and become difficult to test in isolation.

Identities are per-service

Each chart must create and manage its own ServiceAccount and, where applicable, its own managed identity binding. Sharing identities across charts is not permitted.

Why: Shared identities violate the principle of least privilege. If one service is compromised or its credentials leak, a shared identity expands the blast radius to every service that uses it.

Helper templates must be scoped to the chart name

Named templates (defined with {{- define "..." }}) must be prefixed with the chart name, e.g. mychart.fullname.

Why: Helm merges all named templates into a single global namespace at render time. Without scoping, two charts that define fullname will silently shadow each other when composed in an umbrella chart.

Charts must provide meaningful abstractions over Kubernetes primitives

Values files should expose intent (e.g. autoscaling.enabled, ingress.host) rather than raw Kubernetes fields. Avoid "values that are just YAML pass-through."

Why: Charts are interfaces, not wrappers. If a consumer needs to understand the underlying Kubernetes resource to configure the chart, the abstraction has failed. Meaningful abstractions reduce the learning surface and make charts safer to use.

Composition must use umbrella charts

When multiple charts need to be deployed together, use a Helm umbrella chart. Ad-hoc composition (e.g. deploying charts via separate ArgoCD Applications that share a namespace and have implicit dependencies) is not acceptable as a substitute.

Why: Umbrella charts make composition explicit, versioned, and testable. Implicit multi-chart dependencies are fragile — they break silently when deployment order changes and cannot be linted or unit-tested as a unit.

Application names must follow <namespace>-<releaseName> format

The ArgoCD appName in config.json must be set to <namespace>-<releaseName>.

Why: ArgoCD Application names must be unique per cluster. A predictable convention makes names self-documenting (base-agent-api is immediately understood) and eliminates collisions when the same chart is deployed to multiple tenants.


Resource Naming & Configuration

Resource names must include Release.Name

All namespaced Kubernetes resources must include {{ .Release.Name }} in their name. Cluster-scoped resources (e.g. ClusterRole, ClusterRoleBinding) must also include {{ .Release.Namespace }}.

Why: Kubernetes requires unique names within a scope. Without Release.Name, installing the same chart twice in the same cluster (e.g. for two tenants) causes resource conflicts. Cluster-scoped resources additionally need the namespace to avoid collisions across namespaces.

Corti-specific defaults must be overridable via values

Any Corti domain name, registry URL, or other organisation-specific constant may be set as a default, but must be configurable through a documented Helm value.

Why: Hardcoded constants make charts unusable outside the standard Corti environment — for on-premise customers, isolated test environments, or future tenants. Exposing them as values keeps charts portable without requiring chart modifications.


Testing

Every feature toggle must have a Helm unit test

Any chart feature that can be enabled or disabled via a values flag must be covered by at least one Helm unit test that exercises the enabled path.

Why: Helm renders templates at deploy time. Untested feature flags can silently produce invalid YAML or omit required fields, only failing when the chart is applied to a cluster. Unit tests catch these rendering errors in CI, before any cluster is involved.


Registry

All OCI images must be mirrored to the internal registry

Container images referenced by chart defaults must be available in Corti's internal OCI registry. Upstream registry URLs must not be used as defaults.

Why: Pulling from upstream registries at deploy time creates a hard dependency on external availability and network egress. Mirroring guarantees deployments succeed during upstream outages, gives us control over which image versions are available, and ensures images are scanned by our own tooling before reaching production.


Change Management

Breaking changes require a migration runbook in the PR description

Any chart change that requires consumers to update their values or perform manual steps before or after the upgrade must include a step-by-step migration runbook directly in the pull request description.

Why: Breaking changes require coordinated action across multiple teams. Reviewers need to validate the migration path during review, and operators need accurate instructions at the moment they apply the change. A runbook in the PR is the most reliable place — it is version-controlled alongside the change and visible to everyone involved.

Infrastructure changes must be backported across cluster generations

Changes to shared infrastructure charts must be applied to all supported cluster generations, not just the latest.

Why: Clusters run on different generations simultaneously (e.g. different Kubernetes versions, CNI configurations). A change that only lands on the newest generation creates configuration drift, complicates troubleshooting, and eventually makes it impossible to upgrade older clusters because they have diverged too far.

Large scripts and migrations require a second approver (4-eye principle)

Any script or migration that is complex, touches production data, or is difficult to roll back must be reviewed and approved by a second engineer before execution — regardless of normal PR review requirements.

Why: Complex or destructive operations have a higher risk of human error. When you are close to the work it is easy to miss edge cases that are obvious to a fresh reader. A mandatory second set of eyes catches mistakes before they cause an incident.


Observability

JSON-structured logging must be enabled where supported

If the upstream application supports structured logging, the chart must enable JSON log format by default.

Why: Structured JSON logs are parseable by log aggregation pipelines (e.g. Datadog). They enable filtering, alerting, and dashboard construction without fragile regex parsing. Unstructured text logs lose metadata and degrade the signal-to-noise ratio across the platform.

Metrics endpoints must be configured

Charts must expose a Prometheus-compatible metrics endpoint and include the necessary annotations or ServiceMonitor resources for scraping.

Why: Without metrics there is no way to observe the health or performance of a service. Metrics are a prerequisite for SLOs, alerting, and capacity planning. A chart that ships without metrics forces the consuming team to add observability after the fact, which often doesn't happen until after the first incident.


Reliability

Services must be deployed with PDB, ≥2 replicas, pod topology spread, and HPA/KEDA

Production workloads must configure all four:

  • PodDisruptionBudget: prevents node drains from taking a service fully offline.
  • ≥2 replicas: ensures availability during rolling updates and single-node failures.
  • Pod topology spread constraints: prevents both replicas from landing on the same node, so a single node failure does not cause a full outage.
  • HPA or KEDA: scales the service automatically under load, avoiding manual intervention during traffic spikes.

Why: Each of these controls addresses a distinct failure mode. Omitting any one of them leaves a gap that will eventually be exposed by a node drain, a rolling update, or a traffic spike. Together they form the minimum baseline for a resilient production workload.


Infrastructure as Code

Terraform must not generate files committed to this repository

IaC tooling (Terraform, Pulumi, etc.) must not write generated files into the deployments repo as part of their normal apply workflow.

Why: Generated files produce noisy, hard-to-review diffs and create a chicken-and-egg dependency between the IaC run and the GitOps reconciliation. They also make it unclear which files are authoritative: the generator or the repo. Configuration that varies per environment should use Helm values files; anything else should be managed outside the GitOps boundary.


Design Checklist

Before merging a new or significantly changed chart, ask:

Would this chart work for a different tenant or customer with no modifications to the chart itself?

If the answer is no, there is likely a hardcoded assumption that should be extracted into a value. Multi-tenancy is a first-class constraint on the platform; charts that can only serve the base tenant in the standard Corti cloud are not reusable and will require costly rework when a new deployment context arises.