ADR-001: Hybrid ECR Management
Architecture decision for managing ECR with central OIDC roles and per-project repositories.
- 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:
- Fully centralized (like CodeArtifact): all ECR repositories defined in
ontopix/infra. Adding a new image repository requires a PR to this repo. - Hybrid:
ontopix/inframanages 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 — anyontopix/*repository can assume them.- Per-project Terraform creates the actual
aws_ecr_repositoryresources, 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
| Concern | Managed by | Location |
|---|---|---|
| OIDC roles (push/pull) | ontopix/infra | global/ecr/iam.tf |
| ECR repositories | Per-project | Project's own Terraform |
| Lifecycle policies | Per-project | Project's own Terraform |
| Image scanning config | Per-project | Project's own Terraform |
| Tag immutability | Per-project | Project'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.mddocuments recommended settings (immutable tags, scan on push, lifecycle rules). - The OIDC roles are scoped to the
ontopixGitHub 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.