Stable interface policy/Frontend

The stable interface policy for MediaWiki frontend code (CSS, JavaScript and HTML) defines what parts of the software are considered stable and safe for use by other components (gadgets that are following Wikimedia recommendations, mediawiki extensions and skins).. For guidelines on PHP, please see Stable interface policy. The Frontend stable interface policy document is maintained separately from the PHP stable interface policy document, given the audience is different, particularly with its unique requirement to gadget developers. The eventual goal is to move this to Stable interface policy/frontend.

While this documentation is in draft please feel free to dive into the talk page to debate any aspect of this code.

This document applied to MediaWiki developers. It is complemented and supported by a set of recommendations for developers of on-wiki code. Any changes here must be made with consideration to that document.

Terminology

 * See https://datatracker.ietf.org/doc/html/rfc2119 to understand the language used in this policy to Indicate Requirement Levels ("MAY", "MUST", "SHOULD")
 * "Wiki-hosted code" is defined as code that executes on Wikimedia projects, whose source code lives inside a page that is editable on wiki.
 * A "MediaWiki developer" is defined as someone who contributes code to the MediaWiki core code repository or one of its extensions or skins.
 * “Frontend code” is defined as any code that is written in JavaScript and CSS - this includes on-wiki scripts, and code in Wikimedia repositories (extensions, skins and core) unless stated.
 * The “Code search tool” refers to https://codesearch.wmcloud.org/
 * The “Global search” tool refers to https://global-search.toolforge.org/
 * “Caching implications” is used described the situation on Wikimedia production sites where old HTML markup and styles can be mixed with new HTML markup and styles as  we cache HTML for a longer period than JavaScript and CSS assets. Caching implications apply to any page that is cached on the edge layer (typically any page that can be rendered by anonymous users excluding the special namespace). Explaining this in detail is out of scope for the document, but more information on this subject can be found here.

Motivation
This policy is designed to make extensions more robust against changes in MediaWiki core, and provide more freedom for MediaWiki core code to evolve.

The motivation for this policy is two-fold:


 * Offer guarantees to gadget developers and extension developers, providing guidance on what frontend code that they can safely rely upon.
 * Provide guarantees to developers working on MediaWiki core, telling them what aspects of the code they can safely change without having to worry about breaking extensions.

Ecosystem
Despite gadgets and user scripts (which will be referred from now on as wiki-hosted code) being a key component of MediaWiki projects, up until now frontend APIs (e.g. how wiki-hosted code should interact with source control provided code) have been ill-defined leading to misunderstandings between engineers and wiki-hosted code developers when wiki-hosted code breaks. This also leads to code rot, where developers do not feel empowered to make changes as it's unclear how their changes will impact wiki-hosted code developers.

On top of this, when wiki-hosted code breaks it's not clear who can and will fix them.

This document aims to build agreements between Wikimedia staff, volunteer contributors (on Gerrit and Github) and wiki-hosted code developers to lead to a better experience for both parties and build trust and good faith between the two parties.

History

 * [June 2023] Folding feedback from outside wiki into document
 * [May 2023] Targeted MediaWiki.org developers https://www.mediawiki.org/w/index.php?title=MediaWiki:Editpage-code-message
 * [March 2023] Revised format of document
 * [January 2023] Document was separated into User:Jdlrobson/Stable_interface_policy/frontend and Recommendations for gadget developers
 * [May 2022] Emailed engineering-all@wikimedia.org to request feedback
 * [Feb 2022] Emailed wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/message/HLQSR7NCYJFKDBITBYSF2RRQJUEOP6PC/
 * [August 2021] This document began life in User:Jdlrobson/Extension:Gadget/Policy.

Guidelines around HTML markup
HTML markup is not a stable interface (unless explicitly stated) however historically gadget developers have been led to believe this, so we have a responsibility to respect their existing work by over-communicated while this policy is rolled out. Making changes to HTML structure, or renaming classes and IDs as part of active development is to be expected, however MediaWiki developers are encouraged to over-communicate any changes to gadget developers and peers, particularly in projects which have high visibility (e.g. operate in the article namespace).

Wiki-hosted code MUST NOT mimic markup defined by MediaWiki developers for styling purposes as this can lead to misuse, misunderstandings and breakage 1 2]. In cases where it might be mutually beneficial for wiki-hosted code and MediaWiki developers to share code, for example for performance reasons, this MUST be documented in the source-controlled code using a @public an @since keyword linking to the on-wiki discussion. HTML classes that do wish to be considered stable MUST add an inline comment indicating for what MediaWiki versions they were introduced using a @since annotation and must follow the deprecation process in the relevant section below.

Guidelines for changing HTML markup.

 * MediaWiki engineers MUST consider caching implications,namely that HTML from a previous deploy may be served to users alongside newer CSS. For pages subject to cache, MediaWiki engineers MUST consider how HTML that is less than or greater to a week old (e.g. generated during the last train cycle) will be styled.
 * MediaWiki engineers SHOULD assess impact of their change to HTML markup based on the popularity of the gadget e.g. Special:GadgetUsage and en:User scripts/Most imported scripts using the global search tool to decide whether communication is advisable and what a suitable timeframe for the change might be. As a general rule popularity can be judged by 50+ scripts in MediaWiki namespace or more than 1000 scripts across the user and MediaWiki namespace. The timeframe should be at least 1 month, but may warrant longer in some cases. This can be skipped if engineers are confident that gadgets will not be severely impacted (for example if the gadget is still functional after the change but stylistically different).
 * For now, use your best judgement on determining usage and popularity. For example the Twinkle gadget is widely used, so an issue that impacts the Twinkle gadget may be more significant than the impact to 100 user scripts.
 * Particular care MUST be taken when changing any element using a class or ID prefixed with "mw-" as traditionally this has been viewed as a stable interface or any class that is provided by the MediaWiki wikitext parser e.g. .wikitable, .external
 * In the case of renaming IDs where the class might be mistakenly considered stable per Definition of the stable interface (due to historic association with the mw- prefix for example), developers SHOULD consider a longer grace period.
 * In the case of renaming classes, it is recommended that the new class SHOULD be added along with the removed class for at least 1 MediaWiki release cycle. An inline comment should indicate which release the old class was deprecated.

Guidelines for naming

 * All HTML classes prefixed with mw-  generated by MediaWiki core. Note, code outside MediaWiki core, SHOULD NOT use the mw- prefix as it can confuse gadget developers by suggesting a stable API.
 * Extension/skin developers MUST prefix their CSS classes to avoid namespace clashes with wiki-hosted code developers. Extension/skin developers MUST use a unique prefix other than `mw-` e.g. Skin:Vector uses vector-, and Extension:AbuseFilter use mw-abusefilter-. Extension/skin developers are free to use the prefix that makes sense to them. The benefits of this are twofold:
 * 1) our codesearch tool can be easily used to look up where classes originate  2) Gadget developers will often rely on the `mw-` prefixed selectors, and assume they are stable and not prone to change.

Guidelines for changes to HTML structure.
All frontend code (including wiki-hosted code, extensions and skins) relying on HTML structure does so at its own risk. MediaWiki developers SHOULD provide and request APIs to access elements or extend existing elements

Examples:


 * For adding items to menus the mw.util.addPortletLink method is encouraged rather than relying on jQuery
 * For adding subtitles use mw.util.addSubtitle rather than appending to #contentSub or #mw-content-subtitle elements

Guidelines around modifying default styles
MediaWiki developers MAY change default CSS for content generated by wikitext (e.g. changing the default link colors or changing typography). While rare, developers should consult the global search tool to inform themselves on potential local overrides made by editors in MediaWiki:Common.css and follow the communication guidelines in Communicating changes to gadget developers.where the change may be controversial.

It is generally recommended when doing re-designs, where possible that MediaWiki developers SHOULD use new classes/IDs, to avoid caching implications (see definitions section)

What to do when breaking changes to JavaScript interfaces

 * Code that MUST  follow the deprecation policy:
 * Code that is defined on the public mw object, regardless of where it is added.
 * Share code between modules privately, using require and module.exports to circumvent this. See mediawiki.String (and mediawiki.Title) as an example of how to share code privately using module.exports and require(‘ ’).
 * Hooks fired using the mw.hook object in MediaWiki core code
 * Code that has indicated it is stable in its JavaScript documentation, preferably using the @stable tag

See these 2 examples:


 * When deprecating code in this form, method mw.log.deprecate MUST be used to signal the deprecation of the API. The deprecation message should state the release in which the deprecation happened.
 * When deprecating in this manner, the software MUST log hard deprecation warnings to the JavaScript developer console for at least one MediaWiki release. See example below.
 * MediaWiki developers MUST follow guidelines around Communicating changes to gadget developers.

