Page MenuHomePhabricator

[SPIKE] Propose an in-code mechanism for marking endpoints as deprecated
Closed, ResolvedPublic

Description

Description

As we evolve our APIs, we will need to deprecate specific endpoints. We expect this to, at times, happen independently of incrementing major version changes. Today, deprecation is only surfaced through the API documentation, without a way to make the deprecation status visible to callers as part of the actual API responses. Additionally, the deprecation field is currently only communicated through the endpoint descriptions within OpenAPI for the documentation. To ensure that API callers are aware of and can safely respond to REST API deprecation statuses, we need to ensure they are clearly communicated are discoverable through standard, programmatically accessible channels.

Conditions of acceptance

[x For REST APIs, determine how to include a flag in the spec generation process that allows REST API owners to include the "deprecated: true" indicator within the spec itself.

  • Propose a way to send a warning or otherwise mark an endpoint as deprecated for callers.
  • Review proposal with the MediaWiki Interfaces team and any other stakeholders who are interested.
    • Determine if a decision brief is required to socialize more broadly across the foundation. (probably not)
  • Announce the plan for how we intend to use the deprecation header to the community, through standard channels. <-- Halley will help with this.
Dependencies

The first known endpoints that we plan to deprecate are the "trailing slash" transform endpoints. Depending on the scope of this work, we may consider this a blocker for actually marking them as deprecated: https://phabricator.wikimedia.org/T404854

Event Timeline

Some context and links (some of which is redundant with the task description):

The Action API has various sorts of deprecation support that we can take inspiration from (although we may choose to do some things a little differently in MW REST API. Some things to look at:

RESTBase also has a way to mark endpoints as deprecated.

OpenAPI supports deprecation at the operation level (path + HTTP method). And it looks really neat in Swagger UI.

Minor callout about the RESTBase API -- it seems like they only designate the stability policy within the endpoint documentation descriptions. Is that accurate? I don't see any examples of actually using the deprecated: true designation in the spec; the only endpoint I see that is currently marked as deprecated is POST Reading lists, but it is only called out in the endpoint description there.

Minor callout about the RESTBase API -- it seems like they only designate the stability policy within the endpoint documentation descriptions. Is that accurate? I don't see any examples of actually using the deprecated: true designation in the spec; the only endpoint I see that is currently marked as deprecated is POST Reading lists, but it is only called out in the endpoint description there.

Yes, I believe that's correct.

That's not a bad precedent to consider, even though we want to do more. If we've trained our callers to look in the descriptions for a deprecation indicator, then maybe it makes sense to automatically add some sort of suitably localized indicator to that string.

Of course, we also want to do deprecated: true, to make deprecation visible in the REST Sandbox. And maybe also send the RFC9745 header that you mentioned in the task description. But some callers may look at the OpenAPI specs directly, or in their preferred viewer, or even process them programmatically, and might be accustomed to the RESTBase mechanism.

Or maybe not, but it is worth talking about.

Totally agree that it should also be in the spec. My thought is that using the OpenAPI indicator also automatically adds the indicator for it in the docs themselves, per the Swagger UI example.

It's a good call thinking about if we should include something more specific in the OpenAPI style guide and linting process for deprecations, as well, though. For example, something as simple as always starting the description with "This endpoint is marked as deprecated and will be disabled on dd/mm" or something like that. The current style does not actually specify an end date, which seems like a good addition if we can actually stick to them :)

Proposal:

MW REST API

tl;dr: support adding something like the following in endpoint specs (both module definition files and the old flat format):
deprecated: true
x-deprecation:date: 1688169599

For endpoints defined in the old-style route files (ex. coreRoutes.json, probably the only one we care about), you can already mark an endpoint as deprecated, and have that included in the OpenAPI Spec and shown in the REST Sandbox, by adding deprecated: true to the openApiSpec portion of the route definition. No changes to the code necessary to make that work, you can do it today.

For endpoints defined in module definition files, add deprecated as an allowed oasKeys value in SpecBasedModule.php (a safe, simple, one-line change). Then to mark an endpoint as deprecated, you can add deprecated: true to the route spec, at the same level as handler. This is intuitive, because that's the same level it appears in the actual OpenAPI spec. For example:

		"/discovery": {
			"get": {
				"handler": {
					"class": "MediaWiki\\Rest\\Handler\\DiscoveryHandler",
					"services": [
						"MainConfig"
					]
				},
				"deprecated": true
			}
		},

If we choose to auto-adjust the endpoint description to include something like "Status: Deprecated", it would be convenient to , add a protected @stable to override isDeprecated() function to Handler. The default behavior of this new function would be to return false, unless deprecated is present and true in the route spec. This should be enough for most (all?) derived classes, but if any derived class does have a really special need, they can always override it and implement whatever logic they need to.

To actually add the annotation to the endpoint description, modify Handler::getOpenApiSpec() (or associated code) to adjust the description accordingly, keeping in mind that the annotation itself should be localized.

Note: all handlers could just override isDeprecated instead of setting deprecated: true in the route config. Using the route config is needed in cases where multiple paths map to the same handler class, it is a smaller code change than overriding isDeprecated in a derived Handler class, and it associates deprecation with the part of our system that looks more like a spec, which is probably more sensible from a git history perspective, and also more approachable for people unfamiliar with PHP or our Handler implementations. The default implementation in Handler should have a comment suggesting people to use the route config for endpoint deprecation, unless they have a specific reason not to.

If that were all we were doing, this seems like a simple and non-controversial change, with the biggest decision being exactly what the description annotation looks like. But we also want to support the Deprecation header from RFC9745. And it requires a date. We therefore need some way to communicate that date

There are several options for this, including:

  • also add a custom property, something like x-deprecated-date, to the route spec. These are supported by OpenAPI (again, our module definition files aren't exactly OpenAPI but we like to keep them close). Callers who wanted to mark something as deprecated without committing to a date could add deprecated: true but simply not set this value. An open question is what happens if x-deprecated-date is specified but deprecated: true is not. Maybe a structure test could complain about this.
  • instead of setting deprecated: true in the endpoint spec, set something like deprecated: 1688169599, where the numeric portion is the deprecation date in the format expected by the Deprecation header. This would be easy to code, but our module definition files are designed to look a lot like OpenAPI specs, and this abuses a legal OpenAPI value in a non-obvious custom way. It also is inconvenient for callers who may want to mark something as deprecated without committing to a date. We could play games like deprecated: 0 means mark the endpoint as deprecated but don't send the header or display a date. But that feels even worse.
  • don't support deprecated: true at all. Support only the custom property. In that case, setting x-deprecated-date: 0 could be a special "mark as deprecated but don't display a date" value, if we want to support that. This is less offensive than playing that game with deprecated, because this is a custom property we're defining ourselves. But it still feels kinda bad to me.

For clarity, the values discussed above would go into the module definition files (ex. specs.v0.json) or flat route file (ex. coreRoutes.json). At least deprecated: true would also end up in generated specs, and we could include x-deprecated-date in the generated spec if we like. But the above bullet points are talking about how the endpoint developers controls whether something is deprecated, not what callers see in the final OpenAPI spec.

I prefer the first - both deprecated: true plus a custom x-deprecated-date property - but we should talk about this.

Either way, the best place to actually add the deprecation header to the response is in Module::executeHandler(), which can call a new function Handler::applyDeprecationHeader(), named similarly to existing Handler::applyConditionalResponseHeaders() and Handler::applyCacheControl(). This would no-op in the normal case where the endpoint was not deprecated, or was deprecated but didn't have a date. Otherwise it'd add the header.

ACTION API

Action API already has a fairly robust deprecation system, that people have been using for years. It is unclear that any changes need to be made.

The only change I'd suggest considering is adding the Deprecation header. The way most consistent with existing Action API practice would be to add something like a "getDeprecationDate()" that callers could override.

(Details TBD - what happens if isDeprecated() and getDeprecationDate() are inconsistent?)

(Edit for typos and formatting)

After discussion, we decided on the following:

  • don't change anything in Action API at this time. All other bullet points below refer only to MW REST API.
  • support adding deprecated: true to endpoint definitions in module definition files (ex. specs.v0.json) and flat route files (ex. coreRoutes.json). Setting deprecated: true will:
    • cause deprecated: true to be included in the generated OpenAPI spec for that endpoint operation (see example below). This will cause the endpoint to be shown as deprecated in the REST Sandbox
    • add deprecation status text to the endpoint description (exact text TBD, should be localized)
  • support adding x-deprecated-date to endpoint definitions in module definition files (ex. specs.v0.json) and flat route files (ex. coreRoutes.json). Setting x-deprecated-date: will:
    • cause the Deprecation header to be sent with responses, per RFC 9745.
    • add the deprecation date to the endpoint description (exact text TBD, should be localized)
    • cause x-deprecated-date to be included in the generated OpenAPI spec for that endpoint operation (see example below). This will have no visible effect in the REST Sandbox, but will be conveniently machine readable for any callers that care to do that
  • add a structure test to ensure that if x-deprecated-date is set, then deprecated: true is also set. In other words, it will be a test error to set a deprecated date for an endpoint that you haven't marked as deprecated.
  • add a structure test to ensure that x-deprecated-date includes a valid timestamp
  • consider if the mwapi schema should be updated to mention these fields
  • special needs can be dealt with in code by overriding the new Handler class functions. Hopefully this is rare, and we don't anticipating needing it for the initial use case described in the paren task. But is possible if required.

Examples:

coreRoutes.json:

	{
		"path": "/v1/page/{title}/history",
		"class": "MediaWiki\\Rest\\Handler\\PageHistoryHandler",
		"services": [
			"RevisionStore",
			"NameTableStoreFactory",
			"GroupPermissionsLookup",
			"DBLoadBalancerFactory",
			"PageStore",
			"TitleFormatter",
			"PageRestHelperFactory"
		],
		"openApiSpec": {
			"x-i18n-description": "rest-endpoint-desc-get-page-history",
			"x-i18n-summary": "rest-endpoint-summ-get-page-history",
			"deprecated": true,
			"x-deprecated-date": 1688169599
		}
	},

specs.v0.json:

		"/discovery": {
			"get": {
				"handler": {
					"class": "MediaWiki\\Rest\\Handler\\DiscoveryHandler",
					"services": [
						"MainConfig"
					]
				},
				"deprecated": true,
				"x-deprecated-date": 1688169599
			}
		},

Note: we are not actually deprecating those particular endpoints. Those examples serve only to illustrate where the values will be added .

Resulting OpenAPI spec (relevant portion only):

"/v1/page/{title}/history": {
	"get": {
		"parameters": [],
		"responses": {},
		"summary": "Get page history",
		"description": "Returns information about the latest revisions to a page, in segments of 20 revisions, starting with the latest revision. The response includes URLs to get the next oldest, next newest, and latest revision segments, letting you scroll through page history. [Status: Deprecated as of Friday, June 30, 2023 at 23:59:59 UTC]",
		"deprecated": true
		"x-deprecated-date": 1688169599
	}
},

(Note: exact format of text added to description still TBD.)

Edit: added mention of mwapi schema

Thanks for the update, Bill! The notes you captured from our discussion earlier look good to me. Thanks again!

For the description changes, I would expect them to be the last line of the description with two new lines of whitespace, which follows the pattern set by RESTBase originally. A suggestion for the actual text to add to the description might be:

Normal endpoint description.

WARNING: This endpoint is deprecated. It will be removed on or around {Month} DD, YYYY.

Where the second sentence is only included if a date is provided. I'm also not totally sold on the "WARNING" label, but thought it might draw more attention. Would be curious for @KBach to weigh in.

A note about the date structure too -- goal here is be very clear and avoid issues with internationalisation for date formatting. Are you aware of a standard way of dealing with dates in cases like this? The ask is that we convert the Epoch format to be more human readable; providing the month name seems like the best way to avoid day vs month formatting confusion, but that approach may cause more issues with translation?

A suggestion for the actual text to add to the description might be:

Normal endpoint description.

WARNING: This endpoint is deprecated. It will be removed on or around {Month} DD, YYYY.

Per the rfc, the deprecation date is the date on which the resource became (or will become) deprecated, not the date on which it will be removed.

If we want to support a removal date, we'd use the Sunset header (also mentioned in the rfc). Personally, I'd rather not commit to removal dates, at least right now. There are all sorts of reasons we miss those. I'm skeptical that we'll change organizational culture in that regard, nor am I convinced we should try. We can always add Sunset support later if we decide to, using the pattern we're establishing with Deprecation.

A note about the date structure too -- goal here is be very clear and avoid issues with internationalisation for date formatting. Are you aware of a standard way of dealing with dates in cases like this? The ask is that we convert the Epoch format to be more human readable; providing the month name seems like the best way to avoid day vs month formatting confusion, but that approach may cause more issues with translation?

I wondered that too. A quick glance didn't reveal anything, but surely this is a solved problem. If I can't find anything after another look, I'll ask around.

On this bullet point:

* consider if the mwapi schema should be updated to mention these fields

I'm going to look into adding mwapi-1.1.json to the upcoming WIP patch, at least for discussion during code review.

The current mwapi schema version (1.0) doesn't object if we add deprecated and x-deprecated-date to module definition files (structure tests still pass). But it also doesn't do us any good on validating them. Someone could add improperly formed values (ex. "deprecated": "Foo") and structure tests based on mwapi-1.0 wouldn't catch it. By adding these fields to a new version of the schema, things like that would fail, thereby directing developers into correcting it.

If I do indeed add a new schema version, I'll also update specs.v0.json and content.v1.json to use it.

In addition to the benefit for the new fields, this seems like a useful thing to do for its own sake. The string mwapi-1.0 is hard-coded in a few places in tests, so a (small) change to the structure test itself will be needed to make it support multiple versions of mwapi. That's a good thing, and something we'd want to do anyway. Doing it now, as a helpful part of a fairly small change, seems like a good opportunity.

Change #1190781 had a related patch set uploaded (by BPirkle; author: BPirkle):

[mediawiki/core@master] Support MW REST API endpoint deprecation

https://gerrit.wikimedia.org/r/1190781

Overall, I like the proposal, and I'm very happy that this is happening!

Here are a few throughts on some of the details:

  • It would be useful to allow a custom deprecation message to be specified, so we can tell users what to use instead of the deprecated endpoint. This has proven essential to the success of deprecations in our PHP code, and it's a requirement of the stable interface policy. This could be done by specifying a message key in the module description file.
  • while we need the "x-" prefix in the generated OpenAPI spec, we don't need it in the module file schema. In fact, to me "x-" means "not in the schema", so adding something with an "x-" prefix to the schema seems odd.
  • Instead of having separate fields for deprecated yes/no, the date, and the message, it could be a structure:
deprecated:
  from: xyz
  message: xome-message-key

I see an issue with having the deprecation date in the module spec is problematic. The actual date will depend on deployment schedules and configuration changes. It may be totally different (off by years) for other sites that use MediaWiki. We may deprecate an enpoint for the end of 2025, but sites that only update to the next LTS release may still have it for another two years - and will want their users to know that.

I think this could be solved by adding a level of indirection. The module difinition defines the deprecation target as a MediaWiki release number, And we add configuration that maps that to a date. E.g.

deprecated:
  message: my-rest-endpoint-deprecation
  version: MW 1.46

and then, in the config:

$wgApiDeprecationDates = [
  'MW 1.46' => '2025-12-01'
]

If no mapping is given, the deprecation is still mentioned in the docs, but no headers are generated.

This way, the dates can easily be adjusted to deployment/update schedules.

Notes from triage:

  • Add the ability to deprecate modules as well as endpoints
  • There is a nuance between marking as deprecated and actually removing the endpoint
    • Marking as deprecated = treat as minor version change
    • Actually removing = assume a major version change
  • We need to document the expected deprecation flow --> Follow-up task (documentation)
  • We need to outline boundaries for minor vs major version changes --> Follow-up task (documentation)
  • Consider and document the impact & workflow for third party consumers, especially under the assumption that many 3rd parties only use LTRs

Thank you for the thoughts, @daniel ! Continuing the conversation below...

Here are a few throughts on some of the details:

  • It would be useful to allow a custom deprecation message to be specified, so we can tell users what to use instead of the deprecated endpoint. This has proven essential to the success of deprecations in our PHP code, and it's a requirement of the stable interface policy. This could be done by specifying a message key in the module description file.

Where would you see such a message appearing? In the "description" portion of the OpenAPI spec (within the "info" block), likely auto-added to the module description string? Or somewhere else?

  • while we need the "x-" prefix in the generated OpenAPI spec, we don't need it in the module file schema. In fact, to me "x-" means "not in the schema", so adding something with an "x-" prefix to the schema seems odd.

That makes sense. The competing argument, and the reason we used the "x-" prefix, is that when a developer puts this into a module definition file, they're expecting to see "x-deprecated-date" show up in the OpenAPI spec. It seemed more consistent to tell them to enter the thing they expect to see, rather than to put one thing in and expect something else out. Which brings me to...

  • Instead of having separate fields for deprecated yes/no, the date, and the message, it could be a structure:
deprecated:
  from: xyz
  message: xome-message-key

That makes sense for keeping the deprecation information all together, and naturally extends if we decide to add even more deprecation-related things in the future. However, as I understood it, we intentionally tried to make our module definition files look a lot like OpenAPI specs, at least in part because that would be a comfortable and familiar format for developers accustomed to working with REST APIs. This would be counter to that goal, taking a legal OpenAPI value and using it differently here. We're already getting feedback from very experience developers (including Principal Engineer level) that it is confusing to know how to add things to MW REST API. So I'm looking for ways to keep things as obvious as possible.

I'm not saying it is a bad idea, just thinking it through.

What if we used a different property name than "deprecated" to reduce confusion about why it is different between the two places. One option would be "sunset", because presumably removal is the real end goal. Something like:

sunset:
  deprecated-from: xyz
  removed-from: abc
  message: some-message-key

Then we could both deprecate and remove (sunset) things by changing only the same block. That'd keep git history clean. Both dates could be used for an automatically constructed (and suitably localized) message like:
"This module was deprecated on or about 2025-09-26 and removed on 2026-03-26."

This would be automatically added to the message provided by some-message-key, allowing the en.json message to focus on telling developers what to do instead.

Once a "removed-from" date was set, any calls to any path under the module would return an appropriate error response including the Sunset header. This means any associated Handler code could be removed from the codebase. A removed module that still broadcast a sunset message would just consist of the module definition file (which could eventually also be removed).

That's off the top of my head, and maybe it's a terrible idea. But something along those lines might help soften the deprecation/removal process for third parties, by allowing us to return something informative to callers for quite awhile, maybe until after the next LTS, while still removing code we no longer need.

I see an issue with having the deprecation date in the module spec is problematic. The actual date will depend on deployment schedules and configuration changes. It may be totally different (off by years) for other sites that use MediaWiki. We may deprecate an enpoint for the end of 2025, but sites that only update to the next LTS release may still have it for another two years - and will want their users to know that.

I think this could be solved by adding a level of indirection. The module difinition defines the deprecation target as a MediaWiki release number, And we add configuration that maps that to a date. E.g.

deprecated:
  message: my-rest-endpoint-deprecation
  version: MW 1.46

and then, in the config:

$wgApiDeprecationDates = [
  'MW 1.46' => '2025-12-01'
]

If no mapping is given, the deprecation is still mentioned in the docs, but no headers are generated.

This way, the dates can easily be adjusted to deployment/update schedules.

I'm sympathetic to the third party use case, but it feels unlikely to me that we'll manage API lifecycles in this fashion. Among other things, it feels like a lot to think about for rapidly changing APIs, which we want to encourage. We're already looking for ways to make rapid experimentation easier (ex. T389910: Hypothesis 5.5.3: Enable API Experimentation ), and minimizing coupling between code and config is an explicit goal.

The deprecated-from / sunset-from alternative that I proposed would still be a lie because those weren't the dates that those events occurred on that third party site. But it'd be more than nothing.

For the description changes, I would expect them to be the last line of the description with two new lines of whitespace, which follows the pattern set by RESTBase originally. A suggestion for the actual text to add to the description might be:

Normal endpoint description.

WARNING: This endpoint is deprecated. It will be removed on or around {Month} DD, YYYY.

Where the second sentence is only included if a date is provided. I'm also not totally sold on the "WARNING" label, but thought it might draw more attention. Would be curious for @KBach to weigh in.

I think "warning" is an appropriate message type in this case. I'm not sure it should be a part of the description field itself though. If we are introducing new fields into the OAD to manage this, perhaps we can generate this text automatically in the API explorer, place it as you described, and leave the description unchanged?

A note about the date structure too -- goal here is be very clear and avoid issues with internationalisation for date formatting. Are you aware of a standard way of dealing with dates in cases like this? The ask is that we convert the Epoch format to be more human readable; providing the month name seems like the best way to avoid day vs month formatting confusion, but that approach may cause more issues with translation?

I think ISO 8601 is the date standard/format we recommend in most circumstances. But if we were to generate this message, perhaps user's date formatting preferences could also be taken into account here?

I think "warning" is an appropriate message type in this case. I'm not sure it should be a part of the description field itself though. If we are introducing new fields into the OAD to manage this, perhaps we can generate this text automatically in the API explorer, place it as you described, and leave the description unchanged?

@KBach that's a fair question. Especially since we are planning to include the date as an extension property, it doesn't necessarily have to be within the endpoint description for consumers of the raw spec to get that information either. I wonder where would get the data from if we are injecting it into the explorer without it being part of the spec though?

Bill's point about users being used to seeing that information in the description (see: RESTBase API documentation) is also valid, but perhaps not necessary since it is marked as such fairly clearly in SwaggerUI as it is, once it's marked as deprecated in the spec (albeit without the deprecation date automatically displayed).

@KBach that's a fair question. Especially since we are planning to include the date as an extension property, it doesn't necessarily have to be within the endpoint description for consumers of the raw spec to get that information either. I wonder where would get the data from if we are injecting it into the explorer without it being part of the spec though?

I'm not sure I understand what data you're referring to. Do you mean that some of the information necessary to generate the deprecation warning in the explorer won't be available in the OAD (spec)?

Bill's point about users being used to seeing that information in the description (see: RESTBase API documentation) is also valid, but perhaps not necessary since it is marked as such fairly clearly in SwaggerUI as it is, once it's marked as deprecated in the spec (albeit without the deprecation date automatically displayed).

I agree. If the deprecation information is properly displayed in the explorer, SwaggerUI handles it well (even without the deprecation date), and maybe the description and deprecation properties are next to each other in the raw OAD, perhaps that's good enough. Especially if it makes the OAD more maintainable?

Change #1193228 had a related patch set uploaded (by BPirkle; author: BPirkle):

[mediawiki/core@master] Support MW REST API endpoint and module deprecation

https://gerrit.wikimedia.org/r/1193228

After separate conversations with @daniel and @HCoplin-WMF, here is the a proposal for what will be done in the initial patch, plus a plan for how this might be extended for possible future additions.

What we are doing now
  1. supporting basic endpoint deprecation (indicating in the OpenAPI spec that an endpoint is deprecated, and sending the Deprecation header)
  2. introducing a structure into the endpoint/module definition json which allows us to iterate on this later if we choose to add more deprecation-related features

To do this, we will support specifying the following in the module definition or flat route json file:

"deprecationSettings": {
  from: <timestamp or maybe other supported date formats>
}

This can be placed at the module level (preferred) or the individual endpoint level (if deprecating individual endpoints is necessary, as it is in the case of the "trailing slash" transform endpoints).

If the deprecationSettings property is present, then the associated endpoint (or endpoints, in the case of module deprecation) will include "deprecated": true in the OpenAPI spec. This will cause swaggerui to display the endpoint(s) as deprecated.

It is legal for the deprecationSettings property to be an empty object. If so, then including "deprecated": true in the OpenAPI spec is all that will happen.

If the from value is present, then the Deprecation header will be sent with responses from the affected endpoint(s).

Earlier comments discussed modifying description strings in the OpenAPI spec. We will not be doing that in the initial patch. If that is desired, it can be added in a followup.

Future capabilities

The basic system can be extended by adding additional, still-to-be-defined properties to deprecation-settings. This allows activating additional behaviors, the full set of which are still up for discussion, and none of which (other than from) we are implementing in the first patch. A speculative example might look like (YAML-ish version shown):

deprecationSettings:
  from: <timestamp or maybe other supported date formats>
  sunset: <timestamp or maybe other supported date formats>
  message: <hard-coded string or localizable message key>
  version: <mw version this becomes active, similar to @deprecated in PHP code per the Stable Interface Policy>

The deprecation portion of the Stable Interface Policy can be found here.

To be clear: we're not supporting sunset, message, or version in the initial patch (or maybe ever). They're just examples. Implementing just the basic portion first allows us to meet the minimal needs of T404855: [Jan 2026] Remove trailing slash routes for Transform endpoints. Having a plan for an extensible way to add other deprecation-related features allows us to extend the system in incremental ways, as we gain clarity.

Change #1190781 abandoned by BPirkle:

[mediawiki/core@master] Support MW REST API endpoint and module deprecation

Reason:

Abandoning in favor of https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1193228

https://gerrit.wikimedia.org/r/1190781

Change #1193228 merged by jenkins-bot:

[mediawiki/core@master] Support MW REST API endpoint and module deprecation

https://gerrit.wikimedia.org/r/1193228

Basic deprecation support (flag in OpenAPI spec, header on endpoint execution) is merged and riding this week's train.

Additional deprecation support, if desired, can be added under separate tasks.

The only thing remaining per the task description is announcing to the community.

BPirkle updated the task description. (Show Details)