Skip to content

Public Surface Stability Policy

Status: Accepted (ADR-036, from 0.7 roadmap decision D6). This document is normative: release notes list breaking changes against its surface list, and changes to the promises below are made by amending this document in an ordinary reviewed PR.

Awa is consumed through several distinct surfaces. This document states, per surface, what is covered by a compatibility promise, what is explicitly internal, and what each release type may change. Anything not listed here is internal and may change in any release without notice.

Release types (pre-1.0)

While Awa is pre-1.0, "minor" releases (0.6 → 0.7) play the semver-major role:

Release type May contain
Patch (0.7.0 → 0.7.1) Bug fixes only. No breaking changes to any listed surface. No new migrations except to fix a defective migration.
Minor (0.7 → 0.8) Breaking changes to listed surfaces are allowed only with: a changelog entry under "Breaking changes", a migration path in the upgrade guide, and — where feasible — a deprecation period per the policy below.
Beta / RC Surfaces may change between pre-release tags of the same line (the 0.6 QueueFanoutPartitionedQueue rename is the precedent). Pre-release tags promise nothing to each other; the stable tag promises everything below.

Deprecation policy

Announce in release N (changelog + doc note), warn at runtime in N+1 where the surface makes a runtime warning possible, remove in N+2. Security fixes may compress this schedule; the changelog will say so explicitly.

Surfaces

Surface What is covered What is not
Rust API (awa, awa-model, awa-macros, awa-testing, awa-seaorm) All pub items documented on docs.rs. Semver enforcement in CI is planned (#402, cargo-semver-checks); until it lands, breaks are caught by review and the changelog rule below. #[doc(hidden)] items; anything behind an unstable feature flag; awa-worker/awa-ui internals not re-exported by awa.
Python API (awa-pg) Everything exported by awa/__init__.py and typed in the .pyi stubs (stub/API drift gated in CI per #378). Async and _sync counterparts per ADR-009. Underscore-prefixed members; the raw PyO3 module layout.
SQL producer contract The currently shipped awa.insert_job_compat(...) contract: signature, semantics, BLAKE3 unique_key derivation, and ordering_key shard hash, versioned against awa.schema_version. It remains covered until #342 ships awa.insert_job(...) with its contract artifacts and completes the documented migration/deprecation step. Other internal functions and direct DML against storage tables. The physical implementation behind the compatibility entry point may change without changing its covered contract.
Terminal read surface {schema}.terminal_jobs (per ADR-026) and the documented public views. done_entries physical layout and all segment/ring/ledger internals — compact batches mean not every completed job is physically a done_entries row.
HTTP admin API The documented endpoints and their response types (a typed, non-DAL response module in awa-ui#403; schemas listed in ui-design.md). The worker probe bodies (/healthz, /readyz field names, per deployment.md). A standalone awa-api crate is deferred until a second consumer exists (#143, expected with the MCP server). Handler internals; the embedded UI's asset paths; any endpoint not documented in ui-design.md.
Callback receiver contract The signed callback endpoints (ADR-018/021/027): paths under the configured prefix, signature scheme, payload shapes, error mapping. Identical between embedded router and awa callbacks serve.
CLI Documented commands, their exit codes, and --json output schemas (today: awa health, awa queue overrides show, awa storage status; awa doctor when it ships). Fatal errors render their Display guidance. Human-readable (non---json) output formatting.
Metrics Metric names, types, and attribute keys listed in the telemetry docs. Attribute values cardinality; bucket boundaries (may be tuned in minors with a changelog note).
Storage schema / migrations The migration path: awa migrate upgrades any supported prior version's schema (support window per #367 and ADR-037's gate). Schema contents. Tables, indexes, functions, and triggers are internal; migrations may reshape them freely. There is no downgrade path.
Configuration Documented QueueConfig/builder options, Python start() kwargs, and AWA_* environment variables in configuration.md. Undocumented env vars; internal tuning defaults (may change in minors with a changelog note).

Accepted designs that are not active surfaces

The table above lists shipped contracts. Accepting an ADR does not add a public surface before its implementation, documentation, conformance evidence, and release note land together:

  • #342 and ADR-043 reserve awa.insert_job(...) as the future clean, single-signature SQL producer capability. Its final opts jsonb DEFAULT '{}'::jsonb argument is the sole extension point, and PostgreSQL computes the ADR-033 concurrency digest and shard authoritatively from logical keys. Until it ships, insert_job_compat remains the covered transitional producer entry point rather than becoming internal by documentation alone.
  • ADR-042 reserves <queue_storage_schema>.complete_job(...) and its receipt/error/version semantics for caller-owned finalization. The function is not shipped and is not yet an active SQL worker surface.
  • ADR-033 adds the future domain-separated SHA-256 concurrency_key digest and ordering/concurrency shard-precedence vectors to #342's contract gate; those promises become active only with the implementing release. The digest algorithm differs from unique_key's client-side BLAKE3 (ADR-002) by design — PostgreSQL computes the concurrency digest authoritatively and has no native BLAKE3.

The implementation PR for each surface must add or replace the corresponding table row, ship the referenced conformance artifacts, and record any transition from an older covered entry point in the changelog and upgrade guide.

Reserved metadata namespace. Job metadata keys prefixed awa: are reserved for awa itself (today: awa:traceparent, ADR-039). A caller-supplied value under a documented reserved key is honored as authoritative, but awa may add, interpret, or stop writing reserved keys in any release. Keys without the prefix are user-owned and pass through untouched.

What "supported" means for binary/schema skew

Rolling deploys create windows where an older binary runs against a newer schema. The support statement, asserted nightly by scripts/compat-matrix.sh against pinned release artifacts (#367):

  • One minor behind (0.6.2 binary, 0.7 schema in columns authority): full lifecycle supported — enqueue, claim, complete, cancel — on a finalized cluster. 0.6.2 is the required stepping-stone and recognizes this exact forward-compatible schema shape. The pinned awa-pg==0.6.0 wheel remains a data-plane regression leg, but 0.6.0/0.6.1 must never invoke awa migrate on a 0.7 schema. After the one-way ring-authority flip, pre-ledger binaries are deliberately fenced and unsupported.
  • Two minors behind (0.5.x binary, finalized schema): asymmetric. Producers keep working — the awa.jobs compatibility routing sends their inserts to the active engine. Workers are inert: they claim from the canonical hot table, which is empty on a finalized cluster. Upgrade workers before or with the finalize step.
  • Newer binary, older unfinalized schema: awa migrate refuses loudly (exit non-zero, message names the exact finalize steps) rather than upgrading over live canonical work — the ADR-037 gate. Asserted against a 0.5.7-era schema carrying a canonical job; the pre-migrate-0.6 variant of this leg activates automatically once the 0.7 line ships its first migration.
  • The 0.7 boundary additionally requires a finalized queue-storage transition (ADR-037).

Relationship to release notes

Every stable release's changelog lists breaking changes against this document's surface list. If a change breaks something not listed here, it is not a breaking change — but if that surprises users repeatedly, the fix is to amend this document, not to argue.