feat(aws-marketplace): sell several listings from one integration through a product catalog
Merged
WA
3d ago+406+406+012345678901234567890123456789-140-140-012345678901234567890123456789
Summary
- One integration now sells any number of AWS Marketplace listings. Each listing's behavior is a plan in code (
aws-marketplace/products.ts); which product codes exist is deployment configuration,AWS_MARKETPLACE_PRODUCTS=<code>=<plan>,.... Every path resolves a license's product from the code AWS returned or the code on its row, so adding, repricing, or retiring a listing is a config change, not a branch - Plans:
contract(unchanged behavior: any current entitlement grants access) andplatform-with-usage(access requires a currentplatformentitlement; usage dimensions never grant access on their own) entitlementCountstill counts every dimension AWS returned, so a license with usage but noplatformreadsinactive, notpending- Registration routes by the code
ResolveCustomerreturns, since all listings share the one fulfillment URL; a code this deployment doesn't sell is refused as before - Reconcile and the daily re-verify span every configured code and verify each license against its own product; agreement renewals, advisories and endings match across listings (agreement IDs are unique anyway)
- The team's "organizations already linked to this AWS account" hint now matches across listings — a buyer moving to a new listing usually wants the organization they already have — and team notices name the listing
config.tsis the single parse point (memoized); a malformedAWS_MARKETPLACE_PRODUCTSthrows an error naming the bad entry on first use.env.tsstays free of billing code- Reconcile resolves the configured products once per run and the repository returns each license paired with its product, so no loop re-looks-up or skips
Deploy prerequisite: this replaces AWS_MARKETPLACE_PRODUCT_CODE. Before the release carrying this PR deploys, the production env secret must hold AWS_MARKETPLACE_PRODUCTS=<existing code>=contract; otherwise the Marketplace surfaces turn off. The new listing is added to that value (and to the infra event rule) once this is live.
Type of Change
- New feature
Testing
lifecycle.integration.ts+checkout-guard.integration.tson real Postgres (bun run test:integration): 75 pass, including two new ones — a usage-listing buyer is admitted only on a currentplatformentitlement (a usage-only license is recordedinactive), and a queued License Updated event for the usage listing is applied under its own plan (a lapsedplatformends access while usage is current). Both go red with the dimension filter removedentitlements.test.ts: 10 pass; the 3 new required-dimension cases go red with the filter removedtsc --noEmit,bun run lint, andcheck:boundaries,check:client-boundary,check:utils,check:file-names,check:comment-hygiene,check:source-conventions,check:explicit-any; full audits and suites run in CI
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing (new tests pass the
test-auditauthoring gate) - No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)