Skip to content

fix(congressional): decode net-worth amounts as fractional and optional members - #401

Merged
benbenbang merged 3 commits into
mainfrom
fix/377-networth
Sep 30, 2026
Merged

benbenbang merged 3 commits into
mainfrom
fix/377-networth

Conversation

@benbenbang

@benbenbang benbenbang commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Congressional net-worth disclosures return fractional monetary amounts and frequently omit or null several members, so the previous integer, required-member decoding rejected valid API responses. This change relaxes the decoding to match the real data across the Rust core, Python bindings and Go SDK.

  • Switch CongressionalMemberNetWorth.value and every CongressionalMemberNetWorthAggregate amount from i64 to f64 (MarketValue) via the integral_f64 codec.
  • Make frequently-absent members optional: itemized member fields and the range max keep a required-but-nullable key, while date_incurred and the aggregate members may be absent and are omitted on re-encode.
  • Propagate the new float and optional types through the fmp-py models, generated stubs, typecheck contract, and the Go SDK models and shadow decoders.
  • Add Python, Rust and Go coverage for fractional amounts, null itemized members, an empty debtDetails object, and absent or null aggregate members, relaxing the required-member assertions.
  • Extend ADR 0033 to document plain Option members with skip_serializing_if for keys seen absent from the object, distinct from the empty-or-null codec rules, and record the Codec::Plain shape in the generator notes.

BREAKING CHANGE: CongressionalMemberNetWorth.value and the CongressionalMemberNetWorthAggregate amounts changed from i64 to f64 (MarketValue). CongressionalMemberNetWorth.category, name, owner and value, CongressionalNetWorthRange.max, CongressionalDebtDetails.date_incurred and the aggregate real_estate, stock, real_estate_liabilities, business_and_self_employment, ownership_interest, options, revolving_and_credit_lines, asset_backed_securities and business_liabilities are now optional (Option / pointer / Optional); handle None. CongressionalMemberNetWorth and CongressionalMemberNetWorthAggregate no longer derive Eq; compare fields instead.

An empty-string incomeRange ("") on some senate-net-worth rows still fails to decode and is tracked separately.

Closes #377

close #377

…onal

Congressional net-worth disclosures return fractional amounts and omit
or null several members, so the previous integer, required-member
decoding rejected valid rows. Switch the monetary amounts to f64
(MarketValue) and make the frequently-absent members optional so real
responses decode without error.

**Decoding fixes (libfmp):**
* CongressionalMemberNetWorth.value and every
  CongressionalMemberNetWorthAggregate amount are now MarketValue (f64)
  instead of i64, serialized through the integral_f64 codec.
* CongressionalMemberNetWorth.category, name, owner and value,
  CongressionalNetWorthRange.max, CongressionalDebtDetails.date_incurred
  and the aggregate real_estate, stock, real_estate_liabilities,
  business_and_self_employment, ownership_interest, options,
  revolving_and_credit_lines, asset_backed_securities and
  business_liabilities are now optional. The itemized members and the
  range max keep a required key that may be null; date_incurred and the
  aggregate members may be absent and are omitted on re-encode.

**Bindings and SDK:**
* Updated the fmp-py models, generated stubs and typecheck contract to
  expose the new float and Optional types.
* Updated the Go SDK models and shadow decoders to use *float64 and
  pointer members, handling missing and null values.

**Tests:**
* Added Python, Rust and Go coverage for fractional amounts, null
  itemized members, an empty debtDetails object and absent aggregate
  members, and relaxed the required-member assertions accordingly.

An empty-string incomeRange ("") on some senate-net-worth rows still fails
to decode; it needs a nested empty-or-null codec and is tracked
separately.

BREAKING CHANGE: CongressionalMemberNetWorth.value and the
CongressionalMemberNetWorthAggregate amounts changed from i64 to f64
(MarketValue). CongressionalMemberNetWorth.category, name, owner and value,
CongressionalNetWorthRange.max, CongressionalDebtDetails.date_incurred and
CongressionalMemberNetWorthAggregate.real_estate, stock,
real_estate_liabilities, business_and_self_employment, ownership_interest,
options, revolving_and_credit_lines, asset_backed_securities and
business_liabilities are now optional (Option / pointer / Optional); handle
None.
…g_if

Extend ADR 0033 to cover response members whose key is seen missing from
the object, not merely null. Such a member becomes a plain `Option<T>`
with `skip_serializing_if = "Option::is_none"` (no `required_option`),
decoding an absent or null key to `None` and omitting it on re-encode via
`omitzero`, matching serde. This is distinct from the empty-or-null codec
rules, which keep a required key.

Document the first case: `CongressionalMemberNetWorthAggregate` omits
several members across all audited `senate-net-worth-aggregated` rows,
with a live probe also seeing `realEstate` and `stock` absent, and
`CongressionalDebtDetails` omits `dateIncurred`. Record the new
`Codec::Plain` shape in the generator notes.

close #377
Add test coverage verifying that omittable aggregate fields decode a JSON
null as None and re-encode without the field, across both the Rust and Go
SDK parity suites.

BREAKING CHANGE: CongressionalMemberNetWorth and CongressionalMemberNetWorthAggregate no longer derive Eq (their f64 amounts); compare fields instead.
@benbenbang
benbenbang enabled auto-merge (rebase) September 30, 2026 16:18
@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Sep 30, 2026
@benbenbang
benbenbang merged commit 351281b into main Sep 30, 2026
9 of 16 checks passed
@benbenbang
benbenbang deleted the fix/377-networth branch September 30, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix!: congressional net worth amounts are fractional and some members are absent

1 participant