Skip to content

feat(ebuy): add GSA eBuy requests, attachment URLs and access check - #21

Draft
makegov-mark[bot] wants to merge 1 commit into
mainfrom
feat/ebuy
Draft

makegov-mark[bot] wants to merge 1 commit into
mainfrom
feat/ebuy

Conversation

@makegov-mark

@makegov-mark makegov-mark Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

What

Adds GSA eBuy support (Tango API 5.1.0), with the same four operations as the Python SDK:

  • listEbuyRequests(options) — /api/ebuy/requests/, every API filter as a typed option on ListEbuyRequestsOptions (search, rfq_id, reference_number, request_type, status, sin, schedule, buyer_agency, agency, contract_number, issue_date_* / close_date_* bounds, ordering).
  • getEbuyRequest(rfqId, options) — detail by request id, with shape / flat / flatLists / joiner.
  • getEbuyAttachmentUrl(rfqId, docSeqNum) — returns the presigned URL the download endpoint redirects to, without following it. An external-link entry throws the new TangoEbuyAttachmentLinkError (a TangoValidationError) carrying the link's url; an uncaptured document throws TangoNotFoundError.
  • getEbuyAccess() — { enabled, reason, contracts } from /api/ebuy/access/.

New types EbuyRequestRecord, EbuyAttachmentRecord, EbuyAccess; registered EbuyRequest / EbuyAttachment shape schemas. HttpClient gained getRedirectLocation() (a GET with redirect: "manual" that resolves to the Location header).

Why

eBuy requests were in the vendored contract without an SDK method, baselined as a tracked gap. This closes it: ebuy/requests is now mapped in the conformance gate and removed from both coverage baselines, and the shape overlay is regenerated.

Behavior worth knowing (documented in docs/API_REFERENCE.md and the JSDoc)

  • Results are scoped to the GSA schedule contracts linked to the caller's account; an account with none gets an empty list, not an error. getEbuyAccess() tells the two apart.
  • status is frozen at the last-seen state, so Open means "open the last time it was seen"; last_seen is the staleness signal.
  • The attachment URL expires after about five minutes.
  • The agency filter needs Tango API 5.3.0.

Testing

  • npm run lint, npm run typecheck, npm run build, npx vitest run (483 passed), check-filter-shape-conformance (0 errors), check-shape-coverage (no new drift), and the overlay regenerates without drift.
  • New tests/unit/client.ebuy.test.ts (47 tests) with a mocked transport: wire names for every filter, the detail route, the manual redirect, the link and not-captured error paths, the access payload, and the shape schema.
  • No cassettes: eBuy data is scoped to the caller's own contracts, so it is not recorded into this public repo. The four methods were smoke-tested by hand against the live API (list, detail, attachment URL via native fetch with manual redirect, 404 for an unknown id).

🤖 Generated with Claude Code

`listEbuyRequests`, `getEbuyRequest`, `getEbuyAttachmentUrl` and `getEbuyAccess` cover `/api/ebuy/requests/` and `/api/ebuy/access/` (Tango API 5.1.0).
Every filter the API accepts is a typed option on `ListEbuyRequestsOptions`, and `EbuyRequestRecord`, `EbuyAttachmentRecord` and `EbuyAccess` type the responses.
Results are scoped to the caller's linked schedule contracts, so an account with none gets an empty list; `getEbuyAccess()` tells that apart from no matches.
`getEbuyAttachmentUrl()` returns the presigned URL the download endpoint redirects to without following it, via a new `HttpClient.getRedirectLocation()`, and throws `TangoEbuyAttachmentLinkError` with the link's `url` for an external-link entry.
`EbuyRequest` and `EbuyAttachment` shape schemas are registered, `ebuy/requests` is mapped in the conformance gate and dropped from both coverage baselines, and the overlay is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant