Platform-agnostic specifications for PostHog SDK capabilities — the canonical contract every SDK must satisfy so behavior stays on par across platforms (Android, iOS, React Native, JavaScript/Web, Flutter, …).
This repo holds specs and proposals only — no SDK code. Implementations live in their own
repos (posthog-android, posthog-ios, posthog-js, posthog-flutter, …). Each spec here is
the canonical behavior derived from the shipped implementations plus the relevant backend
service, stating the winner wherever SDKs currently diverge.
The acceptance/ directory contains Gherkin feature files for cross-SDK acceptance tests.
acceptance/public/ covers public SDK API behavior, while acceptance/private/ covers
shared internal SDK behavior such as batching, storage, feature flags, sessions, and replay.
Tags on each feature indicate whether scenarios apply to client SDKs, server SDKs, or both.
| Capability | Spec | Scope | Status |
|---|---|---|---|
| Logs | openspec/specs/logs/spec.md |
product | Canonical |
| Traces | openspec/specs/traces/spec.md |
product | Canonical |
| Tracing Headers | openspec/specs/tracing-headers/spec.md |
cross-SDK correlation | Canonical |
| Alias | openspec/specs/alias/spec.md |
public API | Canonical |
| Capture | openspec/specs/capture/spec.md |
public API | Canonical |
| Capture Exception | openspec/specs/capture-exception/spec.md |
public API | Canonical |
| Create Person Profile | openspec/specs/create-person-profile/spec.md |
public API | Canonical |
| Debug | openspec/specs/debug/spec.md |
public API | Canonical |
| Exception Steps | openspec/specs/exception-steps/spec.md |
public API | Canonical |
| Flush | openspec/specs/flush/spec.md |
public API | Canonical |
| Get Anonymous ID | openspec/specs/get-anonymous-id/spec.md |
public API | Canonical |
| Get Distinct ID | openspec/specs/get-distinct-id/spec.md |
public API | Canonical |
| Get Feature Flag | openspec/specs/get-feature-flag/spec.md |
public API | Canonical |
| Get Feature Flag Payload | openspec/specs/get-feature-flag-payload/spec.md |
public API | Canonical |
| Get Feature Flag Result | openspec/specs/get-feature-flag-result/spec.md |
public API | Canonical |
| Get Feature Flags | openspec/specs/get-feature-flags/spec.md |
public API | Canonical |
| Get Feature Flags And Payloads | openspec/specs/get-feature-flags-and-payloads/spec.md |
public API | Canonical |
| Get Session ID | openspec/specs/get-session-id/spec.md |
public API | Canonical |
| Group | openspec/specs/group/spec.md |
public API | Canonical |
| Group Identify | openspec/specs/group-identify/spec.md |
public API | Canonical |
| Identify | openspec/specs/identify/spec.md |
public API | Canonical |
| Is Feature Enabled | openspec/specs/is-feature-enabled/spec.md |
public API | Canonical |
| Is Opt Out | openspec/specs/is-opt-out/spec.md |
public API | Canonical |
| Is Session Replay Active | openspec/specs/is-session-replay-active/spec.md |
public API | Canonical |
| On Feature Flags | openspec/specs/on-feature-flags/spec.md |
public API | Canonical |
| Opt In | openspec/specs/opt-in/spec.md |
public API | Canonical |
| Register | openspec/specs/register/spec.md |
public API | Canonical |
| Reload Feature Flags | openspec/specs/reload-feature-flags/spec.md |
public API | Canonical |
| Reset | openspec/specs/reset/spec.md |
public API | Canonical |
| Reset Group Properties For Flags | openspec/specs/reset-group-properties-for-flags/spec.md |
public API | Canonical |
| Reset Person Properties For Flags | openspec/specs/reset-person-properties-for-flags/spec.md |
public API | Canonical |
| Screen | openspec/specs/screen/spec.md |
public API | Canonical |
| Set Group Properties For Flags | openspec/specs/set-group-properties-for-flags/spec.md |
public API | Canonical |
| Set Person Properties | openspec/specs/set-person-properties/spec.md |
public API | Canonical |
| Set Person Properties For Flags | openspec/specs/set-person-properties-for-flags/spec.md |
public API | Canonical |
| Setup | openspec/specs/setup/spec.md |
public API | Canonical |
| Shutdown | openspec/specs/shutdown/spec.md |
public API | Canonical |
| Start Session Recording | openspec/specs/start-session-recording/spec.md |
public API | Canonical |
| Stop Session Recording | openspec/specs/stop-session-recording/spec.md |
public API | Canonical |
| Unregister | openspec/specs/unregister/spec.md |
public API | Canonical |
| Application Lifecycle | openspec/specs/application-lifecycle/spec.md |
internal behavior | Canonical |
| Autocapture | openspec/specs/autocapture/spec.md |
internal behavior | Canonical |
| Before Send Hook | openspec/specs/before-send-hook/spec.md |
internal behavior | Canonical |
| Consent Gating | openspec/specs/consent-gating/spec.md |
internal behavior | Canonical |
| Device ID Generator | openspec/specs/device-id-generator/spec.md |
internal behavior | Canonical |
| Event Batcher | openspec/specs/event-batcher/spec.md |
internal behavior | Canonical |
| Feature Flag Cache | openspec/specs/feature-flag-cache/spec.md |
internal behavior | Canonical |
| Feature Flag Called Tracker | openspec/specs/feature-flag-called-tracker/spec.md |
internal behavior | Canonical |
| Flag Definition Loader | openspec/specs/flag-definition-loader/spec.md |
internal behavior | Canonical |
| HTTP Client | openspec/specs/http-client/spec.md |
internal behavior | Canonical |
| Local Feature Flag Evaluator | openspec/specs/local-feature-flag-evaluator/spec.md |
internal behavior | Canonical |
| Persistent Storage | openspec/specs/persistent-storage/spec.md |
internal behavior | Canonical |
| Remote Config | openspec/specs/remote-config/spec.md |
internal behavior | Canonical |
| Retry Queue | openspec/specs/retry-queue/spec.md |
internal behavior | Canonical |
| Session Manager | openspec/specs/session-manager/spec.md |
internal behavior | Canonical |
| Session Replay Ingestion Controls | openspec/specs/session-replay-ingestion-controls/spec.md |
internal behavior | Canonical |
| Session Replay Privacy | openspec/specs/session-replay-privacy/spec.md |
internal behavior | Canonical |
| Surveys | openspec/specs/surveys/spec.md |
internal behavior | Canonical |
Each capability is one folder under openspec/specs/<capability>/. A new capability is a new
sibling folder — never folded into an existing spec.
This repo uses OpenSpec for spec-driven development. Install the CLI to propose and validate changes:
npm install -g @fission-ai/openspec # provides the `openspec` command + /opsx slash commandsThe source of truth is openspec/specs/<capability>/spec.md. You never hand-edit it — you
propose a change, implement it, and archiving syncs the change into the spec.
openspec/
├── project.md project context + conventions
├── specs/<capability>/spec.md current truth (one folder per capability)
└── changes/ in-flight proposals; archive/ holds finished ones
Workflow (OpenSpec CLI + /opsx slash commands):
- Propose —
/opsx:propose add-<capability>(oropenspec new change "<name>"). Createschanges/<name>/withproposal.md,design.md,tasks.md, and a delta spec underchanges/<name>/specs/<capability>/spec.md. - Apply —
/opsx:applyto work throughtasks.md. - Archive —
/opsx:archivesyncs the delta intospecs/<capability>/spec.mdand moves the change tochanges/archive/YYYY-MM-DD-<name>/.
All three steps happen on one branch: once review approves the proposal, apply and archive on the same PR so it merges already archived.
Two kinds of change:
- New capability →
add-<capability>(e.g.add-feature-flags) creates a new spec folder. - Porting a capability to a new SDK →
add-<capability>-<platform>(e.g.add-logs-android), a delta measured against the existing contract.
### Requirement: Public capture API
The SDK SHALL expose ...
#### Scenario: missing level defaults to info
- **WHEN** the app calls `captureLog({ body: "hello" })` with no level
- **THEN** the record has severityNumber 9 (`INFO`)Every requirement needs at least one scenario. Validate with:
openspec validate --specs --strictConformance matrix (per-SDK parity against each spec) — TODO. Track which SDKs satisfy each requirement and where they currently diverge.