Skip to content

docs(api-reference): publish the API deprecation policy - #2832

Open
aaronmichaelacosta wants to merge 6 commits into
graphite-base/2832from
APPEX-956/deprecation-policy
Open

aaronmichaelacosta wants to merge 6 commits into
graphite-base/2832from
APPEX-956/deprecation-policy

Conversation

@aaronmichaelacosta

Copy link
Copy Markdown
Contributor

What this adds

A Deprecation Policy page for the public API, sitting next to the changelog in both versions:

  • /api-reference/v1/Deprecation-Policy
  • /api-reference/v2/Deprecation-Policy

It answers one customer question: how much warning do I get before a Semgrep API change breaks my integration? Short version — stable endpoints get 6 months' notice for a breaking change, beta gets 30 days, experimental gets none, and undocumented endpoints aren't covered at all. At the deadline the endpoint returns 410 Gone rather than quietly serving wrong data.

The text is the customer-facing half of the policy drafted in APPEX-956. The internal appendix — notice channels, the 410-vs-301 decision record, known gaps — is not published.

One change from the draft

The policy was written before we decided to ship a changelog, so its "how do I find out what's deprecated" list had no way for a customer to be told proactively — only the reference, response headers, and emailing support. It now leads with the changelog and its RSS feed, which records every deprecation on the day it ships.

Notes for review

  • The body lives in a snippet imported by both version pages, so v1 and v2 can't drift apart.
  • Omitted on purpose: the in-app banner and admin email that the draft names as commitments. Neither exists yet, so publishing them would promise channels we can't serve.
  • Still needs Product and Legal/Compliance sign-off per the APPEX-956 checklist — this is a public commitment, so please don't merge on a docs review alone.

Test plan

  • npx mintlify@latest validate passes

Stacked on #2796 — this page links to the changelog pages that PR adds, so it should merge after it.

aaronmichaelacosta commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Comment thread docs/api-reference/v1/Deprecation-Policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated

@abhijna abhijna left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for writing this doc. Made some style and voice changes to sync with our technical docs guide. Please lmk if you have any questions

Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated
@connorg
connorg requested a review from andy-r2c September 4, 2026 18:28
@connorg

connorg commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

@aaronmichaelacosta I've asked @andy-r2c to take a first review from the PM side and asked him to let me know when it's ready for me to give a final look. I want to be sure we're aligned from both the Product and Eng side of things before we publish.

Thank you for writing this up, also!

aaronmichaelacosta added a commit that referenced this pull request Sep 4, 2026
Takes all twelve suggestions from the review on #2832 verbatim: the intro
and summary sentences, the maturity table's header and all three rows, the
undocumented-endpoints paragraph, the security and legal exception (now
two paragraphs), the "Identify deprecated endpoints" heading, and the
four-bullet list in its label-prefixed form.

Two of the twelve needed a judgement call rather than a substitution:

- One was a question -- "Do we add callouts in the API docs? If so, this
  info would benefit from being in a callout box." We do; <Note> appears
  152 times in this repo. The summary paragraph is now a <Note>, using the
  suggested wording.

- The frontmatter description suggestion was left on the v1 page, but v1
  and v2 are deliberate duplicates importing the same snippet, so applying
  it to one only would have made them diverge. Both are updated.

Style and voice only. Nothing here changes what the policy commits to,
including the six-month window.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aaronmichaelacosta added a commit that referenced this pull request Sep 4, 2026
Takes all twelve suggestions from the review on #2832: the intro and
summary sentences, the maturity table's header and all three rows, the
undocumented-endpoints paragraph, the security and legal exception (now
two paragraphs), the "Identify deprecated endpoints" heading, and the
four-bullet list in its label-prefixed form.

Two of the twelve needed a judgement call rather than a substitution:

- One was a question -- "Do we add callouts in the API docs? If so, this
  info would benefit from being in a callout box." We do; <Note> appears
  152 times in this repo. The summary paragraph is now a <Note>, using the
  suggested wording.

- The frontmatter description suggestion was left on the v1 page, but v1
  and v2 are deliberate duplicates importing the same snippet, so applying
  it to one only would have made them diverge. Both are updated.

