Repository navigation
fix(server): preserve valid creatives in lenient legacy batches - #1841
Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve.
Reviewer found no blocking or Medium findings. This PR implements the spec'd validation_mode: "lenient" partial-admission flow for legacy sync_creatives: supported creatives dispatch while unprojectable ones return as action: "failed"/UNSUPPORTED_FEATURE in submitted order.
What I checked against the decision table:
- No
critical/highfindings → row 1 does not fire. gated_paths: false→ row 2 does not fire (despitereview_decision: REVIEW_REQUIRED).high_risk: true, but reasons are(modified)/(added)only — no(deleted)→ row 3 does not fire. New-file scaffolding (_creative_batch.py) is normal.- No Medium findings at all → rows 4, 5, and 8 do not fire.
- No prior decision → row 6 does not fire.
- No no-auto-approve team match → row 7 does not fire.
- Falls through to row 9 → approve.
Note on high-risk modified files (handler.py, idempotency/store.py, mcp_tools.py): the reviewer confirmed the merge is idempotent by construction, the double overlay converges, assignment refusal fails closed pre-dispatch, idempotency hash uses untouched raw_params (no input mutation), and the DR-0032/DR-0033 version-pathway is handled (refused/typed-unsupported) with a regression test. Semver signal fix(server): is correct — no public-surface removal or wire-shape change, no type-system/forward-compat files touched. The required reviewer backstop remains in effect via branch protection.
Forward-port the stable server fix from #1841 to the SDK 10 beta line. Explicit lenient legacy creative uploads retain supported siblings and ordered per-creative projection failures while preserving strict atomic validation, original idempotency identity, rejected-assignment safety, and SDK-managed completion results. Keep next's pre-dispatch mutation-outcome tracking and account-change response projection. Give the existing JOSE factory and thumbprint boundaries explicit result types so the Python 3.10 static contract works with joserfc 1.8 without changing runtime cryptography or dependency ranges. Validated the exact reviewed source with 21,645 passing tests, 92.04% coverage, all static and generated-code gates, all GitHub CI jobs, and independent protocol review. (cherry picked from commit 2bd7751) Refs #1839.
An unprojectable legacy
format_idcurrently rejects an entiresync_creativesrequest before the seller runs, including requests explicitly selectingvalidation_mode: "lenient". A lenient batch containing one unsupported format and two supported display creatives now returns oneaction: "failed"row and two accepted rows, in submitted order. Strict and omitted validation modes retain atomic rejection.The dispatcher validates the original envelope before isolating projection failures, preserves the original input positions for configured converters, and keeps rejected input content in SDK idempotency hashing. That original-input hint is consumed at the first matching boundary so nested operations retain their own key and payload; pre-validation hooks supplying keys still preserve replay and conflict behavior. SDK-owned failures are materialized before dispatch, preserving schema-valid assignment error keys and the adopter's accepted typed row objects. Assignments to rejected submissions are refused. Managed
PlatformHandlertask completion overlays the same failures before persistence and webhook publication.The SDK does not own adopter library reconciliation or external task completion. Partial batches therefore fail before dispatch when
delete_missing,creative_idsfiltering, unrelated assignments with no projectable uploads, or detectable custom async surfaces would make a reduced request unsafe. Explicit assignment operations continue to require strict mode; partial managed workflow handoffs are refused before enqueue. The migration guide documents these boundaries and retries.Validation:
make test: 18,863 passed, 2,819 skipped, 10 deselected, one existing expected failure; 92.16% coverage (80% required). The mixed-batch suite has no expected failures.aaa2d0bcb7cb4ea943b062b5d62cdd25ed569ca2, including the Python 3.10–3.13 matrix and PostgreSQL/installed-package gates.Fixes #1839.