Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ This project follows [Semantic Versioning](https://semver.org/).

### Added

- **Attachment file and link counts on opportunities and notices** (Tango API 5.9.0; parity with tango-python). Opportunities accept `meta(files_count,links_count)` beside `meta(attachments_count)`, and notices accept `file_count` and `link_count` beside `attachment_count`. An attachment's `type` is `file` (a document; only a file has extracted text) or `link` (a URL the notice lists). The new fields count each, and the existing total still counts every attachment, links included. An attachment of any other type counts only in the total, so files plus links need not equal it. The new fields are `null` until a record has been counted, so read `null` as unknown, not zero. `Opportunity` gains a typed `meta` (the new `OpportunityMeta`), `Notice` gains the three counts, and `docs/API_REFERENCE.md` documents the rules. The SDK's default shapes are unchanged, so name the fields in `shape`.

- **Federal Register documents** (Tango API 5.3.0; parity with tango-python). `listFederalRegisterDocuments(options)` and `getFederalRegisterDocument(uuid, options)` over `/api/federal_register/`, plus a `FederalRegisterDocument` model interface, a registered shape schema, and the `FEDERAL_REGISTER_MINIMAL` / `FEDERAL_REGISTER_COMPREHENSIVE` defaults. These are the rules, proposed rules, notices and presidential documents published in the Federal Register since 1994. All seventeen of the API's filters are typed options on `ListFederalRegisterDocumentsOptions`, including `comments_open`, `cfr_title` / `cfr_part`, `rin`, and both `agency` (a Tango organization, including its sub-agencies) and `fr_agency` (the Federal Register's own agency slug).

`getFederalRegisterDocument()` takes the document's `uuid`, not its `document_number`, because a document number is not unique on its own: the Federal Register reused some before 2016. Look a document up by number with `listFederalRegisterDocuments({ document_number })`. `full_text` is available on the detail method only when named in `shape`, and neither default shape includes it, since it can run to several MB. `ordering: "rank"` requires a non-empty `search`. Documents published before 2008 are mostly typed `Uncategorized Document`, so a `type` filter undercounts that era.

- **Award fields on opportunities and notices** (Tango API 5.5.0; parity with tango-python). `ListOpportunitiesOptions` types the `awarded` and `awardee_uei` filters, both of which search every opportunity rather than only active ones. Opportunity shapes accept `awarded`, `award_count`, `award_date`, `award_amount`, `awardee`, `awardee_uei`, `solicitation_opportunity_id` and an `awards(...)` expand (a list, with `award_number`, `award_date`, `award_amount`, `awardee`, `awardee_uei`, `notice_id`, `opportunity_id`); notice shapes accept `award_date`, `award_amount`, `awardee` and `awardee_uei`.

- **`agency` filter on `listBudgetAccounts()`, `listExclusions()` and `listItDashboard()`** (Tango API 5.3.0; parity with tango-python). It takes a Tango agency name, abbreviation, code or organization key (e.g. `EPA`) and matches the whole organization, so a department includes its sub-agencies; OR several with `|`. On exclusions it scopes by the excluding agency. On IT Dashboard it is available at every plan.

- **`cycle_name` filter on `listSbirTopics()`** (Tango API 5.3.1), an exact match on the DSIP solicitation cycle such as `DOD_SBIR_2026_P1_CBZ`. SBIR topic shapes accept `cycle_name`.

- **Budget account filters `account_category`, `account_category__in`, `data_through_period`, `data_through_period__gte`, `data_through_period__lte` and `data_through_period__isnull`** (Tango API 5.7.0 and 5.8.0) are typed options on `ListBudgetAccountsOptions`, sent verbatim under their dunder names. `data_through_period` is the File A fiscal period (1-12) an account-year's figures run through, so a year below 12 is partial.

- **Shapes accept the fields the API added through 5.9.0.** The `organization(...)` expand on budget accounts, exclusions, SBIR topics and SBIR solicitations (with `organization_id` on the first two); `account_category`, `data_through_period` and `source_anomalies` on budget accounts; and `holder_count` and `order_winner_count` on vehicles. The SDK rejected these client-side before. Default shapes are unchanged.

