Review: Add POST /admin/contract/offer endpoint (v2)

review-931-2026-04-10-v2 Doc

review approved

Verdict: APPROVED

Second-pass review of board item #931 (basketball-api#425). Prior review review-931-2026-04-10 returned NEEDS_REFINEMENT with 5 items. All 5 refinements verified applied.

Refinements Verified

  • [x] Canonical field names — issue body uses contract_signed_at, contract_signed_by, contract_signed_ip, contract_signature_url throughout. No shorthand variants found. Acceptance Criteria block lists all canonical fields up front and states "All references below use these exact names."
  • [x] contract_token in archived JSONB snapshot — "The archived JSONB snapshot in old_state MUST include" list has contract_token as first bullet with justification "critical for tracing disputed signed URLs later". Also referenced in the signed→offered transition bullet.
  • [x] force as query parameter — Request shape explicitly shows POST /admin/contract/offer?force=true // force is QUERY PARAM, not body. Follow-up paragraph: "force is a query parameter (?force=true), not a body field. This matches FastAPI convention for 'modifier' flags..." Referenced again in acceptance criteria and 422 validation list.
  • [x] Dependency Semantics (revised) section — Distinct "PR-merge blockers (none)" vs "Prod-smoke-test blockers (two, but only for specific batch runs)". #420 and #422 correctly classified as prod-smoke-test blockers, not PR-merge blockers. Explicit statement: "Neither blocks this endpoint's PR itself."
  • [x] story:WS-S23 secondary label — Board item labels: type:feature,arch:basketball-api,story:WS-S23,story:WS-S7,scope:discovered. Both story labels present. Traceability footer notes WS-S23 primary, WS-S7 secondary.

Bonus Refinement

  • [x] Transaction boundary nit addressed — Constraints and Database integrity blocks both note: "use a real DB transaction, not begin_nested() (which is a SAVEPOINT, not a top-level transaction)" and "Transaction boundaries must be explicit (top-level db.begin() / with block, NOT begin_nested())".

Prior Verified Dimensions (still in force)

  • [x] Template completeness (Feature template)
  • [x] File targets verified against basketball-api main
  • [x] Transaction boundary semantics now explicit
  • [x] 5-minute rule: fits single agent pass with tight scope

Recommendation

No action needed. Ticket is ready to move backlog → todo. Unblocks basketball-api #424 (Marcus 2026-04-10 batch).