Build CoreOrdered learning track

Ownership, CODEOWNERS, and Review Routing

Learn Git In Action - Part 049

Ownership, CODEOWNERS, review routing, escalation, ownership decay, dan desain review topology untuk repository skala tim maupun enterprise.

12 min read2338 words
PrevNext
Lesson 49126 lesson track24–68 Build Core
#git#codeowners#code-review#governance+3 more

Part 049 — Ownership, CODEOWNERS, and Review Routing

Repository tanpa ownership yang jelas akan terlihat “kolaboratif” di awal, lalu berubah menjadi sistem approval acak: reviewer dipilih berdasarkan siapa yang sedang online, bukan siapa yang memahami invariants dari area yang berubah.

1. Problem Statement

Git menyimpan perubahan. Platform seperti GitHub/GitLab/Bitbucket membantu review perubahan. Tetapi Git sendiri tidak tahu:

  • siapa pemilik modul pembayaran;
  • siapa yang paham migrasi database;
  • siapa yang harus approve perubahan IAM policy;
  • siapa yang menjaga API compatibility;
  • siapa yang wajib melihat perubahan compliance report;
  • kapan reviewer boleh dilewati;
  • kapan escalation harus terjadi.

Tanpa ownership, PR routing menjadi tribal knowledge.

Gejalanya biasanya begini:

Author membuka PR
  -> men-tag orang yang sering responsive
  -> reviewer melihat style issue, bukan invariant penting
  -> owner domain tidak sadar ada perubahan
  -> perubahan merge
  -> incident muncul di runtime, release, audit, atau customer environment

Ownership bukan birokrasi. Ownership adalah mekanisme untuk memastikan perubahan dilihat oleh orang atau tim yang punya konteks cukup untuk menilai risiko.

2. Core Mental Model

CODEOWNERS bukan “daftar orang penting”. Ia adalah routing table untuk review responsibility.

Ada tiga layer berbeda:

LayerPertanyaanContoh
Ownership declarationSiapa responsible untuk path ini?CODEOWNERS
Review routingSiapa diminta review saat PR berubah?Auto-review request
Merge enforcementApakah approval owner wajib?Branch protection / repository ruleset

Kesalahan umum adalah menganggap CODEOWNERS otomatis berarti enforcement. Di banyak platform, ownership dapat menjadi review request otomatis, tetapi enforcement biasanya perlu branch protection/ruleset tambahan.

3. CODEOWNERS as Routing Table

Contoh minimal:

# Default owner untuk semua file
* @org/platform-foundation

# Payment domain
/services/payment/ @org/payment-team

# Database migration risk
/db/migrations/ @org/database-reviewers

# Infrastructure-as-code
/infra/ @org/cloud-platform @org/security

# Public API contract
/api/openapi.yaml @org/api-governance

# Compliance report template
/reports/compliance/ @org/regulatory-engineering

Interpretasi operasionalnya:

  • perubahan di /services/payment/ perlu payment domain review;
  • perubahan di /infra/ perlu platform dan security context;
  • perubahan di OpenAPI spec perlu API governance;
  • perubahan compliance report perlu orang yang memahami defensibility dan evidence model.

Yang penting bukan hanya siapa owner-nya, tetapi apakah boundary path-nya mencerminkan boundary risiko.

4. Ownership Is Not the Same as Authorship

Author adalah orang yang membuat perubahan.

Owner adalah orang/tim yang bertanggung jawab menjaga invariant suatu area.

Maintainer adalah orang/tim yang punya hak operasional untuk merge/release/rollback.

Reviewer adalah orang yang diminta memberikan signal terhadap PR tertentu.

Approver adalah reviewer yang approval-nya memenuhi rule.

Jika role ini dicampur, workflow menjadi rapuh:

  • author approve sendiri karena pernah menyentuh area itu;
  • reviewer non-owner approve perubahan high-risk;
  • maintainer merge karena CI hijau meskipun domain owner belum melihat;
  • owner hanya dianggap “FYI”, bukan gatekeeper untuk path tertentu.

5. What Good Ownership Protects

Ownership yang baik melindungi beberapa invariant.

5.1 Domain Invariants

Contoh:

Enforcement case cannot move from CLOSED back to INVESTIGATION
unless reopened by explicit appeal event.

File yang menyentuh state machine enforcement lifecycle harus dimiliki oleh tim yang memahami lifecycle, bukan hanya Java/Node/Vue maintainer umum.

5.2 Compatibility Invariants

Contoh:

  • public API response field tidak boleh dihapus tanpa deprecation window;
  • event schema tidak boleh breaking tanpa versioning;
  • DB migration harus backward-compatible selama rolling deploy;
  • feature flag default tidak boleh mengubah behavior tenant existing.

5.3 Operational Invariants

Contoh:

  • retry policy tidak boleh memperbesar duplicate action risk;
  • queue consumer tidak boleh kehilangan idempotency key;
  • config default tidak boleh menaikkan blast radius;
  • IaC tidak boleh membuka security group terlalu luas.

5.4 Regulatory / Audit Invariants

Contoh:

  • audit event harus append-only;
  • actor identity tidak boleh nullable untuk enforcement action;
  • case timeline tidak boleh bisa diubah tanpa correction record;
  • report template harus preserve required evidence fields.

6. Designing Ownership Boundaries

Ownership boundary yang buruk mengikuti struktur folder secara mekanis.

Ownership boundary yang baik mengikuti risk boundary.

Boundary TypeCocok untukRisiko jika salah
Path ownershipMonorepo, modular services, docs, infraPath refactor membuat ownership bocor
Domain ownershipPayment, identity, enforcement, reportingDomain tersebar di banyak path
Technology ownershipDatabase, security, frontend, API, mobileReviewer terlalu horizontal, kurang context domain
Risk ownershipSecrets, migrations, authz, compliance, public APIBisa terlalu banyak reviewer jika granularitas buruk
Release ownershipMaintenance branch, LTS branch, customer branchBackport salah tanpa owner versi target

Praktiknya, ownership sering butuh kombinasi.

Contoh:

/services/case-management/         @org/case-domain
/services/case-management/authz/   @org/case-domain @org/security
/services/case-management/db/      @org/case-domain @org/database
/services/case-management/reports/ @org/case-domain @org/regulatory

Boundary ini mengatakan:

  • semua area case-management milik case domain;
  • authz perlu security;
  • database perlu database reviewer;
  • report perlu regulatory reviewer.

7. CODEOWNERS Pattern Strategy

7.1 Put Broad Defaults First, Specific Rules Later

Dalam banyak CODEOWNERS implementation, rule yang lebih akhir dan lebih spesifik biasanya dapat override rule sebelumnya. Karena detail implementasi platform perlu dicek, tim harus menulis file dengan urutan yang mudah diaudit dan dites.

Pattern yang sehat:

# 1. Safe default
* @org/platform-maintainers

# 2. Major domains
/services/payment/ @org/payment
/services/case/ @org/case-domain
/services/identity/ @org/identity

# 3. Cross-cutting high-risk areas
**/migrations/** @org/database
**/authz/** @org/security
**/openapi.yaml @org/api-governance

# 4. Release-critical metadata
/.github/workflows/release*.yml @org/release-engineering @org/security
/charts/** @org/platform @org/sre

7.2 Avoid Personal Ownership for Critical Areas

Buruk:

/services/payment/ @alice

Lebih baik:

/services/payment/ @org/payment-team

Alasan:

  • orang cuti;
  • orang pindah tim;
  • load review tidak seimbang;
  • approval menjadi single point of failure;
  • knowledge tidak berkembang ke tim.

Individual ownership masih berguna untuk area kecil, experimental, atau docs tertentu, tetapi area production-critical harus team-owned.

7.3 Separate Consulted Reviewer from Required Reviewer

Tidak semua orang yang perlu tahu harus menjadi required approver.

Contoh:

/infra/network/ @org/cloud-platform @org/security
/docs/networking/ @org/cloud-platform

Security required untuk perubahan network production, tetapi mungkin tidak wajib untuk docs biasa kecuali docs itu adalah compliance evidence.

Jika semua reviewer menjadi required reviewer, PR latency naik dan orang mulai mencari bypass.

8. Review Routing Topologies

8.1 Single Owner

Cocok untuk service kecil dengan ownership jelas.

Risiko:

  • owner overload;
  • cross-cutting risk tidak terlihat;
  • perubahan security/database bisa lolos jika path hanya dimiliki domain team.

8.2 Layered Ownership

Cocok untuk perubahan yang punya domain dan platform risk.

Risiko:

  • terlalu banyak required approval;
  • unclear reviewer responsibility;
  • masing-masing reviewer mengira yang lain mengecek area tertentu.

Solusi: definisikan checklist per owner.

8.3 Risk-Based Ownership

Cocok untuk regulated systems, platform repos, dan monorepo besar.

8.4 Escalation Ownership

Cocok untuk:

  • emergency hotfix;
  • authz policy changes;
  • data retention changes;
  • release pipeline changes;
  • incident remediation.

9. CODEOWNERS for Monorepo

Monorepo membuat ownership lebih penting karena banyak domain hidup dalam satu graph.

Contoh struktur:

/apps/admin-ui/
/apps/public-portal/
/services/case-management/
/services/identity/
/libs/audit-log/
/libs/workflow-engine/
/infra/
/db/
/.github/workflows/

CODEOWNERS awal:

* @org/platform-foundation

/apps/admin-ui/ @org/frontend-platform @org/admin-domain
/apps/public-portal/ @org/frontend-platform @org/public-portal

/services/case-management/ @org/case-domain
/services/identity/ @org/identity

/libs/audit-log/ @org/platform-foundation @org/regulatory-engineering
/libs/workflow-engine/ @org/platform-foundation @org/case-domain

/db/migrations/ @org/database
/infra/ @org/cloud-platform @org/security
/.github/workflows/ @org/devex @org/security

Masalah yang perlu diantisipasi:

  • generated files menyebabkan owner tambahan terlalu sering diminta;
  • shared library membuat semua domain bergantung pada satu small owner group;
  • path move bisa menghapus ownership tanpa sadar;
  • global default owner menjadi bottleneck jika terlalu luas;
  • CI generated diff bisa memicu owner yang tidak relevan.

10. Ownership for Regulated Systems

Pada sistem regulated, ownership bukan hanya quality control. Ia bagian dari evidence chain.

Contoh mapping:

AreaOwnerRequired Concern
Case state machineDomain ownerlifecycle legality, transition invariant
Enforcement actionRegulatory engineeringauthority, audit trail, action reason
Audit log libraryPlatform + complianceappend-only, actor identity, tamper evidence
Retention policyCompliance + data platformlegal retention, purge defensibility
Authorization rulesSecurity + domain ownerleast privilege, segregation of duties
Report templatesRegulatory + productrequired evidence, interpretation risk

Contoh CODEOWNERS:

/services/enforcement/state-machine/ @org/enforcement-domain @org/regulatory-engineering
/services/enforcement/actions/ @org/enforcement-domain @org/regulatory-engineering
/libs/audit-trail/ @org/platform-foundation @org/regulatory-engineering
/security/policies/ @org/security @org/regulatory-engineering
/reports/statutory/ @org/regulatory-engineering

Yang penting: owner harus tahu apa yang harus mereka review.

Tanpa review rubric, CODEOWNERS hanya jadi label.

11. Review Responsibility Matrix

Buat responsibility matrix eksplisit.

Owner TypeYang harus diperiksaYang tidak harus menjadi fokus utama
Domain ownerbusiness invariant, behavior, edge case, user journeysyntax/style kecil
Security ownerauthn/authz, secrets, threat model, privilege, supply chainproduct copywriting
DB ownermigration safety, rollback, locking, data compatibilityUI layout
API ownercompatibility, versioning, schema semantics, clientsinternal implementation detail
SRE owneroperational risk, observability, rollback, capacitylocal refactor preference
Release ownerrelease boundary, tag/version, backport, changelogcode style
Compliance owneraudit evidence, data retention, defensibilityminor performance micro-optimization

Review comment yang baik harus menyebut invariant yang dijaga:

Blocking: this migration adds a NOT NULL column without a safe backfill path.
During rolling deploy, old writers can still insert rows without this column.
Please split into nullable-add -> backfill -> enforce constraint.

Bukan:

Can we do this differently?

12. Branch Protection and Required Code Owner Reviews

Ownership declaration harus dihubungkan ke protected branch rule kalau ingin menjadi gate.

Minimal policy untuk branch penting:

main:
  - require pull request before merge
  - require status checks
  - require code owner review for owned paths
  - dismiss stale approvals after new commits
  - restrict bypass to small maintainer group

release/*:
  - require release owner approval
  - require status checks from release pipeline
  - require signed tag workflow for final release

Tanpa required owner review, CODEOWNERS masih berguna sebagai notification/routing mechanism, tetapi tidak cukup untuk high-risk path.

13. Ownership Drift

Ownership drift terjadi ketika CODEOWNERS tidak lagi mencerminkan real expertise.

Gejala:

  • owner selalu approve tanpa membaca;
  • owner tidak lagi bekerja di area itu;
  • PR sering stuck karena owner tidak aktif;
  • file pindah path tapi owner tidak ikut pindah;
  • team name berubah tapi CODEOWNERS tidak diupdate;
  • domain baru muncul tanpa owner;
  • default owner menerima terlalu banyak PR acak.

Tambahkan audit berkala.

# cari path tanpa explicit owner secara kasar
find services libs apps infra -maxdepth 2 -type d | sort

# lihat churn tinggi untuk path tertentu
git log --since='90 days ago' --numstat -- services/payment \
  | awk 'NF==3 {add[$3]+=$1; del[$3]+=$2} END {for (f in add) print add[f]+del[f], f}' \
  | sort -nr | head

# lihat siapa yang sering mengubah area
git log --since='180 days ago' --format='%ae' -- services/payment \
  | sort | uniq -c | sort -nr | head

Audit ownership bukan untuk mengubah owner berdasarkan siapa paling sering commit. Churn hanya sinyal untuk mengecek apakah owner masih selaras dengan real work.

14. Ownership Coverage Test

Untuk repository besar, ownership perlu dites seperti config lain.

Contoh pseudo-test:

#!/usr/bin/env bash
set -euo pipefail

critical_paths=(
  "services/enforcement/state-machine/"
  "libs/audit-trail/"
  "infra/"
  "db/migrations/"
  ".github/workflows/"
)

for path in "${critical_paths[@]}"; do
  if ! grep -q "$path" CODEOWNERS; then
    echo "Missing CODEOWNERS rule for $path" >&2
    exit 1
  fi
done

Lebih matang lagi, buat tool internal yang:

  • parse CODEOWNERS;
  • simulasikan changed files;
  • resolve owner;
  • cek required owner coverage;
  • gagal jika high-risk path tidak punya owner eksplisit;
  • report owner overload.

15. Reviewer Load and Queue Health

Ownership yang terlalu granular bisa membuat review latency buruk.

Metrik berguna:

MetricSinyal
Time to first reviewApakah PR masuk ke reviewer yang tepat dan available?
Time from approval to mergeApakah queue/rules terlalu lambat?
Review requests per team per weekApakah owner overload?
Stale PR countApakah routing salah atau scope terlalu besar?
Approval bypass countApakah policy terlalu berat atau emergency sering?
Revert after approved PRApakah reviewer salah atau checklist kurang?
Incident linked to owner-missed changeApakah ownership boundary salah?

Jangan mengoptimasi hanya untuk cepat merge. Optimasi untuk perubahan benar yang bisa dipertanggungjawabkan.

16. Anti-Patterns

16.1 Everyone Owns Everything

* @org/all-engineers

Ini bukan ownership. Ini broadcast spam.

16.2 Default Owner as Permanent Catch-All

* @org/platform

Default owner berguna untuk fallback. Tetapi jika sebagian besar PR hanya kena default owner, ownership model belum selesai.

16.3 Owner as Rubber Stamp

Approval tanpa komentar di area high-risk tidak cukup sebagai evidence. Minimal harus ada checklist atau statement:

Reviewed migration safety: additive-only, no blocking table rewrite, rollback path documented.

16.4 Required Owners Too Broad

Jika setiap PR butuh lima tim, tim akan mencari jalan pintas:

  • split PR palsu;
  • move file untuk menghindari owner;
  • bypass dengan admin;
  • approve tanpa membaca.

16.5 Individual Owner for Critical Path

Single-person owner adalah risk concentration.

16.6 CODEOWNERS Not on Target/Base Branch

Review routing biasanya dihitung berdasarkan CODEOWNERS pada base branch PR, bukan sekadar file di feature branch. Jadi mengubah CODEOWNERS di branch feature belum tentu mengubah routing PR itu sendiri sampai perubahan masuk ke base branch.

17. Escalation Protocol

Buat protokol eksplisit.

Emergency bypass harus meninggalkan evidence:

Emergency merge justification:
- incident id:
- affected service:
- risk of waiting:
- reviewer unavailable:
- fallback approver:
- post-merge audit owner:
- rollback plan:

18. Review Routing for Stacked Branches

Stacked PR membuat ownership lebih rumit.

Misalnya:

PR-1: add new workflow engine abstraction
PR-2: migrate case service to workflow engine
PR-3: update enforcement transition rules

Owner yang relevan:

  • PR-1: platform + domain consumers;
  • PR-2: case domain;
  • PR-3: enforcement/regulatory.

Jangan jadikan PR-3 mereview seluruh perubahan PR-1 dan PR-2 akibat target branch salah.

Gunakan target branch yang benar:

PR-1: feature/workflow-core -> main
PR-2: feature/case-workflow -> feature/workflow-core
PR-3: feature/enforcement-rules -> feature/case-workflow

Lalu setelah parent merge, restack child branch dan gunakan range-diff untuk menunjukkan perubahan baru.

19. Ownership for Generated Files

Generated files sering membuat routing noise.

Contoh:

/openapi/generated/** @org/api-governance

Mungkin salah, karena generated output bukan sumber intent.

Lebih baik:

/openapi/specs/** @org/api-governance
/openapi/generated/** @org/api-tooling

Review source-of-truth file, bukan output generated kecuali output itu dipublish langsung sebagai artifact release.

20. Ownership for Secrets, CI, and Release Pipeline

Path berikut harus hampir selalu high-risk:

.github/workflows/**
.gitlab-ci.yml
Jenkinsfile
Dockerfile
charts/**
terraform/**
helm/**
scripts/release/**
scripts/deploy/**
security/**

Mengapa?

Karena perubahan di sini dapat:

  • mengubah supply chain;
  • mencuri secret via CI;
  • melewati test;
  • mengubah artifact release;
  • mengubah deployment environment;
  • melemahkan provenance.

Contoh rule:

/.github/workflows/ @org/devex @org/security
/scripts/release/ @org/release-engineering @org/security
/terraform/ @org/cloud-platform @org/security
/Dockerfile @org/platform-foundation @org/security

21. Practical Playbook: Introducing CODEOWNERS to Existing Repo

Step 1 — Inventory High-Risk Paths

Mulai dari risk, bukan seluruh repo.

- authn/authz
- database migrations
- public API contracts
- release pipeline
- infra/IaC
- regulatory/audit/reporting
- payment/billing
- secrets/config

Step 2 — Add Conservative Default Owner

* @org/repo-maintainers

Step 3 — Add Explicit High-Risk Owners

/db/migrations/ @org/database
/security/ @org/security
/.github/workflows/ @org/devex @org/security

Step 4 — Add Domain Owners

/services/case-management/ @org/case-domain
/services/enforcement/ @org/enforcement-domain

Step 5 — Enable Advisory Routing First

Biarkan auto-request berjalan dulu untuk melihat noise.

Step 6 — Enable Required Owner Review for Critical Branches

Jangan langsung enforce seluruh repo. Mulai dari:

main
release/*
hotfix/*

Step 7 — Review Metrics and Tune

Setiap 2-4 minggu:

  • path mana yang terlalu noisy;
  • owner mana yang overloaded;
  • PR mana yang stuck;
  • incident mana yang lolos ownership;
  • apakah owner aktual masih benar.

22. Practical Checklist for PR Authors

Sebelum request review:

[ ] Saya tahu path mana yang berubah dan owner mana yang akan kena.
[ ] Saya sudah split PR jika perubahan menyentuh ownership boundary berbeda.
[ ] Saya menulis summary risiko untuk owner.
[ ] Saya menandai migration/config/security/release impact jika ada.
[ ] Saya tidak mengandalkan reviewer untuk menebak intent.
[ ] Saya sudah menjalankan test yang relevan dengan owner concern.

Template PR:

## What changed

## Why

## Ownership-sensitive areas
- Domain:
- Security:
- Database:
- API compatibility:
- Release/ops:
- Compliance/audit:

## Verification

## Rollback

23. Practical Checklist for Owners

Saat review sebagai owner:

[ ] Apakah perubahan menyentuh invariant area saya?
[ ] Apakah behavior baru benar, bukan hanya code-nya rapi?
[ ] Apakah backward/forward compatibility aman?
[ ] Apakah rollback path masuk akal?
[ ] Apakah test membuktikan invariant penting?
[ ] Apakah dokumentasi/operational note perlu update?
[ ] Apakah saya perlu escalate ke owner lain?

Owner tidak harus review semua baris dengan kedalaman sama. Owner harus mengalokasikan perhatian ke bagian yang menjaga invariant.

24. Practical Checklist for Maintainers

Sebelum merge:

[ ] Required owner approval sudah terpenuhi.
[ ] Tidak ada owner yang “sekadar FYI” untuk high-risk path.
[ ] Approval tidak stale setelah commit baru.
[ ] CI berjalan terhadap merge result atau merge queue.
[ ] PR scope tidak menyatukan ownership boundary yang tidak perlu.
[ ] Jika emergency bypass, evidence dicatat.

25. Ownership as Architecture Feedback

Jika CODEOWNERS menjadi terlalu kompleks, itu mungkin bukan masalah CODEOWNERS. Itu sinyal architecture boundary membingungkan.

Contoh smell:

/services/foo/ needs payment, identity, reporting, database, security, platform, and compliance owners for most changes.

Kemungkinan masalah:

  • service terlalu banyak responsibility;
  • shared module terlalu central;
  • compliance logic tersebar;
  • security policy embedded di domain code tanpa abstraction;
  • generated code bercampur source-of-truth;
  • folder layout tidak mencerminkan domain boundary.

Jangan hanya menambah rule. Gunakan ownership pain sebagai input refactoring architecture.

26. Mini Lab: Build Ownership Map from Git History

Tujuan: melihat apakah ownership formal cocok dengan aktivitas aktual.

#!/usr/bin/env bash
set -euo pipefail

path=${1:-services/case-management}

echo "Top authors for $path in last 180 days"
git log --since='180 days ago' --format='%ae' -- "$path" \
  | sort | uniq -c | sort -nr | head -10

echo
echo "Top changed files"
git log --since='180 days ago' --numstat -- "$path" \
  | awk 'NF==3 { churn[$3]+=$1+$2 } END { for (f in churn) print churn[f], f }' \
  | sort -nr | head -20

Interpretasi:

  • author sering berubah tidak otomatis jadi owner;
  • churn tinggi di file tanpa owner adalah risk signal;
  • file critical dengan sedikit perubahan tetap butuh owner;
  • file sering disentuh oleh banyak tim mungkin perlu boundary redesign.

27. Mini Lab: Simulate PR Ownership

Buat file changed-files:

services/enforcement/state-machine/TransitionPolicy.java
services/enforcement/db/migrations/V122__add_appeal_reason.sql
.github/workflows/release.yml
reports/statutory/monthly-template.json

Tentukan owner yang seharusnya:

TransitionPolicy.java -> enforcement-domain + regulatory-engineering
migration -> database + enforcement-domain
release.yml -> devex + security + release-engineering
monthly-template.json -> regulatory-engineering

Jika CODEOWNERS tidak menghasilkan hasil seperti ini, ownership routing belum mencerminkan risiko nyata.

28. Key Takeaways

  • Ownership adalah routing tanggung jawab, bukan daftar nama dekoratif.
  • CODEOWNERS berguna hanya jika boundary-nya mengikuti risk/domain boundary.
  • Required owner review harus digunakan selektif untuk branch/path penting.
  • Terlalu banyak required owner akan menciptakan bypass behavior.
  • Owner harus tahu invariant yang mereka jaga.
  • Ownership drift harus diaudit berkala.
  • Complexity di CODEOWNERS sering mengungkap masalah architecture boundary.

29. References

Lesson Recap

You just completed lesson 49 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.