@classytic/ca-tax 0.0.19 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.20] - 2026-09-09
4
+
5
+ ### Added — every shipped rate table declares its own provenance, and the declaration is enforced
6
+
7
+ A new `@statutory-data` doc block on every module exporting a `RateBook` (and the two
8
+ effective-dated rate tables) states its coverage years, sourcing status
9
+ (`primary-sourced`/`partially-sourced`/`reference-only`), last-verified date, cited sources, and
10
+ known gaps. `tests/statutory-data-provenance.test.ts` enforces four things a comment alone
11
+ cannot: a new rate book cannot ship without the block; a cited vendored document must actually
12
+ exist on disk; the declared `covers:` years must match the years the book actually ships (this
13
+ one would have caught a real defect — every reference book in this package stops at 2024 while
14
+ a host may already have registered 2026); and the roster of unsourced/unverified files is
15
+ pinned, so provenance debt can shrink but never grow silently.
16
+
17
+ Result of running the check against this package's own five rate books: general corporate rates,
18
+ CCA rates, and the Québec CO-17 rate table are `partially-sourced` or `reference-only` and have
19
+ never been checked against a primary document (`verified: never`); the 22-figure
20
+ `PROVINCE_RATE_BOOK` (11 provinces × general + small-business) has zero sourced figures at all —
21
+ the single largest provenance gap in the package. Alberta's rate stack and the GST/HST rate table
22
+ are `primary-sourced` and dated. None of this changes any shipped rate value; it makes the
23
+ package's real sourcing position visible and machine-checked rather than asserted in a comment
24
+ that could go stale unnoticed.
25
+
26
+ ### Fixed — AT1 Schedule 21 line 059 cited no federal source at all
27
+
28
+ Line 059's own printed caption reads "as reported on Federal Schedule 4 line 220" — the ABILs
29
+ expired as non-capital losses — but the field carried no `from` reference, while line 057 right
30
+ above it (current-year capital loss, from Schedule 4 line 210) did. The two are genuinely
31
+ different federal lines; 059 now cites S4 220, pinned by a test asserting both citations point
32
+ at their own line rather than one having been generalized onto the other.
33
+
34
+ ### Changed — Schedule 21's capital-loss pool columns now say GROSS in their own heading
35
+
36
+ The column already carried a note warning that Schedule 12 wants the allowable half and that
37
+ carrying the raw figure over-deducts by roughly two — the heading and all ten row captions in
38
+ the pool now say "gross" up front, so a preparer reading the grid knows which figure the column
39
+ holds before reaching that note.
40
+
3
41
  ## [0.0.19] - 2026-09-09
4
42
 
5
43
  ### Fixed — AT1 Schedule 12 was missing three mandatory computed lines entirely
package/dist/forms.mjs CHANGED
@@ -3443,7 +3443,7 @@ const AT1_SCHEDULE_21_POOLS = [
3443
3443
  },
