Most code can be reviewed quickly. Some code moves money, guards access, holds health records
or changes production data, and a mistake there costs far more. These examples show how teams
write that difference down in coance.yml, so every pull request gets the review
its files need, and the record shows it happened.
A payments service
PCI DSS asks that bespoke and custom software be reviewed before it is released, to find
and correct coding vulnerabilities. When those reviews are manual, they are done by
someone other than the code’s author who knows code-review techniques and secure coding,
and approved by management before release.
[1]
Here the code under /payments/ and /billing/ needs two approvals
from the payments and application security teams, and the author’s own approval does not
count. Everything else in /src/ gets an ordinary review. coance enforces the
reviewer side; release approval stays part of your own process.
# .github/coance.yml for a payments service
levels:
cardholder-data:
approvals: 2
self_review: false
description: |
Code that stores, processes or transmits card data.
Read every changed line against our secure coding
guidelines, look for known and new vulnerability
patterns, and check the tests cover the failure
cases. The author's approval does not count.
standard:
description: Read the file. Does the change make sense?
rules:
paths:
cardholder-data:
/payments/: '@acme/payments @acme/appsec'
/billing/: '@acme/payments @acme/appsec'
standard: ['/src/']
Health data
The HIPAA Security Rule does not prescribe code review. It asks covered entities and
business associates to analyse the risks to electronic protected health information and to
put security measures in place that reduce them to a reasonable and appropriate level.
[3]
Code that reads, writes or sends that information is where those risks live, so it is a
natural place for a stricter level. In this example the record and messaging services and
a shared PHI library need two approvals from the privacy and security teams, with a level
description that tells reviewers exactly what to check.
# .github/coance.yml for a patient portal
levels:
phi:
approvals: 2
self_review: false
description: |
This code reads, writes or sends protected health
information. Check access control and encryption,
and that no PHI reaches logs, analytics or error
reports.
standard:
description: Read the file. Does the change make sense?
rules:
paths:
phi:
/services/records/: '@acme/privacy @acme/security'
/services/messaging/: '@acme/privacy @acme/security'
/lib/phi/: '@acme/privacy @acme/security'
standard: ['/services/', '/lib/']
Authentication, authorization and cryptography
A small change to a permission check or a token lifetime can let the wrong person in, and
it can look harmless in a large diff. NIST’s Secure Software Development Framework leaves
it to the organization to decide where human code review is used and to perform it against
its own secure coding standards.
[2]
A per-file level is that decision, written down.
Here the security team must approve every change to authentication, permissions and
cryptography, with two approvals and none from the author.
# .github/coance.yml: auth and cryptography
levels:
security:
approvals: 2
self_review: false
description: |
A mistake here lets the wrong person in or exposes
secrets. Check every permission decision, token and
session lifetime, and that only vetted cryptography
libraries are used, never hand-rolled.
standard:
description: Read the file. Does the change make sense?
rules:
paths:
security:
/src/auth/: '@acme/security'
/src/permissions/: '@acme/security'
/src/crypto/: '@acme/security'
standard: ['/src/']
Infrastructure as code and CI/CD
Terraform files decide what is exposed to the internet, and workflow files decide what
runs with production credentials. In 2018 the FTC alleged that intruders reached Uber’s
rider and driver data using an access key an engineer had posted on a code-sharing
website.
[7]
Review alone does not prevent every such mistake, but
these are the files where a second careful reader matters most.
The example also puts coance.yml and CODEOWNERS at the strict
level, so changing the review policy is itself reviewed. coance reads the policy from the
pull request’s base branch, so a pull request cannot loosen the rules that apply to
itself.
# .github/coance.yml: infrastructure and CI/CD
levels:
platform:
approvals: 2
self_review: false
description: |
Changes to infrastructure, deployment or the review
rules. Check network exposure, IAM permissions and
secrets handling, and what runs with which
credentials.
standard:
description: Read the file. Does the change make sense?
rules:
paths:
platform:
/infra/: '@acme/platform @acme/security'
'*.tf': '@acme/platform @acme/security'
/.github/workflows/: '@acme/platform @acme/security'
/.github/coance.yml: '@acme/security @acme/leads'
/.github/CODEOWNERS: '@acme/security @acme/leads'
standard: ['/src/']
Database migrations
A migration runs once against production data and is often hard to undo. It deserves a
reviewer who knows the data and the deploy order, not just a look at the SQL.
Here migrations need two approvals from the data team and backend leads, while the rest of
/db/ and /src/ gets an ordinary review.
# .github/coance.yml: database migrations
levels:
migration:
approvals: 2
self_review: false
description: |
A migration runs once against production data and is
hard to undo. Check it locks no large table for
long, keeps old and new code working during the
deploy, and never drops data without a backup.
standard:
description: Read the file. Does the change make sense?
rules:
paths:
migration:
/db/migrations/: '@acme/data @acme/backend-leads'
standard: ['/src/', '/db/']
Generated and vendored code
Generated clients, serializers and vendored libraries can make a pull request look far
larger than the change a person made. Files marked linguist-generated or
linguist-vendored in .gitattributes, the attributes GitHub
already uses to collapse them in diffs, are excluded from coance’s requirements and
metrics, whatever rule matches them. Your repository’s usual review process still applies
to them.
To govern what generates them, put the generator and its inputs at the right level.
# .gitattributes
*.g.dart linguist-generated=true
/api/generated/** linguist-generated=true
/third_party/** linguist-vendored=true
# .github/coance.yml: generated code is excluded from coance
levels:
review:
description: Read the file. Does the change make sense?
rules:
paths:
review: ['/lib/', '/api/']
Regulatory context
Few rules say “review every line”. What laws and standards in regulated sectors ask for is
closer to this: decide where the risk is, put controls on it, and be able to show they
worked.
-
Payments. PCI DSS requires custom software to be reviewed before release,
and manual reviews to be done by someone other than the author.
[1]
-
Secure development. NIST SP 800-218 asks organizations to decide where
code review or code analysis is used and to perform it against their secure coding
standards.
[2]
-
Financial entities in the EU. DORA requires documented, risk-based ICT
change management, so that changes to software are recorded, tested, assessed, approved,
implemented and verified in a controlled manner.
[5]
-
Essential and important entities in the EU. NIS2 requires risk-management
measures that include security in the development and maintenance of network and
information systems.
[6]
-
Personal data. The GDPR requires security measures appropriate to the
risk, and a process for regularly testing and evaluating them.
[4]
-
Health data in the US. The HIPAA Security Rule requires risk analysis and
risk management for electronic protected health information.
[3]
-
Data security enforcement. The FTC has brought actions over data security
it considered careless, describing concrete engineering practices: an access key posted on
a code-sharing website (Uber), and shared database logins and personal data stored in
plain text (Chegg).
[7]
[8]
-
Audits. SOC 2 reports are assurance reports on a service organization’s
controls relevant to security, availability, processing integrity, confidentiality or
privacy.
[9]
What coance records
For every file that needs review, coance records who approved it, when, at which commit, and
whether by resolving the file’s thread or replying /approve. A later commit
that changes the file clears its approvals, so an approval always covers the file as it is
now. On the pull request, the summary comment lists each file’s level, approvals and
approvers, and the coance check passes only when every file has enough of them.
That is the record a team can point to when it explains how its review policy works, to an
auditor, a customer’s security review or itself after an incident.