From f405d7944657254f89429df9a0140a5ca7929b7e Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 25 Sep 2026 10:35:48 +0000 Subject: [PATCH 1/2] docs(reporting): document upgrade boundaries and guarded release steps --- MIGRATION_v7_to_v8.md | 7 + RELEASING.md | 402 +++++++---------------------- docs/releasing.md | 15 +- docs/reliable-reporting-service.md | 6 + docs/reporting-production.md | 10 +- docs/reporting-release-notes.md | 140 ++++++++++ 6 files changed, 259 insertions(+), 321 deletions(-) create mode 100644 docs/reporting-release-notes.md diff --git a/MIGRATION_v7_to_v8.md b/MIGRATION_v7_to_v8.md index 706194ac9..5c84253ac 100644 --- a/MIGRATION_v7_to_v8.md +++ b/MIGRATION_v7_to_v8.md @@ -1,5 +1,12 @@ # Migrating from Python SDK 7 to 8 +For the upcoming Reliable Reporting prerelease, read the +[reporting upgrade and release notes](docs/reporting-release-notes.md) before +deploying. They cover the account-qualified `generation_key` API change, +PostgreSQL drain/migration/activation sequence, all nine historical comparison +boundaries, and the distinction between offline schemas and live rc.6 mounts. +Final package and full-rollout qualification remain pending. + SDK 8 beta also updates the generated protocol surface from AdCP 3.1.15 to AdCP 3.2.0-beta.4 and adds the compact product/media-buy lifecycle. The old 3.x lifecycle remains supported. See diff --git a/RELEASING.md b/RELEASING.md index de8d2cc8b..6474cf9de 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,333 +1,105 @@ # Releasing adcp-client-python -This project uses [Release Please](https://github.com/googleapis/release-please) for automated versioning and releases. It's the Python equivalent of Changesets but works per-PR instead of per-commit. - -## Spec-version pinning for major releases - -**Read this before cutting any major SDK version (e.g. 3.x → 4.x, 4.x → 5.x).** - -The SDK's generated Pydantic types in `src/adcp/types/generated_poc/` are built from the AdCP spec bundle fetched at build time. Which bundle gets fetched is pinned by `src/adcp/ADCP_VERSION`: - -- **`latest`** (default on `main`): tracks spec HEAD. Types drift between regens. Safe for rolling development; **never** safe for a stable release — buyers on that version would see types mutate under them at the next regen. -- **`3.0.0`** (or any semver tag): pinned to a specific spec release. Stable. What you want to ship. - -### Release-day checklist - -Execute in this order. All commands run from repo root. - -1. **Confirm upstream spec is tagged.** The spec repo publishes a bundle at `https://adcontextprotocol.org/protocol/{version}.tgz`. Check it returns 200: - - ```bash - curl -sI "https://adcontextprotocol.org/protocol/3.0.0.tgz" | head -1 - # Expected: HTTP/2 200 - ``` - - If 404, the spec isn't tagged yet — abort the release. - -2. **Pin `ADCP_VERSION`:** - - ```bash - echo "3.0.0" > src/adcp/ADCP_VERSION - ``` - -3. **Regenerate schemas + types:** - - ```bash - make regenerate-schemas - ``` - - This fetches the pinned bundle, rewrites `schemas/cache/`, regenerates `src/adcp/types/generated_poc/` + `_generated.py` + `_ergonomic.py`, and updates `schemas/cache/index.json.adcp_version` to match `ADCP_VERSION`. - -4. **Run the full pre-push check:** - - ```bash - make pre-push - ``` - - Includes `tests/test_schemas_version_pin.py` — a paranoia check that `ADCP_VERSION` matches `schemas/cache/index.json.adcp_version`. If you skipped step 3, this fires. - -5. **Review the diff.** Expect `schemas/cache/*`, `src/adcp/types/generated_poc/*`, `_generated.py`, `_ergonomic.py`, and `src/adcp/ADCP_VERSION` to change. Anything else means a regen script mutated source — investigate. - -6. **Commit + open PR:** - - ```bash - git checkout -b bokelley/pin-spec-X.Y.Z - git add -A - git commit -m "chore(types): pin AdCP spec to X.Y.Z and regenerate" - gh pr create --title "chore(types): pin AdCP spec to X.Y.Z" - ``` - -7. **Merge the spec-pin PR.** Release Please's open release PR (`chore(main): release X.Y.Z`) will pick up the new commit; review the updated changelog. - -8. **Merge the release PR** (`chore(main): release X.Y.Z`). PyPI publish + GitHub release + tag happen automatically. - -### Reverting to `latest` - -After a stable release ships, `main` typically stays pinned until the next spec drop. To resume tracking HEAD: - -```bash -echo "latest" > src/adcp/ADCP_VERSION +Use the [guarded release runbook](docs/releasing.md) for the release procedure, +operator prerequisites, evidence requirements and recovery. Release Please +prepares the version and changelog in a normal pull request; publication is a +separate, protected operation after that PR is merged and its exact main +commit is accepted. + +The legacy `.github/workflows/release-please.yml` is retired and must remain +disabled. The guarded publisher uses PyPI Trusted Publishing. Do not follow +older instructions to enable the legacy workflow, add a PyPI API token, or +upload locally rebuilt distributions as a fallback. + +## Prepare the release + +1. Integrate reviewed changes using concrete conventional commit subjects. + Describe public breaking changes with `!` and a `BREAKING CHANGE:` footer. +2. Complete acceptance on the actual integrated main commit, including the + applicable installed-artifact and interoperability checks. For the reporting + rollout, carry the [upgrade and release notes](docs/reporting-release-notes.md) + into the release proposal, including all nine historical comparison limits. +3. Complete the runbook's environment, proposal App, PyPI trust, historical + workflow retirement and release-tag prerequisites. Freeze main only for + the controlled proposal or publication window, after integration. +4. Use `release-proposal.yml` with the exact current-main SHA and successful + main-push CI run and attempt. Its acceptance and protected environment gate + precede creation or update of the Release Please PR. A proposal creates + neither a release tag nor a PyPI upload. +5. Review the generated version, manifest, changelog and normalized Python + package version. Merge the release PR through the repository's normal + review and check requirements after the proposal window has drained and + its main freeze has been removed. +6. Obtain fresh CI and acceptance for the release PR's actual main merge + commit. Establish a new freeze and target-bound attestation, then use + `release-publish.yml` with that commit, CI run/attempt and release PR number. + Environment approval and final gate checks precede publication of the + accepted distribution bytes and creation of the exact tag/release. +7. Verify registry package versions, hashes and a clean installed consumer. + If publication stops partway through, use the runbook's guarded recovery + procedure with the original accepted bytes. + +This overview does not establish that the reporting rollout or external +publishing configuration is ready. The final guard integration, exact-main +acceptance and operator prerequisites remain release gates. + +## Protocol version and generated types + +`src/adcp/ADCP_VERSION` pins the protocol inputs used to generate the SDK's +types. A prerelease protocol pin is appropriate for an SDK prerelease; a +stable SDK release requires the separately reviewed stable protocol adoption. +Do not cut a stable release from a moving `latest` pin. + +When changing the protocol pin, use the repository's signed-input update +procedure, regenerate schemas and types, and run the complete checks: + +```sh make regenerate-schemas +make pre-push ``` -Commit as `chore(types): resume tracking spec HEAD after X.Y.Z release`. - -### Drift protection - -`tests/test_schemas_version_pin.py` cross-checks `ADCP_VERSION` against `schemas/cache/index.json.adcp_version` on every CI run. You cannot merge a PR where the two drift — which means you cannot accidentally ship stable types generated from `latest` or vice versa. - -## How It Works - -1. **Write Conventional Commits**: Use conventional commit messages in your PRs -2. **Automatic PR**: Release Please creates a "release PR" that updates version and CHANGELOG -3. **Merge to Release**: When you merge the release PR, it creates a GitHub release and publishes to PyPI - -## Conventional Commits - -Release Please determines version bumps based on commit message prefixes: - -### Breaking Changes (Major Version: 1.0.0 → 2.0.0) -```bash -feat!: remove deprecated API -# or -feat: add new feature - -BREAKING CHANGE: removed old API -``` - -### New Features (Minor Version: 0.1.0 → 0.2.0) -```bash -feat: add support for new protocol -feat(client): add retry logic -``` - -### Bug Fixes (Patch Version: 0.1.0 → 0.1.1) -```bash -fix: resolve authentication issue -fix(mcp): handle connection timeout -``` - -### Other Types (No Version Bump) -```bash -docs: update README -chore: update dependencies -test: add integration tests -refactor: simplify adapter code -style: format code -ci: update GitHub Actions -``` - -## Release Process - -### 1. Development - -Work on features using conventional commits: - -```bash -git checkout -b feature/my-feature -# Make changes -git commit -m "feat: add new AdCP tool support" -git push origin feature/my-feature -# Create PR -``` - -### 2. Automatic Release PR - -When PRs are merged to `main`, Release Please: -- Analyzes commits since last release -- Determines version bump (major/minor/patch) -- Creates/updates a "Release PR" with: - - Updated `pyproject.toml` version - - Generated CHANGELOG.md - - Git tag - -Example Release PR title: `chore(main): release 0.2.0` - -### 3. Release - -When you merge the Release PR, it automatically: -- Creates a GitHub release with changelog -- Publishes package to PyPI -- Tags the commit - -## PyPI Publishing Setup - -### Required: PyPI API Token - -1. Create account on https://pypi.org -2. Generate API token at https://pypi.org/manage/account/token/ -3. Add to GitHub Secrets as `PYPI_API_TOKEN`: - - Go to repository → Settings → Secrets → Actions - - New repository secret - - Name: `PYPI_API_TOKEN` - - Value: `pypi-...` (your token) - -### Package Metadata - -Configured in `pyproject.toml`: - -```toml -[project] -name = "adcp" -version = "0.1.0" # Updated by Release Please -description = "Official Python client for the Ad Context Protocol (AdCP)" -authors = [{name = "AdCP Community", email = "maintainers@adcontextprotocol.org"}] -``` - -## Version Numbering - -We follow [Semantic Versioning](https://semver.org/): - -- **Major (1.0.0)**: Breaking changes -- **Minor (0.1.0)**: New features, backward compatible -- **Patch (0.0.1)**: Bug fixes, backward compatible - -### Stable Release Behavior - -Release Please now uses normal SemVer versioning. Keep -`release-please-config.json` and `.release-please-manifest.json` as the source -of truth for automated releases, and do not pass `release-type` directly in -`.github/workflows/release-please.yml`; that bypasses the manifest -configuration. +Review the resulting cache, generated model and provenance changes together +with the pin. See [signed AdCP inputs](docs/protocol-3.2-rc6.md) for the current +protocol and historical bundle policy. A successful download alone does not +establish signed provenance or installed-package contents. -### Pre-1.0 Behavior +## Versioning and commit subjects -Before v1.0.0: -- Breaking changes bump MINOR version (0.1.0 → 0.2.0) -- New features bump MINOR version -- Bug fixes bump PATCH version +`release-please-config.json` and `.release-please-manifest.json` control release +versioning. Review the proposal's exact version and PEP 440 normalization; +changing only `pyproject.toml` is not a release procedure. The current +configuration is for prereleases, so do not infer the next version from normal +stable SemVer examples. -Configured with `bump-minor-pre-major: true` in release-please-config.json. +Use concrete conventional subjects, for example: -## Manual Release (Fallback) - -If you need to release manually: - -```bash -# 1. Update version in pyproject.toml -vim pyproject.toml - -# 2. Build package -python -m build - -# 3. Upload to PyPI -twine upload dist/* -``` - -## Examples - -### Example 1: Feature Release - -```bash -# PR merged with commits: -feat: add webhook signature verification -fix: handle MCP timeout gracefully - -# Release Please creates PR: -# - Version: 0.1.0 → 0.2.0 (feat = minor bump) -# - CHANGELOG updated with both changes +```text +feat(reporting): add authenticated receipt ingress +fix(reporting): preserve the account on configuration leases +docs(reporting): explain activation and upgrade boundaries ``` -### Example 2: Bug Fix Release +For a breaking change, describe the required migration: -```bash -# PR merged with commits: -fix: correct A2A endpoint URL -docs: update README +```text +fix(reporting)!: scope configuration generations by account -# Release Please creates PR: -# - Version: 0.2.0 → 0.2.1 (fix = patch bump) -# - CHANGELOG shows fix (docs ignored) +BREAKING CHANGE: generation_key returns ReportingConfigurationGenerationKey; +replace tuple indexing with its named account/configuration/version fields. ``` -### Example 3: Breaking Change - -```bash -# PR merged with commit: -feat!: require Python 3.10+ - -BREAKING CHANGE: Dropped Python 3.9 support - -# Release Please creates PR: -# - Version: 0.2.1 → 0.3.0 (breaking = minor pre-1.0) -# - CHANGELOG highlights breaking change -``` - -## Tips - -### Good Commit Messages - -✅ **Do**: -```bash -feat(mcp): add session pooling -fix(a2a): correct message format -docs: add MCP examples -test: add protocol adapter tests -``` - -❌ **Don't**: -```bash -update code -fix bug -changes -wip -``` - -### Combining Changes - -Multiple changes in one PR: - -```bash -feat: add new tool support -fix: resolve connection issue - -# Release Please will: -# - Bump MINOR (feat takes precedence) -# - List both in CHANGELOG under appropriate sections -``` - -### Skip Release - -To prevent a PR from triggering a release: - -```bash -chore: update dev dependencies - -Release-As: false -``` - -Or use types that don't trigger releases: `docs`, `chore`, `style`, `test` - -## Monitoring - -### Check Release Status - -- **Release PR**: https://github.com/your-org/adcp-client-python/pulls - - Look for "chore(main): release x.y.z" -- **Published Releases**: https://github.com/your-org/adcp-client-python/releases -- **PyPI Package**: https://pypi.org/project/adcp/ - -### Troubleshooting - -**Release PR not created?** -- Check commits use conventional format -- Ensure commits are on `main` branch -- Verify GitHub Actions are enabled - -**PyPI publish failed?** -- Check `PYPI_API_TOKEN` secret is set -- Verify token has upload permissions -- Check package name is available on PyPI +Documentation commits may not generate their own changelog entries. Preserve +the required migration and compatibility notes when reviewing the actual +release proposal even when Release Please does not select them automatically. -**Wrong version bump?** -- Review commit message prefixes -- Use `feat!:` or `BREAKING CHANGE:` for breaking changes -- Remember pre-1.0 treats breaking as minor bump +## Status and troubleshooting -## Resources +Check the repository's [release PRs](https://github.com/adcontextprotocol/adcp-client-python/pulls), +[workflow runs](https://github.com/adcontextprotocol/adcp-client-python/actions) +and [published releases](https://github.com/adcontextprotocol/adcp-client-python/releases), +then the [PyPI package](https://pypi.org/project/adcp/). -- [Release Please](https://github.com/googleapis/release-please) -- [Conventional Commits](https://www.conventionalcommits.org/) -- [Semantic Versioning](https://semver.org/) -- [Python Packaging](https://packaging.python.org/) -- [Uploading to PyPI](https://packaging.python.org/tutorials/packaging-projects/) +If a proposal or publication is blocked, inspect the selected run's exact +target, CI attempt, acceptance result and environment approval. Follow the +runbook for missing operator configuration or recovery; neither a skipped +check nor a previous commit's successful build qualifies the current target. diff --git a/docs/releasing.md b/docs/releasing.md index e84d21ca8..8bd946e79 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,9 +1,16 @@ # Releasing the Python SDK -The #1198 guard is implemented independently and **must merge last, after the -reporting stack and #1172**. Rebase, review the installed acceptance suite against -the integrated reporting contract, and validate the final exact head before -merging. This implementation does not authorize stack integration or publication. +The guarded workflow entry points are present. **Final guard corrections and +acceptance integration must land after the reporting implementation and #1172**. +Review the installed acceptance suite against the final reporting contract and +validate that exact head before publication. This runbook describes the gate; +it does not establish that implementation, interoperability or operator setup +has been accepted. + +Include the [Reliable Reporting upgrade notes](reporting-release-notes.md) in +the reviewed release proposal, preserving all nine historical comparison +boundaries and the live/offline protocol distinction. The +[release overview](../RELEASING.md) explains version and changelog preparation. Workflow **204238826**, `.github/workflows/release-please.yml`, stays `disabled_manually` permanently. Its new definition is a failing tombstone. diff --git a/docs/reliable-reporting-service.md b/docs/reliable-reporting-service.md index 5f3f5e059..068455823 100644 --- a/docs/reliable-reporting-service.md +++ b/docs/reliable-reporting-service.md @@ -6,6 +6,12 @@ and fetches one frozen slice; the SDK owns staging, replay seals, obligation creation, immutable revisions, snapshot refresh and official close, status, exact revision reads, capability advertisement, and worker lifecycle. +For an upgrade, begin with the +[reporting release notes and deployment boundaries](reporting-release-notes.md) +and the [production composition guide](reporting-production.md). The examples +below explain the service API; complete service and cross-language release +acceptance remain pending. + The minimum adapter has no AdCP transport methods: ```python diff --git a/docs/reporting-production.md b/docs/reporting-production.md index a3ff86e67..581106c5c 100644 --- a/docs/reporting-production.md +++ b/docs/reporting-production.md @@ -6,6 +6,11 @@ receipt ingress and frozen feed with versioned private status. Use typed composition and authenticated MCP/A2A lifecycle. Existing Core polling and eligible Core notification deployments keep their existing composition. +Read the [upgrade and release notes](reporting-release-notes.md) before +deploying these changes. They collect the historical comparison boundaries, +feature-tier requirements and operational limits; final release qualification +remains separate from the integrated source. + The default protocol remains AdCP 3.2.0-rc.6. Set `ReportingProductionSupport`'s `adcp_version="3.2-rc.6"` or omit the pin for the packaged default. Historical rc.3 schemas are available offline but are not advertised as a live reporting @@ -348,8 +353,9 @@ contracts continue to apply. Full buyer adjustment/submission automation and the `client.reporting` facade remain later buyer work. They do not substitute for seller financial validation. -This slice remains open and unmerged pending independent exact-head review and -the separately gated downstream interoperability program. +The seller composition is integrated. Complete service and buyer acceptance, +installed cross-language interoperability and release qualification remain +separate gates. ## Seller acceptance ownership diff --git a/docs/reporting-release-notes.md b/docs/reporting-release-notes.md new file mode 100644 index 000000000..dc963c86f --- /dev/null +++ b/docs/reporting-release-notes.md @@ -0,0 +1,140 @@ +# Reliable Reporting upgrade and release notes + +These notes describe the integrated changes prepared for the next SDK 8 +prerelease. The release version, published distributions, complete service +acceptance and Python/TypeScript interoperability qualification are still +pending. Include these boundaries in the reviewed release proposal; merging +this document does not publish or qualify a package. + +## Account-qualified configuration identity + +`ReportingConfiguration.generation_key` now returns the frozen +`ReportingConfigurationGenerationKey(account_id, delivery_config_id, +delivery_config_version)` value instead of the beta.15 two-tuple. Replace tuple +unpacking and positional indexing with named attributes. Include the account +when indexing configurations or resolving leased work. + +Older workers do not use the account-qualified key safely when accounts reuse +a configuration ID. Drain them before upgrading the PostgreSQL ledger, run +the upgraded store's `create_schema()`, and restart every participant on the +upgraded SDK. The [ledger migration guide](reporting-ledger-migration.md) +describes preserved records, locking and adopter-managed migrations. + +## Rolling upgrade boundaries + +The compatibility controls use the following exact integrated Git snapshots. +They are comparison inputs, not released package versions or a promise that +all operating modes can run together. Earlier snapshots of each component are +untested and unclaimed by these comparisons, even if they share ancestry. + +| Component | Integrated comparison snapshot | Excluded earlier snapshots | +| --- | --- | --- | +| A: durable notification outbox | `17ee407ae3978c8a2bb54437287afbf9dafb8130` | Pre-`17ee407a`; the older `21bf443e` schema fingerprints depend on database collation. | +| B: webhook activity | `0f34c666ac1961e9832fce43ef0ef6937b3c1dde` | Pre-`0f34c666`, including the original `198d50e6` feature snapshot. | +| C: status notifications and rc.6 | `967b6e286301d7e5d089aea6fdbb90bea8ee5a16` | Pre-`967b6e28`, including `ea150fab`. | +| B1: strict selection and destination contracts | `5487f2bdef23c5102118b305be9e868228f6ce61` | Pre-`5487f2bd`, including `1c91311e`. | +| B2.1: durable materializer | `3fd62121c96a074e3ea458c30c5224d6a586f169` | Pre-`3fd62121`; the older `8e18ca12` scheduler can sort `served_at` as text. | +| B2.2: authenticated receipt ingress | `09fd87f79a746665d828dea66b3a1dd9d1fc189e` | Pre-`09fd87f7`, including `74b338d8`. | +| B2.3: frozen authorized feed | `2d777ace7b4bf8be519ce0abd4fd0a25ed4f1da7` | Pre-`2d777ace`, including `50e35f0a`. | +| Schema-proof and receipt-diagnostic hardening | `e16eb8cf3074cabd45aab42840950f05ad6d2b43` | Pre-`e16eb8cf`. | +| Production composition | `34c8f6d929aeac3407e2f595104a8e903e572623` | Pre-`34c8f6d9`. | + +An older A outbox's aggregate notification readiness remains false on the C +schema, both before and after later migrations. These controls do not establish +whole-trigger startup support for A after C. Supported historical reads and +writes do not authorize concurrent incompatible autonomous materializers, +status projectors or clock sweepers. Follow the component-specific migration +procedures before starting those workers. + +## Current and historical protocol versions + +Live reporting mounts and callers use AdCP `3.2-rc.6`, whose bundle spelling is +`3.2.0-rc.6`. Omit an explicit pin to use the packaged default, or configure the +current supported reporting version consistently across the composition and +its mounts. Cross-cohort reporting requests are rejected even when optional +request validation is disabled. + +Historical beta.6 and rc.3 schema bundles support offline validation and +retained historical walks. Their presence does not enable a historical live +mount or client pin. In rc.6, an exactly scoped bilateral waiver can retire +the public mismatch and project underlying seller health while retaining the +consumer evidence; rc.3 forbids waiver alone from clearing that health. The +current implementation therefore cannot advertise the historical live contract. + +The explicit rc.6 mount minimum does not remove a previously accepted +configuration from the integrated SDK: its shared version resolver already +rejected older prerelease pins before the mount's minimum-version check. +See [signed protocol inputs and history boundaries](protocol-3.2-rc6.md) +for bundle identity, versioned status and continuation rules. + +## Choose the installed feature tier + +Capabilities describe the actual mounted composition and its readiness. +Installing the package or adding a capability flag does not activate a tier. + +| Surface | Required composition | +| --- | --- | +| Core polling | A configured producer and source, retained immutable reporting records, and the applicable authenticated status/exact-read routes. | +| Core notifications | An eligible Core composition with durable queues, trusted subscriptions, the matching running notification workers and signing configuration. The frozen-feed store alone does not enable advertisement. | +| Managed delivery | Trusted source and destination contracts, a durable materializer with verified readback, complete status/exact reads, and the production configuration route. Polling does not require receipt ingress or HTTP notification workers. | +| Reconciled billing | Managed delivery plus official finality, canonical verification, and mounted revision/adjustment receipt ingress. | + +Use the [production composition guide](reporting-production.md) for lower-level +durable wiring and activation. The [service guide](reliable-reporting-service.md) +and [source adapter contract](reporting-source-adapters.md) describe adapter +registration and lifecycle. The service's PostgreSQL factory makes the ledger +durable; default adapter staging and replay seals remain in memory. Supply +durable implementations if retained revisions must remain readable after a +restart. Multiple service schedulers still need a single account/configuration +lease owner until that integration is enabled. + +## Migration and activation + +1. Choose the intended tier and review the relevant historical comparison + boundary above. Keep a maintenance window for schema migration and draining + incompatible workers. +2. Drain older ledger writers and autonomous materializers, status projectors + and clock sweepers. Reconcile uncertain external effects using the + [materializer recovery procedure](reporting-durable-materializer.md#recovery-and-retention). + Preserve the original external idempotency identities of pending attempts. +3. Run the upgraded stores' `create_schema()` methods before starting reporting + workers. Follow the [ledger migration guide](reporting-ledger-migration.md) + and [production migration sequence](reporting-production.md#migration-drain-and-activation). +4. Construct the actual source/provider/verifier and durable worker components, + mount the support's authenticated handler, then start and activate the + production support as described in that sequence. A schema-only upgrade + does not establish readiness. +5. Check the advertised tier and exact reads, then exercise polling, enabled + notifications and receipts as applicable. Validate restart and recovery + using the intended installed package and the adopter's configuration before + enabling production traffic. + +Activation preserves epoch-zero work identities and permanently quarantined +readiness events. It does not promote old work or backfill an external +idempotency history. Only new qualified work enters the production epoch. + +## Operational limits + +- Positive schema-proof caches reduce repeated catalog discovery. They do not + cache authorization or replace live topology checks, and they do not + establish performance under load. Stop and drain the support for later DDL, + migrate, construct fresh support and validate before restarting. +- Sampling hints can race between concurrent calls on one store and repeat + candidate scans. Account locks, row locks and rechecked lease predicates + still govern acquisition. No concurrent fairness guarantee is added. +- A changed snapshot boundary can invalidate a cursor and fail closed. These + changes add no snapshot-retention or continuous-write pagination-liveness + promise. Follow the [frozen feed contract](reporting-frozen-feed.md) for + authorization, checkpoints and retained-walk behavior. +- Configure authentication and network access deliberately. The generic + server's wildcard bind default and optional authentication do not provide + a private deployment boundary. Production reporting routes require trusted + account and consumer resolution. + +Complete adapter-first service acceptance and the installed Python/TypeScript +stable/candidate interoperability matrix remain required for the full rollout +([#1172](https://github.com/adcontextprotocol/adcp-client-python/issues/1172), +[#1199](https://github.com/adcontextprotocol/adcp-client-python/issues/1199)). +Partial storyboard results, component comparisons and source integration do +not establish that acceptance. Publication and subsequent registry-install +verification follow the [guarded release runbook](releasing.md). From 773e8d2f05fa2c41f0084db5885762cf00a34216 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 25 Sep 2026 11:31:57 +0000 Subject: [PATCH 2/2] docs(reporting): distinguish ledger retention from source recovery --- docs/reliable-reporting-service.md | 5 +++-- docs/reporting-release-notes.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/reliable-reporting-service.md b/docs/reliable-reporting-service.md index 068455823..0b446e039 100644 --- a/docs/reliable-reporting-service.md +++ b/docs/reliable-reporting-service.md @@ -132,8 +132,9 @@ reporting = ReliableReportingService.postgres( The PostgreSQL factory makes the ledger durable; it does not make the default adapter staging or replay-seal stores durable. Production adapters should pass durable `staging=` and `seals=` implementations to `sources.register`, or use -`sources.register_executor` for a custom executor and object reader. A retained -revision whose staged rows disappear cannot satisfy an exact read. +`sources.register_executor` for a custom executor and object reader. Committed revision rows are retained in the ledger for exact reads. Durable +staging and seals are needed to recover interrupted acquisitions and replay +previously sealed source results across a restart. Managed delivery, notification, and receipt components are replaceable extensions. Startup rejects combinations that cannot be advertised honestly, diff --git a/docs/reporting-release-notes.md b/docs/reporting-release-notes.md index dc963c86f..8ddb718e5 100644 --- a/docs/reporting-release-notes.md +++ b/docs/reporting-release-notes.md @@ -84,8 +84,8 @@ durable wiring and activation. The [service guide](reliable-reporting-service.md and [source adapter contract](reporting-source-adapters.md) describe adapter registration and lifecycle. The service's PostgreSQL factory makes the ledger durable; default adapter staging and replay seals remain in memory. Supply -durable implementations if retained revisions must remain readable after a -restart. Multiple service schedulers still need a single account/configuration +durable implementations for acquisition and sealed-replay recovery across a +restart. Committed revision rows remain in the durable ledger. Multiple service schedulers still need a single account/configuration lease owner until that integration is enabled. ## Migration and activation