SBA OHA on protests: naics_code filter, five OHA fields, conformance mapping#12
Open
makegov-mark[bot] wants to merge 1 commit into
Open
SBA OHA on protests: naics_code filter, five OHA fields, conformance mapping#12makegov-mark[bot] wants to merge 1 commit into
makegov-mark[bot] wants to merge 1 commit into
Conversation
The Tango API now serves SBA OHA (Office of Hearings and Appeals) decisions on /api/protests/ as a third source_system, alongside GAO and the Court of Federal Claims. This brings the SDK to parity, mirroring the tango-python change of the same name. ListProtestsOptions gains naics_code. It is sent verbatim, NOT remapped onto `naics` the way listContracts() and listOpportunities() remap the same option — the protests API param is literally naics_code. The new client test asserts both halves of that. ProtestRecord, PROTEST_SCHEMA, and PROTEST_DOCKET_SCHEMA gain challenged_party, naics_code, size_standard, outcome_reason, and judge. ProtestRecord has an index signature, so these already parsed at runtime — declaring them is what gives consumers types instead of `unknown`. The schema parity counts move 18 -> 23 (case) and 16 -> 21 (docket), verified against tango-python's explicit_schemas.py rather than assumed. Also maps `protests` in RESOURCE_TO_METHOD. It had no entry, so the resource was reported as "no SDK method mapped" and its filters were never validated against the contract — the same blind spot as the Python SDK, which is why the gap survived in both. Verified the checker now sees it: removing naics_code reports "protests: `listProtests` relies on index signature for filters: naics_code". 222 tests pass; typecheck, eslint, and build clean. The three prettier warnings on touched files pre-exist on origin/main (verified in a clean worktree).
vdavez
force-pushed
the
feat/protests-sba-oha
branch
from
July 9, 2026 17:45
85cd202 to
77f2878
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SDK parity for SBA OHA on the protests endpoint. Mirrors makegov/tango-python#50.
What
The Tango API now serves SBA OHA (the Small Business Administration's Office of Hearings and Appeals) decisions on
/api/protests/as a thirdsource_system, alongside GAO and the Court of Federal Claims. Three things follow:ListProtestsOptions.naics_code— the new API filter. It is sent verbatim, not remapped ontonaicsthe waylistContracts()andlistOpportunities()remap the identically-named option. The protests API param really isnaics_code. The new client test asserts both halves:naics_code=541512present,naicsabsent.ProtestRecord,PROTEST_SCHEMA, andPROTEST_DOCKET_SCHEMA—challenged_party,naics_code,size_standard,outcome_reason,judge. Opt-in viashape=and ungated by tier.ProtestRecordcarries an index signature, so these already parsed at runtime; declaring them is what gives consumers types instead ofunknown.protestsmapped in the conformance script'sRESOURCE_TO_METHOD.Why the gap existed at all
protestshad no entry inRESOURCE_TO_METHOD, so the checker reportedprotests: no SDK method mapped in conformance script— even thoughlistProtestshas existed all along — and its filters were never validated against the contract. The Python SDK had the identical blind spot, which is why the same gap survived in both at once.With the mapping in place the checker sees it. Verified by removing the option:
Worth being precise about the strength of this gate: because
ListProtestsOptionshas[key: string]: unknown, a missing filter is a warning, not an error — unlike the Python side, where it is a hard error. The index signature means the call would still have worked; what was missing was the type and the discoverability.Schema parity counts
tests/unit/shapes.schema.parity.test.tspins field counts againsttango-python'sexplicit_schemas.py. Those move18 → 23(case) and16 → 21(docket). I read the real counts off both SDKs rather than assuming the delta:Added assertions that the five OHA fields are optional
strscalars with no nested model, and that they are present in the docket schema too (they're servable insidedockets(...)).Testing
npm run typecheck,npm run lint, andnpm run buildall clean.errors=0, andprotestsno longer appears in the warnings.prettier --check:src/client.ts,scripts/check-filter-shape-conformance.ts,tests/unit/shapes.schema.parity.test.ts. All three already fail onorigin/main— verified in a cleangit worktreeso the repo's prettier config actually applied, rather than by piping through stdin. This PR adds no new formatting debt, and I did not reformat them, since that would bury the real diff.Risks
Additive only. Every new field is optional, and
ProtestRecord's index signature meant they already flowed through untyped. No existing option changed meaning.Merge once SBA OHA is live on the production API — until then
?source_system=sba_ohareturns nothing andnaics_codematches nothing, so the SDK is correct but the data is not yet visible.🤖 Generated with Claude Code