What to do when removing ResourceLoader modules

 * All ResourceLoader modules inside MediaWiki core MUST be considered stable unless marked as deprecated. For modules outside MediaWiki core, there is no need to follow the deprecation policy, unless you have explicitly designed the module for consumption by other extensions/skins.
 * Code that was never part of a public MediaWiki release, and never consumed according to codesearch and globalsearch MAY be changed or removed without deprecation, since it has never become part of the stable interface or used.
 * Before removing a module, the module MUST be deprecated so that usage of them logs warnings for at least 1 MediaWiki release prior to removal. This is to support third party developers who need to be notified and respond to any upstream changes.
 * When deprecating a ResourceLoader module, set the deprecated key on the associated ResourceLoader. When deprecating in this manner, the developer MUST document the deprecation in RELEASE_NOTES and mention the release number in which it was deprecated.
 * Developers MAY fix consumers of a module prior to deprecation, but it is not required as a precursor to deprecation.
 * The software MUST log hard deprecation warnings in this manner for at least one MediaWiki release. When removed, this should also be documented in RELEASE_NOTES.
 * Communicate the change to gadget developers (see Communicating changes to gadget developers)

Maintaining existing features

 * MediaWiki developers SHOULD regularly check the JavaScript console for deprecation notices and warnings and engage with them within 1 release cycle, by either fixing the issue or making clear why that is not possible.
 * MediaWiki developers MUST pay attention to Phabricator tickets with requests for code maintenance and communicate any challenges they see with resolving them.
 * Code creating complex UIs MUST use Vue.js and MUST follow any guidance that appear in the JavaScript console to maintain compatibility.
 * Code written in OOUI MUST follow any deprecation warnings shown in the JavaScript developer console

When developing new features

 * All new MediaWiki code deployed to Wikimedia wikis SHOULD consider support providing on-wiki code a stable way to access its most important elements.
 * Newly written code SHOULD NOT use deprecated ResourceLoader modules e.g. jQuery.UI.
 * MediaWiki developers MUST regularly review popular gadgets to evaluate code that makes assumptions about the HTML structure or to flag potential APIs using the global-search tool. MediaWiki developers MAY do this as part of their planning process, and MUST evaluate the use case in situations where a gadget developer raises a Phabricator ticket after an incident has occurred (for example: in a situation where a popular gadget breaks)
 * MediaWiki engineers SHOULD use feature flagging (e.g. Extension:BetaFeatures or user preferences) in deployments to allow editors to test interfaces prior to development and SHOULD advertise their availability via m:Tech/News.

Handling breaking changes in widely used but non-maintained gadgets
When making breaking changes, despite good intentions it is inevitable even with good communication that some on-wiki scripts will not be updated by their maintainers and the change will lead to production errors and/or disruption to editor workflows.

Client side errors occurring in wiki-hosted code are tracked alongside errors in Wikimedia code on Grafana and can be explored further inside our logstash instance.

When making breaking changes, at times MediaWiki developers have a responsibility to fix or disable certain gadgets in the following scenarios:


 * MediaWiki developers MUST fix or disable error logging for any wiki-hosted code and/or user script errors with error volumes that trigger alerts via Wikimedia alerting systems. Having healthy metrics helps us have more confidence when we deploy code. Ideally the fix SHOULD be made by the maintainer of the code after discussion on the script's talk page, however in time sensitive situations MediaWiki developers MAY take action themselves if they feel comfortable doing so.
 * MediaWiki developers MAY fix or disable wiki-hosted code and/or user script errors that undermine user privacy. For example, if an active user is triggering an error on every page load, which reveals their page history, fixing it is encouraged.
 * MediaWiki developers MAY fix or disable wiki-hosted code that are broken provided the edit summary or the talk page documents how the issue can be fixed.
 * MediaWiki developers MAY run bots to fix multiple wiki-hosted code where resolution is straightforward. Example: A method is renamed.

Communicating changes to gadget developers

 * The scope of this policy regarding gadget code that runs on one of the Wikimedia projects. It does not apply to gadgets running on third party instances
 * For changes that impact more than 10 gadgets (MediaWiki namespace) and/or 1000+ user scripts (user namespace), MediaWiki engineers MUST notify m:Tech/News.
 * If less gadgets/scripts are impacted, then MediaWiki engineers SHOULD notify m:Tech/News
 * A period of at least one month MUST be given for wiki-hosted code developers to respond and raise any concerns relating to the change regardless of MediaWiki release.
 * Wikimedia engineers MUST consider any feedback from gadget developers to minimize disruption (for example create tickets around introducing APIs where missing)
 * The Tech news entry MUST mention "BREAKING CHANGE" in the title and provide steps to resolve the problem inside the description
 * MediaWiki engineers when learning about the breakage of gadgets on-wiki that is not covered by the wiki-hosted code policy MUST assess the inclusion of a new API to reduce future breakage.