Skip to content

Accepting a proposal-led negotiation and booking its quote doesn't check the proposal's approval decision #129

Open

Description

@jaanijuk

Summary

With the approval gate enabled for proposal_decision, a proposal can reach a stored deal linked to it through the negotiation endpoints and quote booking. This happens whether its approval request is pending, approved at different terms, or rejected. The tested negotiation-and-booking path proceeded while the associated approval record was pending or rejected, or approved at the earlier price. Changing the price did not create a new approval request.

We understand the gate is configured for the proposal decision only. We're asking because #96 now links a proposal-led negotiation to the quote that's booked. Should the proposal's decision carry across that link?

Setup

  • seller-agent main at 902e3f57e6c5c55dd2c00956132f1fd44e70d513;
  • APPROVAL_GATE_ENABLED=true, APPROVAL_REQUIRED_FLOWS=proposal_decision;
  • the CSV ad server, SQLite, a fresh database for each run;
  • a synthetic product with base CPM US$45.00 and floor US$38.25;
  • one agency-tier buyer API key for every buyer request.

A deterministic test stand-in answered the proposal review (accept at the bid). Everything after the proposal ran the seller's own code. All data is synthetic.

Steps

  1. POST /proposals at US$42.08: saved with recommendation: accept, status: pending_approval, and one approval request.
  2. Leave it pending; or decide approve or reject (POST /approvals/{id}/decide, then /resume).
  3. POST /proposals/{id}/counter with buyer_price 40.00. The seller counters at US$40.25 and opens a negotiation.
  4. POST /api/v1/quotes for the same product, with target_cpm US$40.00.
  5. POST /api/v1/negotiations/messages with action: accept, naming the proposal_id and the quote_id.
  6. POST /api/v1/deals with that quote_id.

Observed (one run per decision state)

Decision before step 3 Approval record afterwards Stored proposal Step 3 Steps 5 and 6
None (pending) pending pending_approval 200; still one approval request 200 and 200
approve (at US$42.08) approved pending_approval 200; still one approval request 200 and 200
reject rejected pending_approval 200; still one approval request 200 and 200

In all three runs:

  • the negotiation becomes accepted at the seller's last price, US$40.25;
  • negotiation_by_quote:{quote_id} points to the proposal;
  • step 6 stores a deal with status: proposed at US$40.25, rationale "… | Negotiated to $40.25 CPM (neg-…)";
  • the quote's status becomes booked.

The strongest case is the third: a stored deal linked to the proposal was created while the approval record said rejected.

The price stays above the floor, so this is about approval and changed terms, not pricing. Nothing was executed on an external platform; the deal's status is proposed.

Questions

  1. When a negotiation is proposal-led, should accepting it, or booking its quote, require the proposal's approval to have been granted, and be refused after a rejection?
  2. Should a price change after approval invalidate that approval or request a new one?
  3. The stored proposal stays pending_approval after the decision and resume. Is the approval record meant to be the only place the decision lives?

Activity

  1. jaanijuk commented on Nov 4, 2026

    @jaanijuk
    ContributorAuthor

    Related: #130 covers which authenticated buyer may accept the negotiation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions