Skip to content

fix(tax): compute the CSSS base on total net income per art. 107, 2° - #386

Merged
EraPartner merged 2 commits into
mainfrom
claude/project-thread-myhwjp
Oct 29, 2026
Merged

EraPartner merged 2 commits into
mainfrom
claude/project-thread-myhwjp

Conversation

@EraPartner

Copy link
Copy Markdown
Owner

Requested by EraPartner · project thread

Summary

The special social security contribution (law of 30 March 1994, "bijzondere bijdrage voor de sociale zekerheid") was evaluated on the net professional income without pensions. Art. 107, 2° of that law defines the household income as each member's total net income of WIB 92 arts 7-116 (every income category, after the arts 104-116 deductions such as alimony), without the art. 171 separately taxed income, less the art. 34 pensions. Source read on Justel: https://www.ejustice.just.fgov.be/eli/wet/1994/03/30/1994021117/justel

Consequences fixed:

  • Other taxable income (rental, …) now enters the base. Example IY 2025, single employee 50,000 gross plus 10,000 other income: engine gave 343.16, law gives 566.93.
  • The alimony deduction now lowers the base. Same employee with 10,000 alimony paid: engine gave 343.16, law gives 246.98.
  • Under a joint assessment the alimony balance charged on the other spouse (art. 105, 3°) follows the same allocation as the taxable income; pensions are subtracted from the household total before the clamp.

Only households with an employee or civil servant and either other taxable income or alimony paid are affected; everything else is unchanged (all existing scenario-matrix expectations pass without edits). Found by the 2026-10-29 source audit (vision notes, queries/2026-10-29-belgian-tax-source-audit.md).

Type of change

  • fix — bug fix
  • feat — new feature
  • refactor — no behavior change
  • perf — performance
  • docs — documentation only
  • chore / ci / test — tooling, build, or tests

Checklist

  • Tests pass (bun vitest run in packages/shared-utils: 418 pass) and lint is clean (bun run lint:projects, bun run lint:dead)
  • Types check (tsc --noEmit in packages/shared-utils)
  • Conventional Commit title (type(scope): subject)
  • No leftover console.log / debug code
  • Affected docs/ pages updated (docs/features/belgian-tax.md, docs/reference/belgian-tax-rule-matrix.md)
  • i18n: no new strings

Architecture & data

  • No architectural change
  • No API change (the csss.base figure changes meaning per the law; the shape is unchanged)
  • No schema change

Verification

  • packages/shared-utils: bun vitest run → 23 files, 418 tests pass, including the parity property test between the legacy computeBelgianPIT and computeHouseholdTax.
  • pit.test.ts: the two tests that pinned the old base ("uses professional income only …") now assert the statutory base; household.test.ts gains three cases (other income, alimony overflow under a joint assessment, pensioner paying alimony).
  • tsc --noEmit, bun run lint:projects, bun run lint:dead: clean.

Residual risk & follow-ups

  • Separately taxed income (art. 171) and treaty-exempt income (arts 155-156) are not modelled, so they cannot be excluded from the base; the model has no such inputs.
  • The csss_mixed_activity_base_unverified issue is left as is; art. 107, 2° suggests the whole net income enters the base regardless of activity kind, which could close matrix open item 10 in a follow-up.

Generated by Claude Code

The special social security contribution (law of 30 March 1994) was
evaluated on the net professional income without pensions. Art. 107, 2°
defines the household income as each member's total net income of WIB 92
arts 7-116 (every income category, after the arts 104-116 deductions),
without the art. 171 separately taxed income, less the art. 34 pensions.
Other taxable income (rental, ...) therefore enters the base and the
alimony deduction lowers it; under a joint assessment the alimony
balance charged on the other spouse (art. 105, 3°) follows the same
allocation as the taxable income.

- household.ts: base per partner = pre-quotient taxable income less
  pensions, clamped at 0; joint base = household total less pensions,
  attributed pro rata.
- pit.ts (legacy v1): base = taxableIncome, plus the spouse's income
  under married_joint.
- pit.test.ts: the two tests that pinned the old base now assert the
  statutory one; household.test.ts gains three cases (other income,
  alimony overflow, pensioner paying alimony).
- Rule matrix and feature doc rows corrected.

Found by the 2026-10-29 source audit (vision notes,
queries/2026-10-29-belgian-tax-source-audit.md).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QJtaMLEgjALKcoDNnbHdx
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Coverage Report for backend

Status Category Percentage Covered / Total
🟢 Lines 91.06% (🎯 80%) 23170 / 25443
🟢 Statements 89.33% (🎯 78%) 24933 / 27910
🟢 Functions 91.44% (🎯 76%) 5004 / 5472
🟢 Branches 81.61% (🎯 68%) 17481 / 21419
File CoverageNo changed files found.
Generated in workflow #1958 for commit f13938a by the Vitest Coverage Report Action

…7 notices

The FPS indexation notices N25 and N27 are also published in the Belgisch
Staatsblad (23-02-2024 numac 2024001745; 12-08-2026 numac 2026006085), which
stays reachable when Fisconetplus does not answer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QJtaMLEgjALKcoDNnbHdx
@EraPartner
EraPartner marked this pull request as ready for review October 29, 2026 08:19
@EraPartner
EraPartner enabled auto-merge (squash) October 29, 2026 08:20
@EraPartner
EraPartner merged commit 290d6bc into main Oct 29, 2026
11 checks passed
@EraPartner
EraPartner deleted the claude/project-thread-myhwjp branch October 29, 2026 08:21
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.

2 participants