The undocumented-endpoints suggestion carried a double space after its
first period, which is dropped as a typo rather than reproduced.

Style and voice only. Nothing here changes what the policy commits to,
including the six-month window.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@aaronmichaelacosta
aaronmichaelacosta force-pushed the APPEX-956/deprecation-policy branch 2 times, most recently from 9400249 to 691f1ba Compare September 8, 2026 17:17
@aaronmichaelacosta
aaronmichaelacosta force-pushed the api-changelog-from-openapi branch from d413c13 to e15c480 Compare September 8, 2026 17:27
@aaronmichaelacosta
aaronmichaelacosta force-pushed the APPEX-956/deprecation-policy branch from 691f1ba to 547a2d0 Compare September 8, 2026 17:27
Comment thread docs/snippets/api-deprecation-policy.mdx Outdated

@connorg connorg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this a closer read after our review meeting.

The overall direction of my comments is the same, and I've tried to clearly note which would be blocking and which wouldn't.

I did become more concerned about the absolute-ness of the exception language and think we'd do better to soften it a touch.

APIs change over time. This policy explains how much notice you'll receive before a breaking change affects your integration.

<Note>
In summary, **stable endpoints receive at least 6 months' notice before a breaking change or a removal.** After the deprecation period ends, the endpoint returns `410 Gone` with a machine-readable pointer to its replacement. It never returns incorrect or partial data.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking:

the endpoint returns 410 Gone with a machine-readable pointer to its replacement.

Once we know what the machine-readable response is going to be, we should document it on this page.

