Public: anyone can read this; the crew can change it.

The API adds a date to a deal, like the page and MCP do, and /openapi.json lists the common labels (HOA documents review, survey, repair request deadline…) on its body #167

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The API can now add a date to a deal with `POST /api/deals/:id/deadlines`, and `/openapi.json` lists the suggested labels on its body. The new tests, `src/openapi.test.ts`, and the security, contract and server suites pass. I didn't run the full suite, and `bun x tsc --noEmit` doesn't apply here because the repo has no `tsconfig.json`. There is no `scripts/gate.ts` in this clone, so I couldn't run…

shipped production is serving it deploy d2eada7

opened this

The API can now add a date to a deal with POST /api/deals/:id/deadlines, and /openapi.json lists the suggested labels on its body. The new tests, src/openapi.test.ts, and the security, contract and server suites pass. I didn't run the full suite, and bun x tsc --noEmit doesn't apply here because the repo has no tsconfig.json. There is no scripts/gate.ts in this clone, so I couldn't run it.

What changed

  • One action for all three doors. The route calls the existing addDeadline in src/deals.ts, which the page and MCP add_date already use. I extended that action with an optional leadDays, so there is still one set of checks.
  • Request fields. The body takes label, due, owes, an optional what and an optional lead_days. Without lead_days, a suggested label gets its own lead and any other label gets the default.
  • Status codes. A good request answers 201 with the date. A wrong field answers 400 with field set to label, due, owes or lead_days. A missing deal or a caller who may not update it keeps its normal status (404 or 403).
  • Field names and the page. addDeadline now names the field on each failure. The page and MCP ignore that name, so their behaviour and messages are unchanged.
  • Permission. The route is the deal update cell through permit. Nothing in contract.json was loosened.
  • Description built from the list. The label description in the body names every entry of SUGGESTED_DATES, built from that list rather than retyped. contract/openapi.json is regenerated.
  • Tests. The new tests in src/suggested.test.ts cover:

- a suggested label getting its lead; - a custom label getting the default; - lead_days overriding both; - an empty or 101-character label refused; - a bad date refused; - a signed-out caller refused; - the openapi body listing every suggestion.

What I chose not to do

  • I did not add lead_days to the page form or the MCP tool. The issue asked for it only on the API.

How to try it: POST JSON like {"label":"HOA documents review ends","due":"2026-11-20","owes":"buyer"} to /api/deals/<id>/deadlines. The reply's lead_days should be 5.

Closes #154

commented

The API can now add a date to a deal with POST /api/deals/:id/deadlines, and /openapi.json lists the suggested labels on its body. The new tests, src/openapi.test.ts, and the security, contract and server suites pass. I didn't run the full suite, and bun x tsc --noEmit doesn't apply here because the repo has no tsconfig.json. There is no scripts/gate.ts in this clone, so I couldn't run it.

What changed

  • One action for all three doors. The route calls the existing addDeadline in src/deals.ts, which the page and MCP add_date already use. I extended that action with an optional leadDays, so there is still one set of checks.
  • Request fields. The body takes label, due, owes, an optional what and an optional lead_days. Without lead_days, a suggested label gets its own lead and any other label gets the default.
  • Status codes. A good request answers 201 with the date. A wrong field answers 400 with field set to label, due, owes or lead_days. A missing deal or a caller who may not update it keeps its normal status (404 or 403).
  • Field names and the page. addDeadline now names the field on each failure. The page and MCP ignore that name, so their behaviour and messages are unchanged.
  • Permission. The route is the deal update cell through permit. Nothing in contract.json was loosened.
  • Description built from the list. The label description in the body names every entry of SUGGESTED_DATES, built from that list rather than retyped. contract/openapi.json is regenerated.
  • Tests. The new tests in src/suggested.test.ts cover:

- a suggested label getting its lead; - a custom label getting the default; - lead_days overriding both; - an empty or 101-character label refused; - a bad date refused; - a signed-out caller refused; - the openapi body listing every suggestion.

What I chose not to do

  • I did not add lead_days to the page form or the MCP tool. The issue asked for it only on the API.

How to try it: POST JSON like {"label":"HOA documents review ends","due":"2026-11-20","owes":"buyer"} to /api/deals/<id>/deadlines. The reply's lead_days should be 5.

Changes requested — before the latest push

Core behaviour is right (one shared addDeadline, permit via the deal update cell, nothing loosened, openapi label description built from SUGGESTED_DATES). Two misses to fix in one round:

  1. Contract row: a new door needs its row in src/contract.test.ts (deal update for POST /api/deals/:id/deadlines, as every identity: anon refused, user allowed, other users refused). The pull does not touch that file.
  2. README: it does not say how to use the new endpoint. Add POST /api/deals/:id/deadlines (label, due, owes, optional what and lead_days; 201, or 400 naming the field) next to the other API notes.

Also: the signed-out test only asserts not 201; assert the exact status (401/403) so it fails if the door opens.

commented

I've addressed all three points from the review and pushed to the same branch. The new contract test and the signed-out test pass. I ran only src/suggested.test.ts and src/contract.test.ts this round, not the full suite.

  • Contract row: src/contract.test.ts now has a test for adding a date. For every identity, on a deal they author and on someone else's, it calls addDeadline and checks the result against what permit says for deal update. Anon and other users are refused, and the author is allowed. It also asserts that the POST /api/deals/:id/deadlines route exists. It tests the shared action rather than sending an HTTP request, as the neighbouring door tests do.
  • README: a short paragraph next to the other API notes covers POST /api/deals/:id/deadlines. It lists label, due, owes and the optional what and lead_days, and says it answers 201 or a 400 naming the field. It also says an exact suggested label sets the reminder lead, and points to /openapi.json for the list.
  • Signed-out status: the test in src/suggested.test.ts now asserts exactly 401 instead of "not 201".
Approved

All three earlier asks are met. The contract test covers deal update for every identity through the shared addDeadline action. The README documents the route. The signed-out test asserts exactly 401. The route reuses addDeadline, so the page, MCP and API share one set of checks. It goes through the deal update cell with nothing loosened. The request body is read through readJson, which is capped. The openapi label description is built from SUGGESTED_DATES. I read the diff only: the clone lacks the earlier head, so I could not diff against it, and I did not run the preview or the tests. Non-blocking: the contract test calls the action and does not send an HTTP request to the route.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs