The Upstream Decision-Rights Reference: Merge, Gate, Veto, or Admit
For any upstream project, name who can admit, route, gate, merge, or veto your patch, which company employs each of them, and who to approach first.
Key takeaways
- A GitHub CODEOWNERS entry is only a review request unless a repository admin has turned on required code-owner approval, so a listed owner is not automatically a veto holder.
- On GitLab, a CODEOWNERS entry with no accessible owners is invalid and auto-approved, unless the protected branch requires code owner approval. So a broken file can leave the gate open on GitLab where GitHub would simply skip the reviewer.
- Kubernetes treats an OWNERS entry as inactive below 10 Devstats-recorded contributions in a year, and emeritus approvers can no longer approve code, so strike both before choosing who to approach.
- A VOUCHED.td list grants admission only: Ghostty auto-closes PRs from unvouched people, but a list of 250+ vouched contributors says nothing about who merges.
- In Refolk's index, only 124 US profiles carry 'open source maintainer' in the headline, so start from the repository's handles and work outward to employers, not the other way round.
- Employer data is copied between systems and drifts: one CNCF maintainer found the generated foundation CSV still showed an old affiliation a year after fixing it in gitdm, so date every source.
Before your team writes a patch or asks for a feature in a project it depends on, you need to know two things: which named people can admit, approve, block, or quietly ignore the work, and which companies employ them. This reference is for engineering managers, technical founders, developer-relations leads, and technical sourcers who do that lookup from outside the project. For each governance artifact you will meet, it says what decision right the artifact really grants, how it goes stale or misleads, and what to check next. It then gives a procedure that ends with one name to approach.
Which decision rights does an outsider need to separate?
An outsider needs to separate five rights: admission, routing, gating, merging, and veto. Most governance artifacts grant only one of them. Teams that read a file as if it granted all five end up sending a careful PR to someone who cannot act on it.
The terms used throughout this reference:
- Admission - permission to open a pull request that will not be closed automatically. Ghostty's vouch system is the clearest example: if you are not vouched, any PR you open is closed automatically.
- Routing - being the person a forge or script asks for review. Unenforced GitHub CODEOWNERS and the Linux kernel MAINTAINERS file mostly do this.
- Gate - an approval the merge requires mechanically. Examples: a required code-owner review on GitHub, an OWNERS approver's /approve in Kubernetes, or a protected-branch code-owner rule on GitLab.
- Merge - write access plus a visible record of actually merging on your path. This is evidence, not a listing.
- Veto - the right to stop a change on governance grounds. An Apache PMC member's -1 on a code modification is the textbook case.
Five layers of upstream authority
- AdmissionVOUCHED.td, auto-close bots, CONTRIBUTING rules
- RoutingUnenforced CODEOWNERS, kernel MAINTAINERS, OWNERS reviewers
- GateRequired code-owner review, OWNERS approvers, GitLab protected-branch rules
- MergeWrite access plus a record of merging on your path
- VetoApache PMC -1 on a code modification, with technical justification
The layers matter because they do not travel together. Someone with veto rights may never review your path. Someone who gates your path may have no say over admission. The bot that admits you tells you nothing about who merges. The rest of this guide is a lookup table for which layer each artifact actually sits in.
What does each governance artifact actually grant?
Each artifact grants one specific right under specific conditions, and each goes stale in a known way. The table is the short form. The subsections below give, for each artifact, what it proves, when it misleads, and what to check next.
| Artifact | Grants | Goes stale when |
|---|---|---|
| CODEOWNERS (GitHub) | Review request, or a gate only if required | Team loses write access |
| CODEOWNERS (GitLab) | Gate on protected branch | Owner not a direct member, so the rule auto-approves |
| OWNERS approvers | /approve | Person moves to emeritus |
| Kernel MAINTAINERS S: | Routing plus intent | Marked Odd Fixes or Orphan |
| VOUCHED.td | Permission to open PRs | Not tied to who merges |
CODEOWNERS on GitHub
- Proves: someone with repository access said these handles are responsible for these paths. GitHub looks in
.github/, then the repository root, thendocs/, and uses the first file it finds. - Grants: an automatic review request. It becomes a gate only if someone with admin or owner permissions has required code-owner approval before merge. When a line lists several owners, approval from any one of them is enough.
- Misleads when: a listed team has lost write access or is not visible. GitHub requires a team owner to be visible and to have write permission, even if every individual member already has write. It also misleads when enforcement is off and the file is read as a veto list.
- Check next: merged PRs on your path. If some merged without an owner's approval, the file is routing, not a gate.
- Fork detail: for PRs from forks, GitHub uses the CODEOWNERS file from the target branch in the upstream repository. Read the file on the branch you will target.
CODEOWNERS on GitLab
- Grants: a real gate when the protected branch has Require code owner approval enabled.
- Misleads when: an entry lists no owners, or none of its owners are accessible. GitLab treats that entry as invalid and auto-approves it in merge requests, so a name that looks like a gatekeeper holds nothing. Owners need the Developer, Maintainer, or Owner role. Code Owners cannot inherit members from parent groups, so someone who belongs to the project only through a parent group does not count. With Require code owner approval set on a protected branch, rules with zero owners are still honored.
- Check next: whether each listed owner is a direct member of the project with a qualifying role. Also note that approval rules update only when the merge request is created. Changes to the file after you open the MR will not reshape your approvers.
Kubernetes-style OWNERS and OWNERS_ALIASES
- Proves: per-directory lists of
approvers,reviewers, andemeritus_approvers, with OWNERS_ALIASES expanding named groups. - Grants: approvers can /approve. Acceptance needs at least one approver in addition to the assigned reviewers. Reviewers route and review but do not gate alone.
- Misleads when: a name has moved to
emeritus_approvers(emeritus approvers can no longer approve code), or the person is inactive. Kubernetes defines an inactive OWNERS entry as one with fewer than 10 Devstats-recorded contributions in the past year. - Check next: the nearest OWNERS file, walking up from your path, then each approver's Devstats activity.
- Why reviewer listings still mean something: becoming a Kubernetes reviewer takes at least 3 months as a member, primary reviewer on at least 5 PRs, and at least 20 substantial PRs reviewed or merged. A reviewer cannot approve alone, but the listing reflects real past work on that code.
Linux kernel MAINTAINERS
- Grants: routing plus a statement of intent. You CC the maintainers and mailing lists that
scripts/get_maintainer.plgenerates for your patch. - The S: field: values include Supported ("Someone is actually paid to look after this."), Maintained, Odd Fixes, Orphan, and Obsolete.
- Misleads when: an entry is marked Odd Fixes or Orphan. A name is listed, but nobody has committed to act.
- Check next: the S: status for the exact file pattern you touch. For Supported entries, find the employer, because the status says a company is paying for the work.
CNCF MAINTAINERS files and .project/maintainers.yaml
- Proves: the CNCF template asks each project to record every maintainer's current employer affiliation and any project areas they lead. The foundation roster is moving to
.project/maintainers.yaml. In the generated CSV, name and affiliation come from the person's LFID profile, the Linux Foundation ID account. The legacy project-maintainers.csv is closed to new projects, and PRs that try to add them are auto-closed. - Grants: a seat in project governance. It does not necessarily grant code approval, because the template notes that a MAINTAINERS file may list a few people who are not code approvers.
- Misleads when: the affiliation is out of date, or the handles in the code files do not match the roster. TUF's onboarding bot reported handles found in the org's CODEOWNERS, OWNERS, and MAINTAINERS files that were not yet in the CNCF foundation maintainers CSV.
- Check next: cross-reference every name against the OWNERS approvers or CODEOWNERS entries for your path.
VOUCHED.td and auto-close bots
- Grants: admission only. Ghostty keeps its list at
.github/VOUCHED.tdand auto-closes PRs from anyone not on it. The model was merged in PR #10559, and the tooling is mitchellh/vouch, written by Mitchell Hashimoto. A third-party write-up reports a vouch list of 250+ contributors and about 150 repositories carrying VOUCHED.td. Treat both numbers as a snapshot and re-check them. - Misleads when: it is read as a maintainer list. Vouches are added by a bot after a maintainer comments.
- Check next: who triggered the vouch bot. In PR #14794, for example, @jcollie did. The maintainers who trigger vouches are the people worth knowing. Vouch Explorer MCP shows who has been vouched or denounced across GitHub projects.
Merge and review history
- Grants: nothing. It is evidence, and the only artifact that shows who actually acts.
- Limit: no source I found documents a standard method for measuring it, and how often actual mergers differ from listed names is not established publicly. CNCF names the mismatch as an anti-pattern: CODEOWNERS, branch protection rules, or repository permissions that do not match the roles described in governance documents.
- Check next: the employers of the people who merge, which the next sections cover.
How do GitHub and GitLab differ when CODEOWNERS is broken?
GitHub and GitLab fail in opposite directions. GitHub does not assign an owner it cannot resolve, so the review request never goes out. GitLab treats an entry with no accessible owners as invalid and auto-approves it, unless the protected branch requires code owner approval. The same misconfigured file can mean "no reviewer" on one forge and "open gate" on the other.
| Question | GitHub | GitLab |
|---|---|---|
| Is it a gate? | Only if admins require code-owner approval | Yes, on protected branches with the setting on |
| Unresolvable owner | Not assigned (secondary source) | Entry invalid, auto-approved |
| Who qualifies | Teams: visible, with write access | Developer, Maintainer, or Owner role, direct member |
| Which file applies | Upstream target branch's file, even for forks | Rules fixed when the MR is created |
| Empty file or memberless team | Not established publicly | Entry with no owners is invalid |
Two gaps are worth knowing. First, GitHub's documentation and its linter have disagreed about whether individual owners need read or write access (tracked in GitHub docs issue #18984). Second, what GitHub does with an empty CODEOWNERS file, or with a team that exists but has no members, is not documented in any source I found. The local check for both is the same: open a recent merged PR on your path and see whether an owner review was requested and recorded.
How do you resolve the employer behind each maintainer?
Pull the employer from at least two dated sources and keep the dates in your notes. The common sources copy from each other and drift independently: the LFID profile, cncf/gitdm, the MAINTAINERS affiliation column, commit email domains, and public profile fields. The newest dated source wins, and a disagreement is a question to ask, not a gap to fill by guessing.
The sources, and what each one is:
- LFID profile. For CNCF projects, the generated maintainer roster takes both name and affiliation from here.
- cncf/gitdm. CNCF's affiliation data, updated through the Change Affiliation process.
- The project's MAINTAINERS file. It often has an affiliation column, filled in by the project.
- Commit email domains. A strong hint, but a corporate domain only shows where the person worked when they made that commit.
- Public profile fields. Current title and employer as the person states them.
Affiliation drift is documented. In cncf/automation issue #745, a maintainer reported that the generated .project CSV showed "an ancient affiliation". They had already fixed the old affiliation in gitdm a year earlier. The CSV reads from LFID, not gitdm, so the fix in one system never reached the other. How often these sources disagree across projects is not established publicly. A secondary source reports that incubating projects must keep affiliations updated within 30 days, but I could not confirm that in the TOC text itself, so do not rely on it.
Why profile-first searches miss most maintainers
Searching profiles for the word "maintainer" finds very few of the people who hold rights, and the ones it finds are scattered across employers.
| Country | Matching profiles | Most-repeated employer (sample of 25) |
|---|---|---|
| United States | 124 | None above 1 |
| Germany | 47 | Cargoboard (2) |
| US:DE ratio | 2.64x (derived) | - |
The Linux kernel's MAINTAINERS file alone names far more people than these self-labelled totals, although I have not verified an exact count. The practical rule follows: start from the handles in the repository and work outward to profiles. Do not start from profiles and hope they lead back to the repository.
Where maintainer employers cluster
When you search by project instead of by generic title, employer concentration starts to show.
| Keyword | Profiles | Top employers (sample of 25) | Share at top 5 (derived) |
|---|---|---|---|
| kubernetes maintainer | 133 | Broadcom 4, Google 2, Harness 2 | 10/25 = 40% |
| linux kernel maintainer | 50 | Intel 3, Qualcomm 3, Linaro/AMD/Oracle 2 each | 12/25 = 48% |
The kernel clustering fits the meaning of the S: field: a Supported entry says someone is paid to look after the code, and chip vendors pay for their drivers. Geography differs too. Indian locations make up 11 of the 25 in the Kubernetes sample, led by Bengaluru, while the kernel sample's most repeated cities are Warsaw and Antibes with 2 each. These are samples of 25. Use them to set expectations, not to measure a particular project.
Matching a list of handles to current employers is where Refolk removes most of the manual work. You ask in plain English for the people in a specific OWNERS file at named companies, and you get back current profiles drawn from GitHub, LinkedIn, and the open web. Then compare those against the dated foundation records instead of trusting either source alone.
What do foundation rules say about company control?
Foundations limit company control in different ways. At Apache, veto is an individual right that must come with a technical justification. CNCF requires incubating projects to have maintainers from at least two organizations and to survive the withdrawal of any one of them. Neither rule tells you who merges on your path, but both tell you whether a single employer can block your change.
Apache
- PMC members may veto technical decisions, such as proposed patches, but they must give a technical justification.
- PMC members act as individuals, not as representatives of their employers.
- On code modifications, a -1 vote is a veto and kills the proposal until every vetoer withdraws their -1.
- Releases may not be vetoed.
For an outsider, this means mapping the individual PMC members who care about your area. Counting employers is less useful, because a veto belongs to a person and needs a technical reason you can answer.
CNCF
- Incubation requires maintainers from at least 2 organizations, org-balanced voting or representation limits, and a project that can survive the withdrawal of any single organization.
- CNCF also says a single company holding the majority of seats is common and not inherently a problem.
- On outcomes, CNCF reports that projects with maintainers from multiple organizations at sandbox entry graduate at 2.07x the rate of single-org projects (59.1% vs 28.6%).
Upstreaming to a vendor-controlled project
When you upstream a feature to a vendor-controlled open source project, the charter is the ceiling and merge history is the floor. A charter can show multi-org representation while the merges on your path come from one company. CNCF names this pattern too: decision-making authority stays concentrated in a single organization. If every active merger on your path shares an employer, assume that employer's roadmap decides your change. Frame the proposal so it fits that roadmap, and find out whether a seat cap or org-balanced vote gives you anywhere to appeal.
Procedure: from upstream repository to one person to approach
The procedure takes you from a repository URL to a single named, active person with write access, approached through the project's front door. Sources do not agree on an order. I assembled this sequence from the platform documentation, and it takes about three and a half hours for one path in one project.
Upstream decision-rights lookup
- Check who may contribute at allRead CONTRIBUTING and look for .github/VOUCHED.td, auto-close bots, or a stated front door. About 15 minutes; done when you know whether a cold PR would be auto-closed.
- Map your path to its listed ownersUse CODEOWNERS, the nearest OWNERS file, or the kernel MAINTAINERS entries that scripts/get_maintainer.pl generates. About 30 minutes; done when you have handles per path, each tied to a line.
- Strike names that cannot actRemove emeritus approvers, kernel entries marked Odd Fixes or Orphan, names under the activity threshold, and teams without write access or a qualifying role. About 20 minutes.
- Read 90 to 180 days of merge historyList who approved and who merged PRs on your path, including people missing from the files. About an hour; no source documents a standard method, so record which PRs you read.
- Resolve and date each employerCheck the LFID-fed CNCF roster, gitdm, the MAINTAINERS affiliation column, commit domains, and profile fields. About 30 minutes; done when each person has two dated sources.
- Read the governance charterLook for steering seat caps, org-balanced voting, minimum-organization rules, and veto rules such as the Apache PMC -1. About 20 minutes.
- Choose one person and use the front doorPick someone listed, active, with write access, who has merged on your path, then approach through a vouch request or an issue as the project asks.
Steps 2 and 4 give you two lists: who is named, and who acts. Plot each person against both before choosing.
Listed authority versus observed merging
Keep the output in one place. One row per person, with every claim sourced and dated, makes the final choice easy to defend.
Project and forge (GitHub or GitLab): Path touched: Admission rule (open / vouch required / issue first / unknown): Code-owner approval enforced (yes / no / unknown): Charter veto or org-cap rules: handle | artifact and line | right (admit / route / gate / merge / veto) | status (active / emeritus / Odd Fixes / Orphan) | write access confirmed | merges on path, 90-180 days | employer | source 1 + date | source 2 + date | role in approach (first / CC / none)
Fill one row per handle for the exact path you will touch; leave a cell blank rather than guess, and date every source.
How this goes wrong: failure modes and false positives
Most failed upstream approaches start from one of eight misreadings. Each looks like evidence of authority, and each has a check you can run in a few minutes. Run the checks before contacting anyone, because a cold PR to the wrong person usually gets no reply at all.
- Reading CODEOWNERS as veto power. Without the setting that requires code-owner review, GitHub CODEOWNERS only requests reviews. The false positive is a listed owner who never needs to sign off. Check: find merged PRs on the path that had no owner approval. If they exist, the file is routing.
- A GitLab owner that looks like a gate but approves itself. If no listed owner is accessible, GitLab treats the entry as invalid and auto-approves it, so the name holds no real gate. Check: confirm each owner is a direct member of the project with Developer, Maintainer, or Owner role. Membership inherited from a parent group does not count.
- Treating emeritus or inactive names as current. Emeritus approvers can no longer approve code, and kernel entries marked Odd Fixes or Orphan show nobody committed to act. Check: read
emeritus_approvers, the kernel S: status, and the Kubernetes threshold of fewer than 10 Devstats contributions a year. - Affiliation drift. Issue #745 shows the generated CNCF CSV out of date for about a year after the person corrected gitdm, because the CSV reads from LFID. Check: compare the dates on each source. Never treat an undated affiliation as current.
- MAINTAINERS lists that include non-approvers. The CNCF template allows people who are not code approvers, such as community managers, in the MAINTAINERS file. Check: cross-reference against OWNERS approvers or CODEOWNERS for your path.
- Cosmetic diversity. A charter shows several organizations while decision-making authority stays concentrated in one. Check: look at the employers of the people who actually merge, not the employers of the people with titles.
- Mistaking vouched for empowered. A vouch only admits a person to contribute. A list of 250+ vouched contributors says nothing about who merges. Check: see who triggered the vouch bot, as @jcollie did in PR #14794. Those maintainers are the people to know.
- Headline searches that undercount maintainers. Only 124 US profiles in Refolk's index carry "open source maintainer" in the headline, and they are spread thinly across employers. Check: start from the handles in the repository and resolve outward. Asking Refolk for "approvers in this OWNERS file at this employer" works from the repository's side.
A listed name is a claim about authority. A merge on your path is evidence of it.
One limit applies to this whole section. These failure modes come from platform documentation and individual documented cases, not from measured rates. CNCF's share of inactive listed maintainers is not established publicly, and neither is any project-wide figure for mismatch between listed owners and actual mergers. When you find a mismatch, record it as a finding about that project. Do not treat it as confirmation of a general rate.
Keeping the map current and making first contact
A decision-rights map goes stale whenever an approver moves to emeritus, a kernel S: status changes, a team loses write access, or someone changes employer. Re-run steps 3 to 5 before every approach, not only the first one. On GitLab, also remember that approval rules are fixed when the merge request is created, so read the file again right before you open one.
Re-check triggers worth watching on any project you depend on:
- Changes to CODEOWNERS, OWNERS, OWNERS_ALIASES, or MAINTAINERS on the paths you carry patches against.
- Names moving into
emeritus_approvers, or kernel entries moving to Odd Fixes or Orphan. - Edits to CONTRIBUTING, or a new VOUCHED.td file, which can change admission overnight.
- Changes to the foundation roster or the project's
.project/maintainers.yaml. - Employer changes among your confirmed gatekeepers. A plain-English Refolk query for the same approvers at the same employers shows who has moved since the last run.
When you make contact, go through the front door the project names. That usually means an issue or a vouch request, not a cold PR. Lead with the evidence that you did the lookup.
Hi [handle], I'm [name] at [company]. We run [project] for [one-line use case] and carry a local patch to [path] that fixes [one-line problem]. Before opening a PR I wanted to check direction with you, since you approve changes under [path] and merged [link to recent PR] there. What the change does: [two sentences] What it does not touch: [paths or behaviour left alone] What we can commit to: [tests, docs, follow-up maintenance] If this belongs with someone else, or should start as an issue first, I'm glad to follow whatever process the project prefers. Thanks, [name]
Post it through the project's stated front door (issue, discussion, or vouch request); replace bracketed text and cut any line you cannot back with a link.
Before you contact anyone upstream
- The forge is identified and code-owner enforcement is confirmed on, off, or marked unknown.
- The admission rule is known: open, vouch required, issue first, or unknown.
- Every shortlisted handle maps to a specific line in CODEOWNERS, OWNERS, or MAINTAINERS for the exact path.
- No emeritus approver, Odd Fixes or Orphan entry, or sub-threshold inactive name is on the first-contact list.
- Team owners are confirmed visible with write access on GitHub, or owners are confirmed as direct members with Developer role or above on GitLab.
- At least one merged PR on the path shows the chosen person approving or merging.
- Each person's employer has two dated sources, and any disagreement is written down rather than resolved by guess.
- The charter has been read for veto rules, seat caps, and minimum-organization requirements.
- The vouched list has not been used as a maintainer list anywhere in the worksheet.
Questions practitioners ask
Does being listed in CODEOWNERS mean someone can block my pull request?
Only if enforcement is on. On GitHub, a CODEOWNERS entry requests reviews automatically, and it becomes a merge gate only when someone with admin or owner permissions requires code-owner approval. Even then, when a line lists several owners, approval from any one of them is enough. On GitLab the gate applies on protected branches with Require code owner approval enabled. Check merged PRs on the path: if some merged without an owner's approval, the file is routing, not a gate.
What is the difference between a CODEOWNERS file and a MAINTAINERS file?
CODEOWNERS is read by the forge and maps paths to handles for review requests or required approval. MAINTAINERS is a document for people, and its meaning depends on the project. The kernel's file routes patches and states support status. A CNCF-style file lists governance members and their employers, and it may include people who are not code approvers, such as community managers. Cross-reference MAINTAINERS against CODEOWNERS or OWNERS approvers before treating a name as a gatekeeper.
How do I find which company employs an open source maintainer?
Check several sources and date each one. For CNCF projects, the generated maintainer roster takes affiliation from the person's LFID profile. cncf/gitdm holds separate affiliation data, the MAINTAINERS file may have an affiliation column, and commit email domains and public profiles add more evidence. These sources copy from each other and drift, so a fix in one does not fix the others. Use the newest dated source and mark disagreements rather than guessing.
What is a vouch system and how does it affect external contributors?
A vouch system admits only listed contributors to open pull requests. In Ghostty, PRs from anyone not in .github/VOUCHED.td are automatically closed, and vouches are added by a bot after a maintainer comments. A vouch grants admission, not approval, so the vouched list is not a maintainer list. Read CONTRIBUTING for how the project wants you to ask. The maintainers who trigger the vouch bot are the people worth knowing.
Can a single company veto my patch in an Apache project?
Not as a company. At Apache, PMC members may veto technical decisions such as proposed patches, but they must give a technical justification, and they act as individuals, not as representatives of their employers. A -1 on a code modification kills the proposal until every vetoer withdraws it. Releases may not be vetoed. The practical question is which individual PMC members care about your path, not which employer they share.
How do I get a patch accepted upstream in a vendor-controlled project?
Find the people who actually merge on your path, resolve their employers, and read the charter for organization caps. CNCF says a single company holding most seats is common and not a problem in itself. Incubating projects still need maintainers from at least two organizations and must survive any one organization leaving. Approach an active approver through the front door, and if all mergers share one employer, frame the change around that employer's stated roadmap.
Try it on the search you came here for
Stop building boolean strings. Just describe the person.
Type one sentence. I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web as it is right now, and hand back a ranked list with the reason next to every name.
01Describe them
One plain sentence. Role, city, stack, stage, whatever matters to you.
02I read the web live
GitHub, public LinkedIn and Crunchbase records, the open web. Not a database that went stale last quarter.
03You read the shortlist
Ranked, with the reasoning under every name. Open a profile, ask a follow-up, narrow it down.
- Staff backend engineers in NYC who shipped Rust in production
- Series A fintechs in SF under 50 people, growing headcount this year
- Maintainers of fast-growing Rust web frameworks on GitHub
- No boolean, no filters, no seat to buy. One box.
- Read at search time, so a profile updated yesterday counts today.
- Every step visible as it runs, every name with its reason.
500 free credits on sign-up. No card, no demo call. See real searches.