As the Bytecode Alliance (BA) grows, we need more formalized ways of communicating about and reaching consensus on major changes to core projects. This document proposes to adapt ideas from Rust’s RFC and MCP processes to the Bytecode Alliance context.
There are two primary motivations for creating an RFC process for the Bytecode Alliance:
-
Coordination with stakeholders. Core BA projects have a growing set of stakeholders using and contributing to foundational projects, often from varied organizations or teams. An RFC process makes it easier to communicate possible major changes that stakeholders may care about, and gives them a chance to weigh in.
-
Coordination within a project. As the BA grows, we hope and expect that projects will be actively developed by multiple organizations, rather than just by a “home” organization. While day-to-day activity can be handled through issues, pull requests, and regular meetings, having a dedicated RFC venue makes it easier to separate out discussions with far-ranging consequences that all project developers may have an interest in.
The design of this RFC process draws ideas from Rust’s Request for Comment (RFC) and Major Change Proposal (MCP) processes, adapting to the BA and trying to keep things lightweight.
Each core BA project has a formal set of stakeholders. These are individuals, organized into groups by project and/or member organization. Stakeholders are not necessarily members of the BA. Formally, stakeholder review is required for RFCs to be accepted, and stakeholders can likewise block the process from proceeding.
The process for determining core BA projects and their stakeholder set will ultimately be defined by the Technical Steering Committee, once it is in place. Until then, the current BA Steering Committee will be responsible for creating a provisional stakeholder arrangement, as well as deciding whether to accept this RFC.
- We have a dedicated bytecodealliance/rfcs repo that houses all RFCs for core BA projects, much like Rust’s rfcs repo that is shared between all Rust teams.
- The rfcs repo will be structured similarly to the one in Rust:
- New RFCs are submitted via pull request, and both technical and process discussion happens via the comment thread.
- The RFC is tagged with project labels, corresponding to the BA project(s) it targets. This tagging informs tooling about the relevant stakeholder set.
- When discussion has stabilized around the main points of contention, any stakeholder can make a motion to finalize, using a special comment syntax understood by tooling. This motion comes with a disposition: merge or close.
- N.B.: an RFC may be closed for reasons of timing or other project management concerns. The project team should make clear under what conditions, if any, a similar RFC would be reconsidered.
- In response to the motion to finalize, a bot will post a special comment with a stakeholder checklist.
- This list includes the GitHub handle for each individual stakeholder, organized into stakeholder groups.
- The individual who filed the motion to finalize is automatically checked off.
- Once any stakeholder from a different group has signed off, the RFC will move into a 10 calendar day final comment period (FCP), long enough to ensure that other stakeholders have at least a full business week to respond.
- During FCP, any stakeholder can raise an objection using a syntax understood by the bot. Doing so aborts FCP and labels the RFC as
blocked-by-stakeholder
until the objection is formally resolved (again using a special comment syntax). - Finally, the RFC is automatically merged/close if either:
- The FCP elapses without any objections.
- A stakeholder from each group has signed off, short-cutting the waiting period.
In general, an RFC is a single markdown file with a number of required sections. Many RFCs should begin as drafts, to encourage early discussion about the approach and only a sketch of a proposal. Full RFCs contain a fleshed-out proposal and more discussion around rationale and alternatives.
Template files for both draft and full RFCs will be available in the repository root.
It is encouraged to use the RFC process to discuss ideas early in the design phase, before a full proposal is ready. Such RFCs should be marked as a draft PR, and contain a markdown file with the following sections:
- Motivation. What problem are you ultimately hoping to solve?
- Proposal sketch. At least a short sketch of a possible approach. Beginning discussion without any proposal tends to be unproductive.
- Open questions. This section is especially important for draft RFCs: it’s where you highlight the key issues you are hoping that discussion will address.
RFCs cannot be merged in draft form. Before any motion to merge, the draft should be revised to include all required RFC sections, and the PR should be changed to a standard GitHub PR.
Full RFCs are markdown files containing the following sections (which will be laid out in a template file):
- Summary. A ~one paragraph overview of the RFC.
- Motivation. What problem does the RFC solve?
- Proposal. The meat of the RFC.
- Rationale and alternatives. A discussion of tradeoffs: why was the proposal chosen, rather than alternatives?
- Open questions. Often an RFC is initially created with a broad proposal but some gaps that need community input to fill in.
When should you open an RFC, rather than just writing code and opening a traditional PR?
- When the work involves changes that will significantly affect stakeholders or project contributors. Each project may provide more specific guidance. Examples include:
- Major architectural changes
- Major new features
- Simple changes that have significant downstream impact
- Changes that could affect guarantees or level of support, e.g. removing or adding support for a target platform
- Changes that could affect mission alignment, e.g. by changing properties of the security model
- When the work is substantial and you want to get early feedback on your approach.
The proposal above assumes the presence of tooling to manage the GitHub workflow around RFCs. The intent is to use Rust's rfcbot. It will need some modifications to support the proposed workflow; these can hopefully land upstream so we can share the tool with the Rust community, but otherwise the BA will maintain its own fork.
This RFC, and any future RFCs targeting similar process-related questions, will go before the Bytecode Alliance Steering Committee (eventually replaced by the Technical Steering Committee, once that group has been formed).
This proposal tries to strike a good balance between being able to move quickly, and making sure stakeholder consent is represented.
The core thinking is that getting active signoff from at least one person from a different stakeholder group, together with the original motion to finalize, is sufficient evidence that an RFC has received external vetting. The additional 10 day period gives all stakeholders the opportunity to review the proposal; if there are any concerns, or even just a desire to take more time to review, any stakeholder can file an objection. And on the other hand, proposals can move even more quickly with signoff from each group.
In total, this setup allows proposals to move more quickly than either Rust’s RFC or MCP processes, due to the less stringent review requirements and ability to end FCP with enough signoff. At the same time, the default FCP waiting period and objection facility should provide stakeholders with enough notice and tools to slow things down when needed.
Motion through the FCP process is gated at the stakeholder group level, but the actual check-off process is tied to individuals. There are reasons for both:
- Gated by group. The goal of the signoff process is to provide a “stakeholder consent” check before finalizing an RFC. We view a signoff from any member of an organization or project as a fair representation of that organization or projects’s interests, and expect individuals to act accordingly.
- Individual sign-off. Despite being gated by groups, we call out individuals by GitHub handle for review. Doing so helps avoid diffusion of responsibility: if we instead merely had a checkbox per organization, it could easily create a situation where no particular individual felt “on duty” to review. In addition, tracking which individual approved the review provides an important process record in case that individual fails to represent their group's interests.
The Rust RFC process has successfully governed the development of the language from before 1.0, and covers an enormous range of subprojects, including the language design, tooling, the compiler, documentation, and even the Rust web site. It is a proven model and variations of the process have been adopted by several other large projects. Its workflow is simple and fits entirely within GitHub, which is already the central point of coordination within the BA. And given the central role of Rust within the BA, it’s a model that members are likely to already be familiar with.
That said, a major difference in design is the notion of stakeholders and how they impact the decision-making process. Here we borrow some thinking from Rust’s lightweight MCP process, allowing a decision to go forward after getting buy-in from just one stakeholder within a different group -- but still requiring a waiting period to do so. A further innovation is that getting sign off from within all groups immediately concludes FCP. That was not possible in the Rust community, where the set of stakeholders is unbounded.
A common complaint about the Rust RFC process is that it is, in some ways, a victim of its own success: RFC comment threads can quickly become overwhelming. While this may eventually become an issue for the BA as well, we have some additional recourse in this proposal: we have a clear stakeholder model which will allow us to prioritize concerns from stakeholders, and take action when individuals who are not formal stakeholders overwhelm comment threads.
We could instead follow Rust’s MCP model and use Zulip streams for RFC discussion. However, that introduces a more complex workflow (spanning multiple systems) and leaves a less permanent and less accessible record of discussion.
- As written, an individual stakeholder can block acceptance of an RFC indefinitely. In the Rust community, such an arrangement has sometimes caused problems, leading to a secondary process that kicks in after a waiting period, and requires an additional stakeholder to approve continued blocking. Should we consider building in such a mechanism now, or add it to the process only if it becomes necessary later?