3444
3444
  {
3445
3445
  key: "capital",
3446
- label: "Net capital losses",
3446
+ label: "Net capital losses (Gross amount)",
3447
3447
  carriedForward: "051",
3448
3448
  windUpTransfer: "055",
3449
3449
  currentYearLoss: "057",
@@ -3791,6 +3791,7 @@ const continuityFields = AT1_SCHEDULE_21_POOLS.flatMap((pool) => CONTINUITY_ORDE
3791
3791
  const isAppliedLine = k === "appliedAgainstIncome";
3792
3792
  const isOpening = k === "opening";
3793
3793
  const isCurrentYearLoss = k === "currentYearLoss";
3794
+ const isAbilExpired = k === "abilExpired";
3794
3795
  let role = "input";
3795
3796
  let from;
3796
3797
  const closingFootnotes = {
@@ -3814,6 +3815,11 @@ const continuityFields = AT1_SCHEDULE_21_POOLS.flatMap((pool) => CONTINUITY_ORDE
3814
3815
  line: pool.key === "farm" ? "310" : "410",
3815
3816
  note: "Defaults to this federal figure — override only where Alberta genuinely diverges."
3816
3817
  };
3818
+ else if (isAbilExpired) from = {
3819
+ form: "T2SCH4",
3820
+ line: "220",
3821
+ note: "Printed on the form: \"as reported on Federal Schedule 4 line 220\" — federal line 220 is \"ABILs expired as non-capital losses (line 215 multiplied by 2)\". An expiring ABIL leaves the non-capital pool and arrives here as a net capital loss."
3822
+ };
3817
3823
  else if (isCarryBack) role = "computed";
3818
3824
  const footnoteMarks = isClosing ? closingFootnotes[pool.key] : void 0;
3819
3825
  return {
package/dist/index3.d.mts CHANGED
@@ -92,6 +92,23 @@ declare function resolveAlbertaTaxRates(taxYear: number, book?: RateBook<Alberta
92
92
  * after 2020-06-30 8.0%
93
93
  *
94
94
  * Pure, no I/O. Whole dollars.
95
+ *
96
+ * @statutory-data
97
+ * covers: 2006-04-01 onward (effective-dated bands, not year-versioned)
98
+ * status: primary-sourced
99
+ * verified: 2026-09-09
100
+ * sources:
101
+ * - research/sources/tra-spec/AT1-Chapter3-2026.4-full.txt §3.2.3.1 line 068
102
+ * ("Basic Alberta Tax Payable"). The spec defines the day counts B–F and
103
+ * their multipliers H–L; every band above is a transcription of that pair:
104
+ * B after 2006-03-31, before 2015-07-01 H = A x .100 x B/H
105
+ * C after 2015-06-30, before 2019-07-01 I = A x .120 x C/H
106
+ * D after 2019-06-30, before 2020-01-01 J = A x .110 x D/H
107
+ * E after 2019-12-31, before 2020-07-01 K = A x .100 x E/H
108
+ * F after 2020-06-30 L = A x .080 x F/H
109
+ * "Value = H + I + J + K + L. Round up at $.50 to the nearest dollar. If
110
+ * the value is negative, default = zero." — the rounding and floor this
111
+ * module implements.
95
112
  */
96
113
  interface GeneralRateBand {
97
114
  /** Inclusive start of the band, ISO `YYYY-MM-DD`. */
package/dist/t2.mjs CHANGED
@@ -57,6 +57,23 @@ function extendRateBook(base, overrides) {
57
57
  * Never mutate a shipped year — add a new {@link RateBookEntry} to the host book.
58
58
  * A host wires future Alberta years / TRA-published values via the same
59
59
  * effective-dated seam the federal engine uses (see rates/rate-book.ts).
60
+ *
61
+ * @statutory-data
62
+ * book: AB_TAX_RATE_BOOK
63
+ * covers: 2024
64
+ * status: partially-sourced
65
+ * verified: 2026-09-09
66
+ * sources:
67
+ * - research/sources/tra-spec/AT1-Chapter3-2026.4-full.txt §3.2.3.1 line 068 —
68
+ * GENERAL_RATE 8%, as band F of the day-weighted table (`L = A x .080 x F/H`,
69
+ * days after 2020-06-30). See rates/general-rate-bands.ts for the full table.
70
+ * - research/sources/tra-spec/AT1-Chapter3-2026.4-full.txt §3.2.3.2 —
71
+ * BUSINESS_LIMIT $500,000, in effect since 2009-04-01.
72
+ * gaps:
73
+ * - SMALL_BUSINESS_RATE (2%) appears in NO vendored source. The AT1 spec states
74
+ * no small-business rate at all: its only rate multipliers are the five
75
+ * general-rate bands above. Verify against the Alberta Corporate Tax Act /
76
+ * TRA's published rate page before relying on it to file.
60
77
  */
61
78
  const AB_TAX_2024 = Object.freeze({
62
79
  GENERAL_RATE: .08,
@@ -4442,6 +4459,23 @@ function albertaCurrentYearLoss(result) {
4442
4459
  *
4443
4460
  * Rates per CRA T4012 / ITR Schedule II. T2 CCA amounts are whole dollars (GIFI
4444
4461
  * convention), so the CCA calculator works in integer dollars — NOT cents.
4462
+ *
4463
+ * @statutory-data
4464
+ * book: CCA_RATE_BOOK
4465
+ * covers: 2024
4466
+ * status: partially-sourced
4467
+ * verified: never
4468
+ * sources:
4469
+ * - research/sources/legislation/ITR-section-1100-cca-deductions.txt —
4470
+ * the Reg 1100(1) allowance rates these classes are drawn from.
4471
+ * - research/sources/legislation/ITR-schedule-III-class-13-leasehold.txt —
4472
+ * class 13, which is straight-line and deliberately NOT in this table.
4473
+ * gaps:
4474
+ * - The per-class rates are transcribed from ITR Schedule II, which is not
4475
+ * vendored; ITR s.1100 above is the deduction mechanism, not the class list.
4476
+ * - No class rate has been checked against a primary document on a recorded
4477
+ * date. Class rates move rarely, so staleness is a lower risk here than in
4478
+ * the year-tagged tax tables — but it is unmeasured, not measured-as-fine.
4445
4479
  */
4446
4480
  const CCA_DECLINING_BALANCE_RATES_2024 = Object.freeze({
4447
4481
  "1": .04,
@@ -6196,6 +6230,28 @@ function federalSchedulePayloads(r) {
6196
6230
  *
6197
6231
  * Never mutate a shipped year — add a new {@link RateBookEntry} for the new
6198
6232
  * year (in the host book) so prior-year returns stay reproducible.
6233
+ *
6234
+ * @statutory-data
6235
+ * book: CORP_TAX_RATE_BOOK
6236
+ * covers: 2024
6237
+ * status: partially-sourced
6238
+ * verified: never
6239
+ * sources:
6240
+ * - research/sources/legislation/ITA-section-123.4-general-rate-reduction.txt —
6241
+ * GENERAL_RATE_REDUCTION (13%).
6242
+ * - research/sources/legislation/T4012-lines-638-639-general-tax-reduction.txt —
6243
+ * the general tax reduction as CRA states it on the return.
6244
+ * - research/sources/legislation/ITA-section-191.1-part-vi-1-tax.txt —
6245
+ * the PART_VI_1_* rates.
6246
+ * gaps:
6247
+ * - The rate stack itself (BASIC_RATE 38%, FEDERAL_ABATEMENT 10%, SBD_RATE 19%)
6248
+ * is transcribed from ITA s.123/124/125, which are NOT vendored.
6249
+ * - The thresholds (BUSINESS_LIMIT, TC_GRIND_*, AAII_*, SRED_*) and the
6250
+ * refundable fractions have no vendored source.
6251
+ * - No value in this file has been checked against a primary document on a
6252
+ * recorded date, which is what `verified: never` means. It is a REFERENCE
6253
+ * table: a host filing a real return supplies CRA-published figures through
6254
+ * CORP_TAX_RATE_BOOK.
6199
6255
  */
6200
6256
  const CORP_TAX_2024 = Object.freeze({
6201
6257
  BASIC_RATE: .38,
@@ -6478,6 +6534,21 @@ function blendProvinceRateTable(baseTable, changes, periodStart, periodEnd) {
6478
6534
  * ⚠ REFERENCE VALUES for tax year 2024 — verify against each province's current
6479
6535
  * schedule before filing. They are year-versioned in {@link PROVINCE_RATE_BOOK}
6480
6536
  * so a host wires the authoritative figures without an engine change.
6537
+ *
6538
+ * @statutory-data
6539
+ * book: PROVINCE_RATE_BOOK
6540
+ * covers: 2024
6541
+ * status: reference-only
6542
+ * verified: never
6543
+ * sources: none
6544
+ * gaps:
6545
+ * - All 22 figures (11 provinces × general + small-business) are unsourced.
6546
+ * Each province legislates its own rate and publishes its own schedule;
6547
+ * none of those are vendored, and several provinces have changed rates
6548
+ * since 2024 — so these values are a plausible starting shape, not a
6549
+ * filing authority, and the header above says so.
6550
+ * - A host MUST supply its own PROVINCE_RATE_BOOK before filing a T2 with a
6551
+ * Schedule 5. This is the single largest provenance gap in the package.
6481
6552
  */
6482
6553
  /** 2024 reference rates (general / small-business). Host overrides via the book. */
6483
6554
  const PROVINCE_RATES_2024 = Object.freeze({
@@ -9255,6 +9326,21 @@ function formatConformanceReport(summary) {
9255
9326
  * 2026-04-29 — wire that year via the rate book.
9256
9327
  *
9257
9328
  * Never mutate a shipped year — add a host rate-book entry for a new year.
9329
+ *
9330
+ * @statutory-data
9331
+ * book: QC_TAX_RATE_BOOK
9332
+ * covers: 2024
9333
+ * status: reference-only
9334
+ * verified: never
9335
+ * sources: none
9336
+ * gaps:
9337
+ * - GENERAL_RATE (11.5%), SMALL_BUSINESS_RATE (3.2%), BUSINESS_LIMIT and
9338
+ * SBD_HOURS_THRESHOLD (5,500) are transcribed from the Taxation Act (Québec)
9339
+ * and Revenu Québec guidance, neither of which is vendored. The CO-17 forms
9340
+ * under research/sources/rq-forms carry line captions, not rates.
9341
+ * - The doc comment above notes the SBD rate rises (small-business rate 2.2%)
9342
+ * for tax years beginning after 2026-04-29. That year is NOT in this book —
9343
+ * resolving 2026 returns the 2024 entry. A host must wire it.
9258
9344
  */
9259
9345
  const QC_TAX_2024 = Object.freeze({
9260
9346
  name: "Québec",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/ca-tax",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "Canadian corporate tax engine for @classytic/tax-core — federal T2, Alberta AT1 and Québec CO-17 with form definitions traced to the published forms, plus GST/HST/PST/QST with dated provincial regimes.",
5
5
  "type": "module",
6
6
  "license": "MIT",