Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/[[...path]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ function mdxComponentsForFrontMatter(frontMatter: Record<string, unknown>) {
const boundProps = {
version: String(frontMatter.spec_version),
status: frontMatter.spec_status,
guidelines: frontMatter.spec_guidelines
? String(frontMatter.spec_guidelines)
: undefined,
kind: frontMatter.spec_kind ? String(frontMatter.spec_kind) : undefined,
};
specOverrides.SpecMeta = function () {
return <SpecMeta {...boundProps} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Aligning Cross-SDK Changes
spec_id: sdk/playbooks/aligning-cross-sdk-changes
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/coordination-maintenance
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Project Management in Linear
spec_id: sdk/playbooks/managing-linear-projects
spec_version: 1.0.0
spec_status: draft
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/planning-scoping
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Quarterly Cross-SDK Retro
spec_id: sdk/playbooks/quarterly-cross-sdk-retro
spec_version: 1.0.0
spec_status: draft
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/coordination-maintenance
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Triaging
spec_id: sdk/playbooks/triaging
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/coordination-maintenance
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Adding a Dependency
spec_id: sdk/playbooks/adding-a-dependency
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/code-quality
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Handling a Regression
spec_id: sdk/playbooks/handling-a-regression
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/coordination-maintenance
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Handling an External Contributor Pull Request
spec_id: sdk/playbooks/handling-external-contributor-pr
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/review-ci
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Opening a Pull Request
spec_id: sdk/playbooks/opening-a-pr
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/code-submission
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Reviewing a Pull Request
spec_id: sdk/playbooks/reviewing-a-pr
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/review-ci
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Reviewing AI-Generated Code
spec_id: sdk/playbooks/reviewing-ai-generated-code
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/review-ci
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Syncing Feature Branches
spec_id: sdk/playbooks/syncing-feature-branches
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_changelog:
- version: 1.0.0
date: 2026-02-21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Introducing Breaking Changes
spec_id: sdk/playbooks/breaking-changes
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/api-architecture
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Cutting a Release
spec_id: sdk/playbooks/cutting-a-release
spec_version: 1.1.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/review-ci
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Deprecating an API
spec_id: sdk/playbooks/deprecating-an-api
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/api-architecture
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Deprecating an SDK
spec_id: sdk/playbooks/deprecating-an-sdk
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/api-architecture
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Dropping Platform or Language Version Support
spec_id: sdk/playbooks/dropping-platform-support
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/api-architecture
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Setting Up a New SDK Repository
spec_id: sdk/playbooks/setting-up-new-sdk-repo
spec_version: 1.0.0
spec_status: candidate
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/repository-docs
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Setting Up Release Infrastructure
spec_id: sdk/playbooks/release-infrastructure
spec_version: 1.0.0
spec_status: stable
spec_kind: process
spec_depends_on:
- id: sdk/getting-started/standards/release-versioning
version: ">=1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: API and Architecture
spec_id: sdk/getting-started/standards/api-architecture
spec_version: 1.0.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Code Quality
spec_id: sdk/getting-started/standards/code-quality
spec_version: 1.0.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Code Submission
spec_id: sdk/getting-started/standards/code-submission
spec_version: 1.2.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Coordination and Maintenance
spec_id: sdk/getting-started/standards/coordination-maintenance
spec_version: 1.0.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Planning and Scoping
spec_id: sdk/getting-started/standards/planning-scoping
spec_version: 1.0.0
spec_status: draft
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Release and Versioning
spec_id: sdk/getting-started/standards/release-versioning
spec_version: 1.0.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Repository and Documentation
spec_id: sdk/getting-started/standards/repository-docs
spec_version: 1.1.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
1 change: 1 addition & 0 deletions develop-docs/sdk/getting-started/standards/review-ci.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Review and CI
spec_id: sdk/getting-started/standards/review-ci
spec_version: 1.1.0
spec_status: stable
spec_kind: process
spec_platforms:
- all
spec_changelog:
Expand Down
2 changes: 2 additions & 0 deletions develop-docs/sdk/getting-started/standards/spec-lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Each spec is an MDX page with frontmatter that drives the status badge, version,
| `spec_depends_on` | no | Other specs this one relies on, each `{id, version}` with a SemVer range. |
| `spec_platforms` | no | Platforms the spec applies to; defaults to `all`. |
| `spec_superseded_by` | no | `spec_id` of the replacement spec. Set when `deprecated`. |
| `spec_guidelines` | no | Declares conformance to [Writing SDK Specs](/sdk/getting-started/standards/writing-specs/), e.g. `writing-specs@0.1`. Shown next to the version. Specs without it show a legacy notice, unless `spec_kind` is `process`. |
| `spec_kind` | no | Set to `process` for specs that set rules for how SDK teams work, such as playbooks and engineering standards, rather than for how SDKs behave. Process specs are out of scope for Writing SDK Specs and show no legacy notice. |

A spec's body is divided into `<SpecSection>` blocks, each with its own `status`, a `since` version marking when its current requirements landed, and an optional `superseded_by` link. Sections **MAY** advance independently — a `stable` spec can still contain a `candidate` section that's gathering feedback.

Expand Down
122 changes: 122 additions & 0 deletions develop-docs/sdk/getting-started/standards/writing-specs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
title: Writing SDK Specs
description: How to write SDK specs that only require externally observable behavior and use requirement keywords sparingly.
spec_id: sdk/getting-started/standards/writing-specs
spec_version: 0.1.0
spec_status: draft
spec_guidelines: writing-specs@0.1
spec_changelog:
- version: 0.1.0
date: 2026-10-19
summary: Initial draft
sidebar_order: 0
---

<SpecRfcAlert />

<SpecMeta />

SDK specs define what SDKs do, not how they do it. This spec builds on [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and adds only what is specific to Sentry SDK specs.

## Scope

This spec applies to itself and to all specs except process specs. Its [Legacy Specs](#legacy-specs) section also applies to SDKs that implement legacy specs. Status, versioning, changelogs, and frontmatter fields are covered by [Spec Lifecycle](/sdk/getting-started/standards/spec-lifecycle/).

## Definitions

- **Spec**: a page under `develop-docs/sdk/` with `spec_id` frontmatter.
- **Requirement**: a statement in a spec that uses, rather than mentions, an RFC 2119 keyword written in uppercase, such as "MUST", "SHOULD", or "MAY". Keywords have the meaning defined in RFC 2119.
- **Non-normative content**: anything in a spec that is not a requirement.
- **Externally observable behavior**: behavior whose conformance can be determined without inspecting the implementation's internals. For an SDK, conformance is determined using only its public API, the data it sends, its calls into user code, its effects on the host application, and its responses to inputs.
- **Process spec**: a spec with `spec_kind: process` in its frontmatter. Process specs, such as playbooks and engineering standards, set rules for how SDK teams work rather than for how SDKs behave.
- **Legacy spec**: a spec, other than a process spec, without `spec_guidelines` in its frontmatter.

## Requirements

<SpecSection id="keywords" status="draft" since="0.1.0">

### Keywords

Keywords **SHOULD** be bold. A keyword that is mentioned rather than used **SHOULD** be put in quotes. Non-normative content **SHOULD NOT** state obligations with lowercase "must", "should", "may", or phrases such as "needs to".

</SpecSection>

<SpecSection id="observable-behavior" status="draft" since="0.1.0">

### Observable Behavior

Requirements **MUST** only describe externally observable behavior. When a requirement is written as steps, SDKs **MAY** produce its observable result in any other way.

</SpecSection>

<SpecSection id="requirement-levels" status="draft" since="0.1.0">

### Requirement Levels

Requirements **MUST** follow [Section 6 of RFC 2119](https://www.rfc-editor.org/rfc/rfc2119#section-6):

> Imperatives of the type defined in this memo must be used with care and sparingly. In particular, they MUST only be used where it is actually required for interoperation or to limit behavior which has potential for causing harm (e.g., limiting retransmisssions) For example, they must not be used to try to impose a particular method on implementors where the method is not required for interoperability.

In addition, requirements **MAY** specify an SDK's public API. Such requirements **SHOULD** allow SDKs to adapt names, signatures, and types to their platform's conventions.

Requirements **SHOULD** use "SHOULD" by default, and "MUST" or "MUST NOT" only where no SDK could have a valid reason to deviate. Authors **SHOULD** assume such a reason could exist unless shown otherwise.

A requirement that most SDKs do not implement yet **SHOULD** be placed in a `draft` or `candidate` section (see [Spec Lifecycle](/sdk/getting-started/standards/spec-lifecycle/)), not weakened.

</SpecSection>

<SpecSection id="concision" status="draft" since="0.1.0">

### Concision

Specs **SHOULD** be as concise as possible without losing necessary detail. They **SHOULD NOT** repeat requirements or include content readers don't need, such as snippets or examples that only restate requirements.

</SpecSection>

<SpecSection id="clarity" status="draft" since="0.1.0">

### Clarity

Specs **SHOULD NOT** be vague or ambiguous, so that readers agree on what each requirement means and whether an SDK conforms to it. This can conflict with _Concision_. Specs **SHOULD** balance the two, adding words only where they remove doubt.

</SpecSection>

<SpecSection id="structure" status="draft" since="0.1.0">

### Structure

A spec **SHOULD** contain, in this order:

- A short summary of the spec.
- _Scope_: what the spec applies to, such as all SDKs or only some.
- _Definitions_: terms with a spec-specific meaning. This section **MAY** be omitted if there are no terms which need to be defined.
- _Requirements_: all requirements.
- _Implementation Guidance_: patterns that are not documented elsewhere and that implementers would likely get wrong without guidance. This section is non-normative and **SHOULD NOT** be included if no such patterns need to be documented.
- _Changelog_: as required by Spec Lifecycle.

</SpecSection>

<SpecSection id="legacy-specs" status="draft" since="0.1.0">

### Legacy Specs

A spec that conforms to this spec **SHOULD** declare it in its frontmatter with `spec_guidelines: writing-specs@<major.minor>`. A spec **MUST NOT** declare it unless the whole spec conforms.

SDKs **MAY** deviate from requirements in a legacy spec on behavior that is not externally observable, but **SHOULD** preserve the externally observable behavior that results from them.

</SpecSection>

## Implementation Guidance

**The black-box test.** Ask: "Could I check this against a mock transport and the public API, without opening the SDK's source?" If not, it isn't a requirement. Usually the observable intent can be kept:

- "Use a single, centralized `ClientReports` component per client" → "Discarded events are reported in the client report of the client that discarded them."
- "Aggregate counts in a map keyed by reason and category" → "Each client report contains at most one entry per (reason, category) pair."

**The Section 6 test.** Ask: "Is this part of the public API? If not, would Sentry reject or misread data if an SDK ignored it, would SDKs fail to work together, or would users be harmed?" If none apply, it isn't a requirement. Outside the public API, consistency across SDKs alone is not a reason for a requirement.

**Migrating a legacy spec.** Rewrite the observable intent as requirements and delete everything else unless it qualifies as _Implementation Guidance_ (see [Structure](#structure)). Don't add requirements, and list every requirement whose level or meaning changed in the changelog entry.

## Changelog

<SpecChangelog />
26 changes: 25 additions & 1 deletion src/components/specMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@
type SpecMetaProps = {
status: SpecStatus;
version: string;
/** Value of the `spec_guidelines` frontmatter field, e.g. `writing-specs@0.1`. */
guidelines?: string;
/** Value of the `spec_kind` frontmatter field. `process` specs are not subject to the guidelines. */
kind?: string;
};

export function SpecMeta({version, status}: SpecMetaProps) {
const WRITING_SPECS_PATH = '/sdk/getting-started/standards/writing-specs/';

export function SpecMeta({version, status, guidelines, kind}: SpecMetaProps) {
const badgeClass = SPEC_STATUS_BADGE[status];
const isProcessSpec = kind === 'process';
// `spec_guidelines` is `writing-specs@<major.minor>`; show just the version.
const guidelinesVersion = guidelines?.match(/^writing-specs@(.+)$/)?.[1];

return (
<div className="not-prose mb-8 rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm dark:border-gray-700 dark:bg-gray-900">
Expand All @@ -20,7 +29,7 @@
>
{status}
</span>
<a

Check warning on line 32 in src/components/specMeta.tsx

View workflow job for this annotation

GitHub Actions / Lint

Do not use an `<a>` element to navigate to `/sdk/getting-started/standards/spec-lifecycle/`. Use `<Link />` from `next/link` instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages
href="/sdk/getting-started/standards/spec-lifecycle"
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
aria-label="Learn about spec statuses"
Expand All @@ -42,6 +51,21 @@
</a>
</div>
</div>
{guidelines && (
<p className="mt-3 mb-0 text-gray-600 dark:text-gray-400">
Follows <a href={WRITING_SPECS_PATH}>Writing SDK Specs</a>
{guidelinesVersion ? ` version ${guidelinesVersion}` : ` (${guidelines})`}.
</p>
)}
{!guidelines && !isProcessSpec && (
<p className="mt-3 mb-0 text-gray-600 dark:text-gray-400">
This spec predates the{' '}
<a href={`${WRITING_SPECS_PATH}#legacy-specs`}>spec writing guidelines</a> and
does not follow them yet. Requirements on behavior that is not externally
observable are not mandatory, but SDKs should preserve the observable behavior
that results from them.
</p>
)}
</div>
);
}
Loading