SBA OHA on protests: naics_code filter, five OHA fields, conformance mapping#50
Open
makegov-mark[bot] wants to merge 1 commit into
Open
SBA OHA on protests: naics_code filter, five OHA fields, conformance mapping#50makegov-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. list_protests() gains a naics_code filter. It is sent verbatim, NOT remapped onto `naics` the way list_contracts() and list_opportunities() remap the same kwarg — the protests API param is literally naics_code. Protest, PROTEST_SCHEMA, and PROTEST_DOCKET_SCHEMA gain challenged_party, naics_code, size_standard, outcome_reason, and judge. All five are opt-in via shape= (null on gao/cofc rows) and ungated by tier, so they belong in the schemas but not in PROTESTS_MINIMAL. Also maps `protests` in the conformance checker's RESOURCE_TO_METHOD. It had no entry, so the resource fell through to "no SDK method implemented" and its filters were never validated against the contract — which is precisely how the naics_code gap survived. Verified the gate now bites: removing the kwarg produces "protests: `list_protests` missing runtime filters: naics_code". Refreshed the vendored contract via scripts/refresh_contract.py. That also picks up unrelated drift accumulated since it was last vendored (opportunities `active`, max_page_size, two filter-class renames) — it is a generated file and cherry-picking would leave it internally inconsistent. 307 unit tests pass; mypy clean.
vdavez
force-pushed
the
feat/protests-sba-oha
branch
from
July 9, 2026 17:45
2f9e2b1 to
8d0e91d
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.
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:list_protests(naics_code=...)— the new API filter. It is sent verbatim, not remapped ontonaicsthe waylist_contracts()andlist_opportunities()remap the identically-named kwarg. The protests API param really isnaics_code. There is a test for both halves of that.Protest,PROTEST_SCHEMA, andPROTEST_DOCKET_SCHEMA—challenged_party,naics_code,size_standard,outcome_reason,judge. Opt-in viashape=and ungated by tier, so they belong in the schemas but deliberately not inPROTESTS_MINIMAL(they're null on GAO/CoFC rows, which is the large majority of the table).protestsmapped in the conformance checker'sRESOURCE_TO_METHOD.Why the gap existed at all
protestshad no entry inRESOURCE_TO_METHOD, so it fell through toNoneand the checker emittedprotests: no SDK method implemented for this resource— even thoughlist_protestshas existed all along. Its filters were never validated against the contract. That is precisely hownaics_codeslipped through, and the identical blind spot exists intango-node(fixed in its companion PR, makegov/tango-node#12).With the mapping in place the gate is real, not decorative. Verified by removing the kwarg:
and restoring it returns
errors: []with the protests warning gone.The vendored contract
Refreshed via
scripts/refresh_contract.py(the sanctioned path). Beyondprotests.naics_code, that picks up drift accumulated since it was last vendored: opportunities'active, twomax_page_size: null → 100corrections,NoticeSearchFilter/OpportunityPlaceOfPerformanceFilterclass renames, and anamefilter.I kept the full refresh rather than cherry-picking
naics_code: it is a generated file, and hand-editing it would leave it internally inconsistent with its own source. None of the extra drift produces a conformance error — the baseline absorbs the known gaps.Testing
mypy tango/clean.TestListProtestsNaicsCodeFilter—naics_codereaches the wire asnaics_code,naicsis absent, and an omitted filter sends no key at all.TestProtestOhaShapeFields— the five fields parse off a shaped response into the dynamic model.errors: [], andprotestsno longer appears in the warnings.ruff check/ruff formatclean on every file this PR touches. (21 pre-existing ruff errors elsewhere in the repo are untouched.)Risks
Additive only.
Protestis a schema dataclass with defaults, so new optional fields break no constructor. No existing kwarg 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