Context
The bazaar has six routes. Five of them write or aggregate; none of them lets you read a single negotiation.
POST /api/v1/bazaar/intent returns the row it just created — and that is the last time the publisher sees it.
POST /api/v1/bazaar/quote returns the quote to the agent that sent it. The intent's author never receives it.
GET /api/v1/bazaar/feed lists status = 'active' intents only. The moment an intent is accepted it becomes negotiating and drops out of the only readable surface in the API.
So an agent that paid $0.005 to publish an intent has no way to answer: who quoted me, at what rate, is that quote still valid, was my intent accepted, and against which secret_hash?
accept writes secret_hash and selected_quote_id to the row (routes/bazaar.ts), and nothing can read them back.
Why this matters
This is a marketplace between agents that cannot poll. Everything a counterparty needs in order to decide is written to the database and never exposed. valid_until on a quote is meaningless to the one party who should act on it, because that party cannot see the quote at all.
What to do
Add two read routes in apps/api/src/routes/bazaar.ts:
GET /api/v1/bazaar/intent/:id — the intent, whatever its status. 404 when the id is unknown. Shape it with intentRowToObject() so it matches the feed exactly; do not invent a second shape for the same record.
- The quotes for an intent — either
GET /api/v1/bazaar/intent/:id/quotes or GET /api/v1/bazaar/quotes?intent_id=…. Pick one, and say in the PR why. Each quote should carry enough for the caller to act: rate, from_agent, valid_until, and whether it is still valid right now.
Decide and state in the PR whether these are paid (requirePayment) or free. The feed costs 0.001; there is a defensible argument either way, but it should be a decision, not an accident.
Acceptance criteria
Notes
getIntent(), getQuotesForIntent() and getQuote() already exist in apps/api/src/db/bazaar.ts — this needs no new SQL. apps/api/src/__tests__/bazaar.test.ts shows the offline setup: no network, no Postgres.
Context
The bazaar has six routes. Five of them write or aggregate; none of them lets you read a single negotiation.
POST /api/v1/bazaar/intentreturns the row it just created — and that is the last time the publisher sees it.POST /api/v1/bazaar/quotereturns the quote to the agent that sent it. The intent's author never receives it.GET /api/v1/bazaar/feedlistsstatus = 'active'intents only. The moment an intent is accepted it becomesnegotiatingand drops out of the only readable surface in the API.So an agent that paid $0.005 to publish an intent has no way to answer: who quoted me, at what rate, is that quote still valid, was my intent accepted, and against which
secret_hash?acceptwritessecret_hashandselected_quote_idto the row (routes/bazaar.ts), and nothing can read them back.Why this matters
This is a marketplace between agents that cannot poll. Everything a counterparty needs in order to decide is written to the database and never exposed.
valid_untilon a quote is meaningless to the one party who should act on it, because that party cannot see the quote at all.What to do
Add two read routes in
apps/api/src/routes/bazaar.ts:GET /api/v1/bazaar/intent/:id— the intent, whatever its status.404when the id is unknown. Shape it withintentRowToObject()so it matches the feed exactly; do not invent a second shape for the same record.GET /api/v1/bazaar/intent/:id/quotesorGET /api/v1/bazaar/quotes?intent_id=…. Pick one, and say in the PR why. Each quote should carry enough for the caller to act: rate,from_agent,valid_until, and whether it is still valid right now.Decide and state in the PR whether these are paid (
requirePayment) or free. The feed costs0.001; there is a defensible argument either way, but it should be a decision, not an accident.Acceptance criteria
GET /api/v1/bazaar/intent/:idreturns an intent whose status isnegotiating— the case the feed cannot serve404, distinguishable from an intent that existsGET /feedreturns for the same recordNotes
getIntent(),getQuotesForIntent()andgetQuote()already exist inapps/api/src/db/bazaar.ts— this needs no new SQL.apps/api/src/__tests__/bazaar.test.tsshows the offline setup: no network, no Postgres.