Skip to content

feat(contract-appeals): add the contract appeals resource - #65

Merged
vdavez merged 1 commit into
mainfrom
feat/contract-appeals
Sep 23, 2026
Merged

vdavez merged 1 commit into
mainfrom
feat/contract-appeals

Conversation

@makegov-mark

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

Copy link
Copy Markdown
Contributor

What

Adds the contract_appeals resource, new in Tango API 4.26.0: Contract Disputes Act appeal decisions from the Civilian Board of Contract Appeals (CBCA, 2007 onward) and the Armed Services Board of Contract Appeals (ASBCA, 2010 onward). These are disputes under an existing award, not bid protests — those stay on the protests methods.

  • list_contract_appeals(...) and get_contract_appeal(appeal_id, ...). All ten filters are named parameters: board, docket, appellant, judge, decision_type, decision_date_after / _before, listed, document_id, search, plus ordering and the shared page / limit / shape options.
  • ContractAppeal model, 21 fields, all optional: an unshaped list response carries only a core subset, so an unrequested field is absent rather than null. decision_text is Enterprise-gated and absent below that tier.
  • ShapeConfig.CONTRACT_APPEALS_MINIMAL and ..._COMPREHENSIVE, mirroring the API's own list and retrieve defaults. Neither names decision_text, and a test pins that.

Two changes beyond the endpoint, both deliberate

  • Re-vendored the contract, 4.25.1 → 4.26.0, the way the previous new-resource PR did. Without it the conformance gate cannot see the new method at all. Side effect: it also picks up two SLED fields new in 4.26.0 (delisted_at, meta(jurisdiction_declared)) that the SDK had been rejecting client-side. Both gates still report zero errors and zero new drift, and nothing was added to the baseline. Everything ran off a local checkout, with no network.
  • ContractAppeal's shape schema is hand-curated rather than left to the generated overlay. The generator falls back to name heuristics for a resource it has not sampled, and it got four fields wrong — docket_numbers as a scalar, listed and decision_date_repaired as strings, listing_year as a string. The overlay wins at lookup time, so those guesses would have mis-parsed real responses. Curating the base also makes the generator emit nothing here, so a later regeneration cannot reintroduce them.

Testing

  • pytest: 512 passed, 31 skipped, 15 new.
  • mypy tango/ (strict): clean. ruff format --check and ruff check on the gate's scope: clean.
  • check_filter_shape_conformance.py: 0 errors, and contract_appeals now maps, so every API filter is confirmed present with a compatible annotation.
  • check_shape_coverage.py: 0 new drift.
  • Tests cover the list path with every filter, listed=False surviving rather than being dropped, the limit cap, retrieve by uuid, decision_text present and absent, and shape validation. Mutation-checked: dropping the listed parameter and swapping the retrieve default shape each broke the expected tests.

Notes

  • No version bump. This repo splits that: feature PRs add to ## [Unreleased], and a separate release PR bumps the version and dates the section.
  • Alert types are not modeled as an enum here (query_type is a plain str), so alerts.contract_appeal.match is documented rather than added as a constant. The create_webhook_alert docstring was already stale — it omitted exclusions, both DIBBS types and SLED — and now names the current set and points at list_webhook_event_types() as the authority.
  • No joiner parameter: the API advertises it, but the closest analogs (protests, SLED, DIBBS, SBIR, exclusions) do not expose it, so this follows them.

🤖 Generated with Claude Code

`list_contract_appeals` and `get_contract_appeal` cover `/api/contract_appeals/`, the Contract Disputes Act decisions of the civilian and defense boards of contract appeals, with all ten filters as named parameters and a 21-field `ContractAppeal` model whose fields are optional so a withheld `decision_text` stays absent rather than null.
The vendored contract already carries this resource, so wrapping it removes `contract_appeals` from the shape-coverage baseline.
The shape schema is hand-curated because the overlay generator guesses four of these fields wrong, and the generated overlay wins at lookup time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vdavez
vdavez force-pushed the feat/contract-appeals branch from 5e23b8b to 70d8209 Compare September 23, 2026 13:35
@vdavez
vdavez marked this pull request as ready for review September 23, 2026 13:40
@vdavez
vdavez merged commit 130a0ec into main Sep 23, 2026
11 checks passed
@makegov-mark makegov-mark Bot mentioned this pull request Sep 23, 2026
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