Skip to content

Commit 69c585c

Browse files
authored
docs(proposals): product architecture — layered model + two-platform composition (#502)
* docs(proposals): product architecture — layered model + two-platform composition Foundational design doc capturing the layered architecture for products across the SDK: wire / internal-config (recipe) / capability overlap / supporting tables. Anchors the missing prerequisite that the salesagent migration guide (PR #489) currently has no answer for. Key conceptual moves: - Four-layer model with explicit ownership per layer. - Two-platform composition: ProposalManager + DecisioningPlatform, with the recipe (implementation_config) as the typed contract between them. - Three concrete shapes: tight coupling (LinkedIn), sophisticated multi-decisioning (Prebid salesagent), naive (programmatic non-guaranteed). - Path B recipe binding: discriminated-union with recipe_kind tag, explicit tenant binding, boot-time validation. - ProposalCapabilities is sales-axis-scoped (not generic to all specialisms) — guaranteed vs non-guaranteed flavors. Status: DRAFT (conceptual scaffold). Concrete examples sections marked [citations pending] for follow-up agent pass once budget allows. Python-first; ports back to JS once settled. Reverses the typical direction (lifecycle-state proposal went JS-to-Python) because the conceptual gap surfaced during the Python migration story. Refs: - PR #489 (migration guide reviewer feedback that prompted this) - Issues #491-#497 (already-filed buyer-side request-shape helpers) - #477 (multi-platform proof — interacts with tenant binding model) - proposals/decisioning-platform-dispatch-design.md (current DecisioningPlatform design) * docs(proposals): v1 ProposalManager is mock-backend forwarder, not new catalog impl Brian's review correction: the mock seller backend (bin/adcp.js mock-server) already implements the naive case via product fixtures. SDK doesn't need a separate SimpleCatalogProposalManager. v1 of ProposalManager is just the wiring that forwards to the mock backend — symmetric with DecisioningPlatform's upstream_for(ctx) mock-mode dispatch from Phase 2. Adopters declare a mock_upstream_url; framework forwards get_products / refine; recipes flow back. Updates: - Shape 3 reframed: Naive → Mock-backed (v1 default) - MockProposalManager sketch with parallel pattern to upstream_for - Independent-modes table: ProposalManager and DecisioningPlatform can each be mock or live independently - Future-issues list: SimpleCatalogProposalManager replaced with MockProposalManager (the v1 work is wiring, not a new impl) - §What ships in v1 framing: framework wiring, not catalog content * docs(proposals): address review comments — recipe lifecycle, hydration, finalize Four corrections from Brian's review: 1. Recipe lifecycle (Layer 2): never on the wire. Lives in framework session cache during negotiation; persists alongside the committed proposal after finalize; the framework hydrates it for every subsequent operation in the buy's lifecycle. Adopters do NOT store recipes themselves — the SDK is the system of record. 2. ProposalManager flavors: don't lock the formal taxonomy. Two extremes today (simple catalog vs complex proposal); useful variants will emerge between. sales_specialism + capability flags let adopters declare their actual shape; naming variants is future-state work. 3. Proposal hydration + capability validation upstream of adapter: buyer may reference packages by proposal_id OR product_id; framework hydrates from session cache or persisted store and validates the buyer's request against capability_overlap BEFORE invoking adapter. Buyer asking for geo-metro targeting on a product that doesn't expose it gets a structured error without adapter code participating. Layer 3 capability-overlap seam gets concrete. 4. Acceptance IS in the spec — buying_mode='refine' with refine[] action='finalize' transitions a draft proposal to committed with locked pricing, expires_at hold window, optional HITL. I incorrectly said the spec had no proposal lifecycle. Rewrote the section to walk the actual wire flow: get_products → refine → finalize → create_media_buy. SDK responsibilities at the seam: session cache, finalize transition, expires_at enforcement, persistence through the buy lifecycle.
1 parent 786e6a2 commit 69c585c

1 file changed

Lines changed: 885 additions & 0 deletions

File tree

0 commit comments

Comments
 (0)