- **`matched_by` on agency-filter diagnostics** (Tango API 5.9.0; parity with tango-python). Each entry of `PaginatedResponse.meta.resolved_filters[<filter name>]` that resolved now says how its token matched: `key` (an organization UUID), `code` (a 3-digit CGAC or 4-digit FPDS code), `name` (the organization's name, including a department's everyday name, a spelling variant or a rename), `alias` (an abbreviation or the organization's own alias) or `fuzzy` (a looser text match, worth checking against the resolved name). An entry that did not resolve has no `matched_by`. `meta` is passed through as the API sends it, so no code change was needed to receive the field; it is now documented on the interface and in `docs/API_REFERENCE.md` and pinned by a test. `agencyWarnings`, `unresolvedAgencyTokens` and `resolvedAgencies` are unchanged.

- **Boards-of-contract-appeals decisions** (Tango API 4.26.0). `listContractAppeals(options)` and `getContractAppeal(uuid, options)` over `/api/contract_appeals/`, with every filter the API accepts declared as a typed option on `ListContractAppealsOptions` (`search`, `board`, `docket`, `appellant`, `judge`, `decision_type`, the `decision_date_after` / `_before` pair, `listed`, `document_id`, `ordering`), the new `ContractAppealRecord` return type, and a registered `ContractAppeal` shape schema so the typed shape API resolves the resource's fields.
Expand All @@ -30,6 +46,7 @@ This project follows [Semantic Versioning](https://semver.org/).

### Changed

- Re-vendored the contract for Tango API 5.9.0 (51 resources) and regenerated the overlay: 385 fields across 28 containers, 76 nested schemas. `contracts/observed_shape_types.json` is re-vendored from tango-python as well, so the new fields carry the types the API returns (`awards` is a list, `awarded` a boolean, `data_through_period` an integer) instead of types guessed from their names. With Federal Register documents wrapped, eBuy requests are the only resource in the contract without an SDK method, and they stay baselined as a tracked gap.
- Re-vendored `contracts/filter_shape_contract.json` (schema_version 2, 48 resources) and regenerated `src/shapes/generatedOverlay.ts` from it — 359 fields across 25 containers, 73 nested schemas.
- Re-vendored the contract for Tango API 5.1.0 and regenerated the overlay, which now merges a model's expand when two resources embed it instead of letting the narrower copy win. eBuy requests are in the contract without an SDK method yet, so it is baselined as a tracked gap.
- Baselined 14 reverse-shape-coverage gaps in `contracts/shape_coverage_baseline.json`, matching tango-python. All 14 are the nested sub-resource routes above, which reuse the parent resource's model rather than carrying one of their own; none is SLED, and none is a regression — they became visible only with the re-vendored contract.
Expand All @@ -43,6 +60,7 @@ This project follows [Semantic Versioning](https://semver.org/).

### Documentation

- New **Federal Register** section in `docs/API_REFERENCE.md` with both methods and the full filter table, and both new constants in the `docs/SHAPES.md` preset table. `README.md`'s method list gained both methods.
- New **Contract Appeals** section in `docs/API_REFERENCE.md` covering both methods, the full filter table, and the two properties that catch people out (the core-subset default and the tier-gated, absent-rather-than-null `decision_text`). `README.md`'s method list gained both methods.
- New **State & Local (SLED) — Beta** section in `docs/API_REFERENCE.md` covering all six methods, both defaults that surprise people, and the new `ShapeConfig` constants.
- `docs/WEBHOOKS.md` troubleshooting gained the date-lapse rule and its one exception. An exclusion or a DIBBS solicitation reaching its date fires nothing, because open/closed is derived at query time — but `alerts.sled_opportunity.match` **does** fire on a closing, since SLED liveness is a stored column a fifteen-minute sweep writes.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,12 @@ The Node.js client mirrors the Python SDK's high-level API. Selected highlights:
- `getForecast(id, options)` / `getOpportunity(opportunityId, options)` / `getNotice(noticeId, options)` / `getGrant(grantId, options)`
- `searchOpportunityAttachments(options)`

**GSA eLibrary / Protests / Contract Appeals / IT Dashboard / LCATs**
**GSA eLibrary / Protests / Contract Appeals / Federal Register / IT Dashboard / LCATs**

- `listGsaElibraryContracts(options)` / `getGsaElibraryContract(uuid, options)`
- `listProtests(options)` / `getProtest(caseId)`
- `listContractAppeals(options)` / `getContractAppeal(uuid, options)`
- `listFederalRegisterDocuments(options)` / `getFederalRegisterDocument(uuid, options)`
- `listItDashboard(options)` / `getItDashboard(uii)`
- `listLcats(options)` / `listIdvLcats(key, options)`

Expand Down
Loading
Loading