Comment on lines +11 to +19
This policy applies to every endpoint documented on [docs.semgrep.dev](https://docs.semgrep.dev/), according to its maturity level.

| Maturity | What to expect | Notice before a breaking change or removal |
| --- | --- | --- |
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |
| **Beta** | Supported and documented. Semgrep maintains backward compatibility during the beta period, but the endpoint may still be renamed or removed. | 60 days |
| **Experimental** | Published to help you preview functionality. Experimental endpoints may change, be renamed, or be removed at any time without notice. | None |

Each endpoint's maturity is shown as a badge in the API reference and as a badge extension in the OpenAPI spec.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking, style.

After reading the first sentence, I'm wondering "how do I know an endpoint's maturity level?". So moving that answer up could be helpful.

Not a strong opinion; the flow works as it stands.

Suggested change
This policy applies to every endpoint documented on [docs.semgrep.dev](https://docs.semgrep.dev/), according to its maturity level.
| Maturity | What to expect | Notice before a breaking change or removal |
| --- | --- | --- |
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |
| **Beta** | Supported and documented. Semgrep maintains backward compatibility during the beta period, but the endpoint may still be renamed or removed. | 60 days |
| **Experimental** | Published to help you preview functionality. Experimental endpoints may change, be renamed, or be removed at any time without notice. | None |
Each endpoint's maturity is shown as a badge in the API reference and as a badge extension in the OpenAPI spec.
This policy applies to every endpoint documented on [docs.semgrep.dev](https://docs.semgrep.dev/), according to its maturity level.
Each endpoint's maturity is shown as a badge in the API reference and as a badge extension in the OpenAPI spec.
| Maturity | What to expect | Notice before a breaking change or removal |
| --- | --- | --- |
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |
| **Beta** | Supported and documented. Semgrep maintains backward compatibility during the beta period, but the endpoint may still be renamed or removed. | 60 days |
| **Experimental** | Published to help you preview functionality. Experimental endpoints may change, be renamed, or be removed at any time without notice. | None |


## Identify deprecated endpoints

- Subscribe to the API changelog: Every deprecation is announced in the changelog on the day it ships and is tagged as Deprecated. Each API version has its own RSS feed. Subscribe to the [v1](/api-reference/v1/Changelog) or [v2](/api-reference/v2/Changelog) feed to receive deprecation notices automatically.

@connorg connorg Sep 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking question.

I see you're adding these pages in #2796.

One question about that approach: if you're auto-generating the changelog, won't you need a different way to publish the advance notice 60–180 days before the change?


| Maturity | What to expect | Notice before a breaking change or removal |
| --- | --- | --- |
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion (non-blocking)

I just thought about this and realized it might be more predictable to have a literal number of days vs relying on variable-length months

Suggested change
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |
| **Stable** | Covered by the Semgrep API deprecation policy. | 180 days |

If changed, also change in the text above


| Maturity | What to expect | Notice before a breaking change or removal |
| --- | --- | --- |
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |

@connorg connorg Sep 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly blocking, but recommend fixing

Just realized on a closer reading that the existing wording doesn't really add value ("stable = covered by this policy"). But all APIs are covered by this policy, including Beta. Maybe something like:

Suggested change
| **Stable** | Covered by the Semgrep API deprecation policy. | 6 months |
| **Stable** | Supported and documented. Expected to evolve and improve without breaking changes. | 6 months |

Comment on lines +23 to +27
### The one exception: urgent security and legal changes

If continuing to support an endpoint or field would expose customer data, create a security risk, or violate a legal obligation, Semgrep may make changes with less notice than described above, or in rare cases, without notice.

This is the only exception to the deprecation policy. Semgrep does not invoke it for convenience. When invoked, Semgrep will communicate what changed and why as soon as possible.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reframe (blocking)

I want to be careful about making exclusive claims like "the one exception". I would rather

  • still make it clear this is to be done carefully
  • but not claim this is literally the only reason we might do it
  • also not mention "legal" as this sort of opens up a can of worms IMO
Suggested change
### The one exception: urgent security and legal changes
If continuing to support an endpoint or field would expose customer data, create a security risk, or violate a legal obligation, Semgrep may make changes with less notice than described above, or in rare cases, without notice.
This is the only exception to the deprecation policy. Semgrep does not invoke it for convenience. When invoked, Semgrep will communicate what changed and why as soon as possible.
### Exception: unavoidable urgent changes
If continuing to support an endpoint, field, or other aspect of API behavior would expose customer data, create a security risk, or violate an obligation, Semgrep may make changes with less notice than described above, or in rare cases without notice.
Semgrep will not invoke this exception lightly. When invoked, Semgrep will communicate what changed and why as soon as possible.


This policy applies to every endpoint documented on [docs.semgrep.dev](https://docs.semgrep.dev/), according to its maturity level.

| Maturity | What to expect | Notice before a breaking change or removal |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment (non-blocking)

I know you removed the details of what we consider a breaking change. However, I think as a reader I'd like to know what we consider in scope and out of scope. For example, I would want to know that Semgrep won't change URL paths or remove fields I might rely on.

Notably we could frame this either as "what would a break be" (negative) or "what do we promise stays the same" (positive).

@aaronmichaelacosta
aaronmichaelacosta force-pushed the APPEX-956/deprecation-policy branch from f13765c to 37ee39b Compare September 21, 2026 17:10
@aaronmichaelacosta
aaronmichaelacosta changed the base branch from api-changelog-from-openapi to graphite-base/2832 September 22, 2026 21:52
aaronmichaelacosta and others added 6 commits September 22, 2026 21:52
Adds a Deprecation Policy page alongside the changelog in both API
versions, from the customer-facing half of the APPEX-956 policy doc. The
internal appendix (notice channels, the 410-vs-301 decision record, open
gaps) is not published.

The body lives in a snippet imported by both version pages. Terms-of-Use
duplicates its one sentence per version, but 30 lines of policy would
drift, and the repo already shares longer content this way (see
snippets/metrics.mdx).

One content change from the source doc: it was written before we decided
to publish a changelog, so "Finding out what is deprecated today" had no
push channel -- only the reference, response headers, and support. It now
leads with the changelog and its RSS feed, which records every deprecation
tagged Deprecated on the day it ships.

Deliberately not carried over: the in-app banner and admin email named in
the internal appendix. Neither exists yet (appendix gap 4), so publishing
them would commit us to channels we cannot serve. The invented
/api/migrations/<resource> URL (gap 5) appears only in the appendix and is
not published either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Stable endpoints had two clocks: 6 months for a breaking change, 3 months
for removing an already-deprecated optional field. The short one does not
survive contact with how the clock actually starts.

Per styleguide 13.2 the clock only runs once the notice is public --
`Deprecation` and `Sunset` headers live, spec marked. A field marked
deprecated with no sunset date has therefore started no clock at all, so
the 3 months would be the entire notice a customer gets, not a follow-on
to time already served. That is half the window for something oasdiff
rates `response-optional-property-removed` at WARN, potentially breaking:
"optional" says the server may omit the field, not that nobody reads it.

One window for stable, whatever the change. Simpler to state, simpler to
honour, and it errs long on a public commitment.

Styleguide 13.1 transcribes this table and still carries the 3-month row;
that needs the same edit in semgrep-app. Its link to
api-deprecation-policy.md is also dangling -- that file does not exist in
that repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Takes all twelve suggestions from the review on #2832: the intro and
summary sentences, the maturity table's header and all three rows, the
undocumented-endpoints paragraph, the security and legal exception (now
two paragraphs), the "Identify deprecated endpoints" heading, and the
four-bullet list in its label-prefixed form.

Two of the twelve needed a judgement call rather than a substitution:

- One was a question -- "Do we add callouts in the API docs? If so, this
  info would benefit from being in a callout box." We do; <Note> appears
  152 times in this repo. The summary paragraph is now a <Note>, using the
  suggested wording.

- The frontmatter description suggestion was left on the v1 page, but v1
  and v2 are deliberate duplicates importing the same snippet, so applying
  it to one only would have made them diverge. Both are updated.

The undocumented-endpoints suggestion carried a double space after its
first period, which is dropped as a typo rather than reproduced.

Style and voice only. Nothing here changes what the policy commits to,
including the six-month window.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Doubles the beta notice period from 30 days to 60. 30 days is a short
window for a customer to notice a deprecation, schedule the work, and ship
it -- particularly for teams on a monthly release train, where it can
amount to a single opportunity to react.

Stable stays at 6 months and experimental still promises nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Connor's review, plus two accuracy fixes the 410 write-up turned up.

Reviewer-requested:

- Move the maturity-badge sentence above the table, so the question the
  table raises ("how do I know which one an endpoint is?") is answered
  before it is asked rather than after.
- State stable's window as 180 days. Beta was already in days, so the
  column no longer mixes units, and a month-length assumption cannot
  change what the commitment means.
- Rewrite the stable row, which said only "covered by this policy". Beta
  is covered too, so the cell distinguished nothing.
- Soften the exception. It claimed to be "the only exception" and named
  a legal obligation specifically; both are more absolute than we can
  actually promise. Same care, less cornering.
- Restore what counts as a breaking change, from the APPEX-956 draft.
  Split into what will not change without notice and what may change at
  any time, because the second half is what a caller has to build for --
  tolerate new fields, do not match on error strings.

APPEX-956 wanted that definition to be a link to the oasdiff ruleset in
APPEX-959, so it would be mechanical rather than prose. APPEX-959 is
cancelled, so prose is what is left.

Accuracy, found while writing the sunset section against the
implementation in semgrep-app#31680:

- The `Link` header is the machine-readable pointer, and it is omitted
  when a removal has no replacement. "Returns 410 with a machine-readable
  pointer to its replacement" promised it unconditionally.
- Document the sunset response itself: headers, body, and which parts are
  stable enough to parse. `error` wording is not.

semgrep-app#31680 is still a draft, so this must not publish before it
ships -- the page would describe a response nothing returns yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two claims on this page were ahead of the generator, and both are now true
rather than aspirational.

"Tagged as Deprecated" described a chip in the Change column as though it
were a filter. The filter tag was "Non-breaking", so a reader who followed
this page's advice -- subscribe, watch for what will break you -- was told
to filter for exactly the thing that hid the notice. The generator now files
deprecations as potentially breaking, so say both: what the row is marked,
and which filter it survives.

Also say that the removal itself lands in the changelog. It did not
previously; a removal that served its full notice window produced no entry
at all, which made "the changelog records every deprecation" true and
"the changelog tells you when the endpoint went away" false.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants