Add an Amazon Seller¶
Purpose and safety boundary¶
Use this runbook for the Amazon-v1 automatic connection lifecycle. A provider
credential check is not the Connected milestone. Connected is projected only
after the database readiness evaluator accepts current evidence for every
required stage.
This runbook never authorizes a migration, reconciliation apply, workflow dispatch, secret change, deploy, or accounting write. The release owner must hold separate authority for each production-changing command shown below. Never paste credentials into a terminal, ticket, email, chat, or runbook.
Amazon readiness does not require QuickBooks, Ads, daily inventory, or an external sheet. Those capabilities may report a delay without blocking Amazon.
Owners¶
| Boundary | Action owner | Expected evidence |
|---|---|---|
| Authoritative legal entity and brand | Tenant owner / onboarding operator | Named source recorded with the identity |
| Secure Amazon credential entry | Authorized account operator | UI reports Setting up; no credential appears in response or logs |
| Lifecycle execution and retry | Lifecycle worker | Fenced stage receipts and derived readiness |
| Identity conflict or credentials needed | Tenant owner / onboarding operator | Corrected authoritative identity or a new secure connection submission |
| Worker, schema, or publication incident | Platform operations | Sanitized reason code and restored green acceptance |
| Production migration, reconciliation apply, dispatch, or deploy | Accountable release owner | Separate change receipt and readback |
1. Collect identity before credentials¶
Record four different identities. Never copy a label from one column into another merely because it looks plausible.
- Workspace/organization: the tenant access boundary.
- Legal entity: the authoritative company name.
- Brand: the commercial brand.
- Amazon account: the managed provider account, marketplace, and runtime seller key.
The normal Settings company-creation flow calls the transactional
create_amazon_company_awaiting_credentials RPC. Its postcondition is one
workspace-scoped company projection with:
provider_status=awaiting_credentials;- an inactive runtime seller and
recurring_enabled=false; - distinct
legal_entity_id,brand_id, andmanaged_asset_id; and - no inferred marketplace or merchant identity.
If the legal entity is unknown, stop at Action needed. Do not infer it from a
brand, app, seller, Amazon-account, or QBO label.
Known scenario rules:
- PartyPrints is the brand; Hemani Noon LLC is the legal entity.
- Culinary Couture remains identity-blocked until an authoritative legal entity is supplied.
- Keto Vitals remains awaiting credentials and recurring-ineligible.
2. Submit Amazon credentials through the secure connection surface¶
An authorized operator opens the company in Settings > Companies > Amazon
and submits credentials through that form or an approved one-use intake link.
Do not use the legacy add_seller.py credential flags or copy per-seller secrets
to an operator machine.
On a successful submission, one database transaction must:
- record the current opaque credential version and provider verification;
- record the sanitized provider receipt;
- create or deduplicate the lifecycle run;
- enqueue one outbox event.
The expected response is connectionStatus=verified and
lifecycle.status=setting_up, with one lifecycle run ID. A duplicate callback
must return that same current run. It must not create another run or report
Connected early.
3. Inspect progress without executing work¶
Use one explicit UUID. --plan is read-only and never claims a stage:
Expected receipt:
{
"manifestId": "<manifest-uuid>",
"state": "queued|running|blocked|ready",
"compiledRegistryVersion": "<64-lowercase-hex>",
"stages": [{"stageKey": "identity", "required": true}]
}
The compiled and stored registry fingerprints must match. Settings should show
Setting up, N/M while work is queued or running, one sanitized primary blocker
when blocked, and Connected only when derived readiness is true. Optional
failures remain visible as sync delays.
The durable stage receipt must contain the current input fingerprint, coverage,
opaque source references, counts, and a sanitized reason code. queried_zero is
valid coverage; no receipt or NOT_ATTEMPTED is not.
4. Worker execution and recovery¶
The normal worker polls at most one run from
public.amazon_lifecycle_recovery_queue:
This is a production-writing command. Only the lifecycle worker or an explicitly authorized release/incident owner may run or dispatch it. Do not run it as a readiness check.
Each stage claim has a lease and monotonically increasing fencing token. A replacement claim after an expired lease invalidates the old worker's ability to publish evidence or a runtime feed. A nonzero process exit also fails, but exit zero alone never succeeds; the stage's query-backed postcondition must pass.
For an interrupted run:
- Do not mark the stage or lifecycle ready manually.
- Inspect the latest sanitized
reason_code,retry_at, lease expiry, and current fingerprint. - Allow the recovery worker to reclaim only after the lease expires, or fix the terminal prerequisite and enqueue the manifest through the authorized path.
- Confirm the old token cannot complete or advance a publication pointer.
- Re-run the read-only
--plancommand and wait for new fenced receipts.
5. Readiness acceptance¶
Before recurring cutover, all of these must be true:
- The credential is still verified and not revoked or disabled.
- Every required stage has current, fingerprint-matched evidence.
- The
console_feedstage published an immutable tenant-keyed version and read it back through the authenticated tenant-scoped consumer path. amazon_recurring_eligibilityresolves exactly the intended runtime seller.- The independent acceptance suite is green:
A zero-sales seller may pass with explicit coverage receipts using
queried_zero; zero rows without a request/coverage receipt must remain blocked.
Safe legacy reconciliation¶
Reconciliation is dry-run by default. It does not infer identity, publish a feed, or mark a run ready:
python3 scripts/reconcile_connection_lifecycle.py \
> /private/tmp/connection-lifecycle-reconciliation.json
Expected top-level receipt:
Review every scenario. PartyPrints may use the approved Hemani Noon LLC /
PartyPrints mapping. Culinary must remain LEGAL_ENTITY_UNVERIFIED. Keto must
remain CREDENTIALS_MISSING. Any other seller requires an authoritative legal
entity, brand, and source reference.
Only after migration validation, green independent acceptance, approved diff, and separate production-write authority may the accountable release owner run:
Expected receipt: mode=apply; writeCount equals only the previously approved
create_manifest_and_queue_run rows; Culinary and Keto remain unchanged. Save
the JSON receipt before proceeding. If the observed set differs, roll back the
transaction, stop, and investigate; never broaden the mapping in place.
The compatibility bridge is available for one explicit existing seller but is not the normal path:
It resolves one verified, non-revoked manifest and delegates to the lifecycle. It does not copy credentials or assert readiness.
Revocation and rollback¶
Revoked, disabled, rotated, reassigned, or materially reconfigured connections
must invalidate affected evidence, fence in-flight publication, remove recurring
eligibility, and enqueue recovery where appropriate. Never restore eligibility
by writing ready, changing a receipt, or setting raw.sellers.is_active alone.
If lifecycle cutover must be rolled back, use the selector rollback in
docs/runbooks/nightly-refresh.md. That changes recurring selection only. It
does not delete lifecycle data, erase receipts, re-enable a revoked credential,
or authorize legacy workers to publish readiness.