The contribution contract: who owns a feature that a user of the platform built
Platforms that refuse contributions become queues their users route around. Platforms that accept them without an ownership agreement accumulate features designed for one team and supported forever by another. The contract states who owns the interface, who owns the implementation, and what acceptance requires.
TL;DR: Write down what happens after the merge, because that is the part both sides skip. The platform owns the interface and the review, the contributing team owns the implementation until acceptance, and acceptance requires tests, documentation, an operational cost estimate and a named maintainer. Without the last one, a contribution is a transfer of permanent cost.
The failure this concept exists to prevent
A product team needs a capability. The platform roadmap puts it two quarters away. They offer to build it, the platform team says yes because saying yes feels collaborative, and three weeks later a large pull request arrives.
It merges. The feature works for the team that wrote it. Eight months on, that team has reorganised, the one engineer who understood the code has moved, and the platform team is paged for a component they did not design, cannot change with confidence, and never agreed to operate.
Nothing in that sequence was obviously a mistake at the time, which is why it keeps happening.
The two failure modes are symmetric
Refusing contributions keeps the platform coherent and makes it a queue. Teams with deadlines do not wait: they fork the component, wrap it, or build beside it, and the platform now competes with internal alternatives it cannot see and did not approve. The coherence was preserved on paper.
Accepting everything keeps teams happy and grows surface area faster than the team that supports it. Each contribution is designed by somebody optimising for one workload, and the sum is a platform with four ways to do several things, all of which must keep working.
The contract exists because both of those are worse than the middle, and the middle has to be written down to survive a staffing change.
What the contract has to say
Four clauses carry the weight.
The interface is agreed before implementation, in a short design note. This is the clause that protects the relationship: a team that writes three weeks of code and then has the shape rejected does not contribute again, and tells its neighbours.
Acceptance applies the platform's own standard, not a lower one for guests. Tests at the level the platform requires of itself, documentation in the same form, and an operational cost estimate in expected hours a month.
A maintainer is named, with a period. This is the clause people argue about and the only one that prevents the failure above.
Ownership is decided explicitly at acceptance, with two legitimate outcomes. The platform takes it fully including the pager, which should be the default for anything in the main path. Or it stays with the contributing team behind a documented extension point. The undefined middle, where the platform answers for code it cannot change, is the arrangement to refuse.
The cost that gets ignored
A merged feature is not free to the platform team. Each capability carries recurring work: upgrades, security patches, support questions, and a share of every future refactor.
Take an estimate of 4 hours a month of operational load for a modest capability:
4 x 12 = 48 hours a year, indefinitely
Accept six such contributions in a year and the platform team has taken on 6 x 48 = 288 hours, about 7 working weeks annually, without anyone deciding to spend it. That is why the operational estimate belongs in the acceptance checklist rather than in a retrospective.
The 4 hours is illustrative and the real figure varies by an order of magnitude between a config template and a stateful component. What does not vary is the direction: the estimate is never zero, and a contribution process that does not ask for it is accumulating a commitment nobody has priced.
Self-check
A team contributes a caching layer that solves a real problem for three services. It passes tests and review. They name a maintainer for six months. Eleven months later the maintainer has left the company and the component has had two incidents. Say what the contract got right and wrong, and what you do now. Work both through before reading on.
The contract worked as far as it went. The design was reviewed, the bar was applied, and a maintainer was named, which is more than most platforms require. What it lacked was anything that happens at the end of the six months, so the maintainer clause expired into nobody, and the expiry was not an event anyone was told about.
That is the fix for next time: a maintainer period needs a review date that fires, with three outcomes available. The platform adopts it fully and records the operational cost, the contributing team renews, or the component is deprecated because nobody will own it. A clause that expires silently is the same as no clause.
For the component in front of you now, the decision is ownership and it cannot be deferred again. If three services still depend on it, the platform adopts it, which means budgeting the operational hours and spending time to understand code it did not write. If the dependents can be migrated to something the platform already supports, deprecating is cheaper and more honest than adopting a component the team does not want.
What the incidents do not tell you is which of those is right. Two incidents in eleven months may indicate a fragile component, or a well-built one doing hard work. Read them before deciding, because adopting a component on the assumption it is bad, or deprecating one that was fine, are both expensive mistakes made from the same missing evidence.
Next: service catalogs and ownership metadata covers making an ownership gap visible before it becomes an incident.