Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
58 changes: 37 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
uv pip install --system -e ".[dev]" -e "./packages/adcp-reporting-storage"

- name: Run linter
if: matrix.python-version == '3.12'
run: ruff check src/
run: ruff check src/ packages/adcp-reporting-storage/src/

- name: Run type checker
if: matrix.python-version == '3.12'
run: mypy src/adcp/
run: mypy src/adcp/ packages/adcp-reporting-storage/src/adcp_reporting_storage/

- name: Run adopter type-check suite
if: matrix.python-version == '3.12'
Expand Down Expand Up @@ -245,7 +245,7 @@ jobs:

- name: Install dependencies (with [pg] extra)
run: |
uv pip install --system -e ".[dev,pg]"
uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"

- name: Run Postgres conformance tests
env:
Expand Down Expand Up @@ -356,8 +356,12 @@ jobs:
npm ci
npm run build
test -f dist/lib/reporting/ledger/index.js
# SDK 16 moved the row storage into the @adcp/reporting-storage workspace
# package, which the root build does not compile; the interop driver reads it.
npm run build --workspace packages/reporting-storage
test -f node_modules/@adcp/reporting-storage/dist/index.js
- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run the interop test in both directions
env:
ADCP_PG_TEST_URL: postgresql://postgres@localhost:5432/adcp_interop_test
Expand Down Expand Up @@ -445,7 +449,7 @@ jobs:

- name: Install dependencies (with [pg] extra)
run: |
uv pip install --system -e ".[dev,pg]"
uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"

- name: Run status semantics, transaction, clock/process and maintenance gates
env:
Expand Down Expand Up @@ -508,7 +512,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run installed frozen binaries and materializer migrations
# Propagate pytest failures through tee while retaining evidence for upload.
shell: bash
Expand Down Expand Up @@ -574,7 +578,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run receipt transactions, real mounts, crash and installed gates
shell: bash
timeout-minutes: 30
Expand Down Expand Up @@ -642,7 +646,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Require stopped-worker retention, ownership backfill and receipt isolation
env:
ADCP_PG_TEST_URL: postgresql://postgres@localhost:5432/adcp_receipt_maintenance_test
Expand Down Expand Up @@ -690,7 +694,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run frozen feeds, checkpoints, mounts, transaction faults and migrations
shell: bash
timeout-minutes: 20
Expand Down Expand Up @@ -773,7 +777,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Require private feeds and legacy cursor invalidation after maintenance
shell: bash
timeout-minutes: 45
Expand Down Expand Up @@ -836,7 +840,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run installed base and PostgreSQL restart cells
shell: bash
timeout-minutes: 40
Expand Down Expand Up @@ -894,7 +898,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run complete production and projection conformance
shell: bash
# A passing suite plus harness cleanup can exceed 30 minutes.
Expand Down Expand Up @@ -977,7 +981,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Run installed source-equivalent production contract
shell: bash
timeout-minutes: 45
Expand Down Expand Up @@ -1045,7 +1049,7 @@ jobs:
prune-cache: true

