Architecture Decisions

ADR-001: Hybrid ECR Management

Architecture decision for managing ECR with central OIDC roles and per-project repositories.

Approved
  • Status: Accepted
  • Date: 2026-02-08
  • Issue: #15

Context

The Ontopix organization needs an ECR (Elastic Container Registry) to store Docker images used across multiple projects (starting with maxcolchon/agent-support for Amazon Bedrock AgentCore Runtime).

ECR differs from CodeArtifact in a key way: the registry already exists per AWS account — only repositories (which hold images for a specific service) need to be created. This raised the question of where repository definitions should live.

Two approaches were considered:

  1. Fully centralized (like CodeArtifact): all ECR repositories defined in ontopix/infra. Adding a new image repository requires a PR to this repo.
  2. Hybrid: ontopix/infra manages only the org-wide OIDC access roles. Each project creates its own ECR repositories with project-specific configuration.

Decision

We adopt the hybrid approach:

  • ontopix/infra (global) manages GitHub Actions OIDC roles for ECR push/pull access. These are org-wide — any ontopix/* repository can assume them.
  • Per-project Terraform creates the actual aws_ecr_repository resources, lifecycle policies, and scanning configuration.

Rationale

  • Team autonomy: projects control their own container infrastructure (retention policies, scanning settings) without PRs to global infra.
  • Different projects have different needs: one project may keep 10 images, another 50. Lifecycle policies are project-specific decisions.
  • Minimal bottleneck: the only shared resource is the OIDC role, which rarely changes. Day-to-day push/pull operations need no global coordination.
  • CodeArtifact is different: it has a domain concept and shared repositories (npm, pypi). ECR repositories are project-scoped by nature.

Naming Convention

ECR repositories follow the pattern {project}/{image}:

maxcolchon/agent-support
ontopix/some-service

This mirrors the GitHub organization structure and prevents namespace collisions across projects.

Responsibilities

ConcernManaged byLocation
OIDC roles (push/pull)ontopix/infraglobal/ecr/iam.tf
ECR repositoriesPer-projectProject's own Terraform
Lifecycle policiesPer-projectProject's own Terraform
Image scanning configPer-projectProject's own Terraform
Tag immutabilityPer-projectProject's own Terraform

Consequences

Positive:

  • Teams can iterate on their container infrastructure independently.
  • Global infra stays thin and focused on access control.
  • Adding a new project's images doesn't require changes to ontopix/infra.

Negative:

  • No centralized enforcement of lifecycle policies or scanning. Teams must follow the recommended patterns in global/ecr/README.md.
  • If a project misconfigures their repository, global infra won't catch it.

Mitigations:

  • The global/ecr/README.md documents recommended settings (immutable tags, scan on push, lifecycle rules).
  • The OIDC roles are scoped to the ontopix GitHub organization, so only org repos can push/pull.

Future Considerations

  • Cross-account access: if additional AWS accounts need to pull images, registry-level policies can be added to this module without changing the per-project approach.
  • Policy enforcement: if inconsistency becomes a problem, we can introduce a shared Terraform module for repository creation with opinionated defaults.