- name: Install test dependencies
run: uv pip install --system -e ".[dev,pg]"
run: uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
- name: Require owned production admission and installed maintenance contracts
shell: bash
timeout-minutes: 42
Expand Down Expand Up @@ -1141,6 +1145,10 @@ jobs:
python -m build --outdir dist/
python scripts/ci/check_distribution_size.py dist/
pip install dist/*.whl
# The storage distribution is built from its own tree and must
# install over the freshly built adcp wheel, never pull adcp from PyPI.
python -m build --outdir dist-storage/ packages/adcp-reporting-storage
pip install --no-deps dist-storage/*.whl

- name: Verify prerelease dependency resolution imports server
run: |
Expand Down Expand Up @@ -1262,7 +1270,15 @@ jobs:
)
assert adcp.get_adcp_version(), "ADCP_VERSION file is empty"

print(f"OK — adcp=={adcp.__version__}, spec={adcp.get_adcp_version()}")
# The storage distribution's facade is lazy and its stores work without a driver installed.
import sys
import adcp_reporting_storage
assert not [m for m in sys.modules if m.startswith("adcp_reporting_storage.")]
from adcp_reporting_storage import PgReportingLedgerStore, ReportingRowStorageOptionsV1
assert "adcp.reporting.ledger.pg" not in sys.modules, "the ledger store moved; adcp must not ship it"

print(f"OK — adcp=={adcp.__version__}, spec={adcp.get_adcp_version()}, "
f"adcp-reporting-storage=={adcp_reporting_storage.__version__}")
PY

schema-check:
Expand Down Expand Up @@ -1291,7 +1307,7 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
uv pip install --system -e ".[dev]" -e "./packages/adcp-reporting-storage"

# Blocking. Grades the COMMITTED generated tree against a regeneration
# from the COMMITTED schemas, so it runs before the sync steps below
Expand Down Expand Up @@ -1665,7 +1681,7 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev,pg]"
uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
# Example-local deps: the v3 reference seller imports
# sqlalchemy + asyncpg + httpx-respx but those aren't in the
# SDK's [dev] extras. Install them inline rather than adding
Expand Down Expand Up @@ -1740,7 +1756,7 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev,pg]"
uv pip install --system -e ".[dev,pg]" -e "./packages/adcp-reporting-storage[pg,gcs,s3,azure]"
# Example-local deps: the v3 reference seller imports
# sqlalchemy + asyncpg (async Postgres driver) which aren't
# in the SDK's [dev,pg] extras. Install inline rather than
Expand Down Expand Up @@ -2011,7 +2027,7 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
uv pip install --system -e ".[dev]" -e "./packages/adcp-reporting-storage"

- name: Map tenant subdomains to localhost
run: |
Expand Down Expand Up @@ -2148,7 +2164,7 @@ jobs:

- name: Install dependencies
run: |
uv pip install --system -e ".[dev]"
uv pip install --system -e ".[dev]" -e "./packages/adcp-reporting-storage"

- name: Boot sales-proposal-mode seller
run: |
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,18 @@ jobs:
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PROPOSAL_PRS: ${{ steps.release.outputs.prs }}
- name: Queue publication for the created release
- name: Queue publication for the created adcp release
if: steps.release.outputs.release_created == 'true'
env:
GH_TOKEN: ${{ github.token }}
RELEASE_SHA: ${{ steps.release.outputs.sha }}
RELEASE_TAG: ${{ steps.release.outputs.tag_name }}
run: gh workflow run release-publish.yml --ref main -f release_sha="$RELEASE_SHA" -f tag_name="$RELEASE_TAG"
run: gh workflow run release-publish.yml --ref main -f package=adcp -f release_sha="$RELEASE_SHA" -f tag_name="$RELEASE_TAG"
- name: Queue publication for the created adcp-reporting-storage release
# Manifest mode prefixes every non-root package's outputs with its path.
if: steps.release.outputs['packages/adcp-reporting-storage--release_created'] == 'true'
env:
GH_TOKEN: ${{ github.token }}
RELEASE_SHA: ${{ steps.release.outputs['packages/adcp-reporting-storage--sha'] }}
RELEASE_TAG: ${{ steps.release.outputs['packages/adcp-reporting-storage--tag_name'] }}
run: gh workflow run release-publish.yml --ref main -f package=adcp-reporting-storage -f release_sha="$RELEASE_SHA" -f tag_name="$RELEASE_TAG"
25 changes: 23 additions & 2 deletions .github/workflows/release-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ name: Release publish
on:
workflow_dispatch:
inputs:
package:
description: Distribution to publish (each Release Please component publishes on its own)
required: true
type: choice
default: adcp
options:
- adcp
- adcp-reporting-storage
release_sha:
description: Exact commit of the Release Please release
required: true
Expand All @@ -15,7 +23,7 @@ on:
permissions: {}

concurrency:
group: release-publish-${{ inputs.tag_name }}
group: release-publish-${{ inputs.package }}-${{ inputs.tag_name }}
cancel-in-progress: false

jobs:
Expand All @@ -39,8 +47,15 @@ jobs:
GH_TOKEN: ${{ github.token }}
RELEASE_SHA: ${{ inputs.release_sha }}
RELEASE_TAG: ${{ inputs.tag_name }}
PACKAGE: ${{ inputs.package }}
run: |
[[ "$RELEASE_SHA" =~ ^[0-9a-f]{40}$ ]]
# adcp tags are vX.Y.Z; the storage component tags carry its name.
case "$PACKAGE" in
adcp) [[ "$RELEASE_TAG" =~ ^v[0-9] ]] ;;
adcp-reporting-storage) [[ "$RELEASE_TAG" =~ ^adcp-reporting-storage-v[0-9] ]] ;;
*) echo "unknown package $PACKAGE" >&2; exit 1 ;;
esac
test "$(git rev-parse "$RELEASE_TAG^{commit}")" = "$RELEASE_SHA"
git merge-base --is-ancestor "$RELEASE_SHA" HEAD
for attempt in {1..220}; do
Expand All @@ -57,9 +72,15 @@ jobs:
with:
python-version: '3.12'
- name: Build and check distributions
env:
PACKAGE: ${{ inputs.package }}
run: |
python -m pip install build twine
python -m build
if [ "$PACKAGE" = adcp ]; then
python -m build
else
python -m build --outdir dist/ packages/adcp-reporting-storage
fi
python -m twine check dist/*
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __pycache__/
build/
develop-eggs/
dist/
dist-storage/
# Bundled schema copy — populated by scripts/bundle_schemas.py before
# wheel build, mirrors schemas/cache/ so setuptools package-data ships
# them. Committed copies would duplicate ~13MB across both trees.
Expand Down
3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
".": "9.0.0-beta.4"
".": "9.0.0-beta.4",
"packages/adcp-reporting-storage": "0.1.0-beta.0"
}
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@

### ⚠ BREAKING CHANGES

* **reporting:** the Reliable Reporting storage implementations ship as a
separate distribution, `adcp-reporting-storage`, maintained in this
repository and versioned on its own line (`packages/adcp-reporting-storage`).
The PostgreSQL ledger, reconciliation, materializer, receipt, feed,
projection, production, outbox, status, inline-storage and buyer-submission
stores, the chunked row storage with its filesystem, GCS, S3 and Azure
providers, the host change feed, period retirement, row migration, the
caller-ownership migration helpers and `ReliableReportingService.postgres`
moved out of `adcp.reporting`; the old import paths are gone, with no shims.
`adcp` keeps the store protocols, the in-memory stores, the producer, the
handlers, the row encoding and the store-contract errors, and never imports
the new package. The `adcp[reporting-gcs]`, `[reporting-s3]` and
`[reporting-azure]` extras are removed; `adcp[pg]` remains for the signing
and decisioning stores. Install `adcp-reporting-storage[pg]` (plus `gcs`,
`s3`, `azure`) and import from `adcp_reporting_storage`; the full old-to-new
table is in [docs/reporting-storage-package-migration.md](docs/reporting-storage-package-migration.md).
The composition now depends on store protocols
(`adcp.reporting.production.store.ReportingProductionStore`,
`adcp.reporting.outbox.durable.ReportingDurableNotificationLedger`,
`ReportingDurableStatusStore`, `adcp.reporting.ledger.ReportingRowStagingStore`,
`ReportingSourcePublicationStore`, `ReportingWorkerRetryPolicy`) instead of
recognizing the PostgreSQL classes by type; `ReliableReportingService` takes
`staging=`, `seals=` and `initialize_source_storage=`. The public-API
snapshot now covers `adcp.reporting`, `adcp.reporting.ledger` and
`adcp_reporting_storage`. Refs #1510, #1490, #1488, #1489.

* **types:** `ProductFormatDeclaration` is a class again — a `Format` subclass
that reads the root rules of `core/product-format-declaration.json` on every
validation — rather than an `Annotated` union. Construction,
Expand Down
1 change: 1 addition & 0 deletions MIGRATION_v8_to_v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ changes below before upgrading each client, server and reporting worker.
| `ProductFormatDeclaration` enforces its schema's root rules | It is a `Format` subclass, so construction, `model_validate`, `isinstance` and the projection helpers all work on it, and it refuses a `format_kind` outside the schema's closed set. Read typed parameters with `params_as`. Use `Format` for open consumer parsing of unknown kinds, and `LegacyProductFormatDeclaration` for the generated branch union. A validated declaration is published on `Product.format_options` as-is. `Format` stays the lenient path for reading and publishing stored declarations; `ProductFormatDeclaration` is the authoring check. See [product declarations](docs/types-9-migration.md#product-declarations-are-graded-against-their-root-schema) and [strict authoring and lenient publishing](docs/types-9-migration.md#strict-authoring-lenient-reading-and-publishing). |
| Structural pointer references share the selected type | Remove imports of obsolete internal per-position wrappers. Use public `adcp.types` names or `adcp.types.domains` modules. See [pointer references](docs/types-9-migration.md#3-pointer-refs-resolve-to-the-selected-type-1371). |
| Format-kind fields preserve open strings | Replace enum identity comparisons with string equality. Opt into `CanonicalFormatKindStr` when your application needs a closed vocabulary. See [format-kind validation](docs/canonical-format-kinds-migration.md). |
| The PostgreSQL reporting stores and row storage providers ship as `adcp-reporting-storage` | Install `adcp-reporting-storage[pg]` (and `gcs`/`s3`/`azure`) and import from `adcp_reporting_storage`; `ReliableReportingService.postgres` is `adcp_reporting_storage.postgres_reliable_reporting_service`. `adcp` keeps the protocols, the in-memory stores and the digest code. See [the storage package migration](docs/reporting-storage-package-migration.md). |
| Reporting generations require authenticated caller ownership | Include `consumer_id` in custom store/binding implementations and typed constructors. Migrate populated ledgers with stopped workers; an entirely empty ledger can use the explicit replacement API. See [reporting ownership migration](docs/reporting-caller-ownership-migration.md). |
| New source requests and sealed artifacts include their owning consumer | Read `request.identity.consumer_id` when implementing adapters. Historical ownerless artifacts retain their original hashes, but active owned generations refuse ownerless or differently owned frozen acquisitions; reconcile retained state and admit a new generation instead of relabelling evidence. See [reporting ownership migration](docs/reporting-caller-ownership-migration.md). |
| URL canonicalization gives an empty path its `/` whatever the query does | The `@target-uri` signature base changes for bare-authority URLs such as `https://seller.example.com`. Dial signed clients at the explicit root path, which canonicalizes identically on both versions, or move an unrespellable agent URL's signer and verifier in one window. Identifier matching on `adagents.json`, `brand.json`, TMP and the governance issuer only becomes more permissive. See [the empty-path canonicalization fix](docs/request-signing-migration.md#6-upgrading-across-the-empty-path-canonicalization-fix). |
Expand Down
Loading
Loading