@classytic/ca-tax 0.0.19 → 0.0.21
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 +100 -0
- package/README.md +16 -0
- package/dist/forms/index.d.mts +2 -2
- package/dist/forms/index.mjs +2 -2
- package/dist/forms.mjs +3284 -491
- package/dist/index.d.mts +835 -5
- package/dist/index.mjs +3 -3
- package/dist/index3.d.mts +288 -10
- package/dist/index4.d.mts +3 -3
- package/dist/t2/index.d.mts +3 -3
- package/dist/t2/index.mjs +3 -3
- package/dist/t2.mjs +284 -36
- package/docs/STATUTORY-DATA.md +109 -0
- package/package.json +3 -3
package/dist/t2.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ft as AT1_SCHEDULE_21_POOLS, ot as SCHEDULE_1_LINE_BY_NUMBER } from "./forms.mjs";
|
|
2
2
|
//#region src/t2/rates/rate-book.ts
|
|
3
3
|
/**
|
|
4
4
|
* Resolve the table in effect for `taxYear` — the entry with the greatest
|
|
@@ -57,6 +57,46 @@ 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
|
+
* - research/sources/tra-forms/pdf/AT1SCH01-small-business-deduction-TRA11723.pdf
|
|
73
|
+
* page 1, "Calculation of the Alberta Small Business Deduction", column F
|
|
74
|
+
* ("SBD Rate") — SMALL_BUSINESS_RATE, by subtraction. See the gap note.
|
|
75
|
+
* gaps:
|
|
76
|
+
* - SMALL_BUSINESS_RATE (2%) is stated DIRECTLY by no vendored source. The AT1
|
|
77
|
+
* spec states no small-business rate at all: its only rate multipliers are
|
|
78
|
+
* the five general-rate bands above.
|
|
79
|
+
*
|
|
80
|
+
* It is now corroborated arithmetically, which is a real improvement on the
|
|
81
|
+
* "appears in NO vendored source" this note used to say. AT1 Schedule 1's
|
|
82
|
+
* own calculation table pre-prints an SBD rate per period, and that rate is
|
|
83
|
+
* the general rate MINUS the small-business rate:
|
|
84
|
+
*
|
|
85
|
+
* 2009-04-01 .070 = 10% − 3% 2019-07-01 .090 = 11% − 2%
|
|
86
|
+
* 2015-07-01 .090 = 12% − 3% 2020-01-01 .080 = 10% − 2%
|
|
87
|
+
* 2017-01-01 .100 = 12% − 2% 2020-07-01 .060 = 8% − 2%
|
|
88
|
+
*
|
|
89
|
+
* Six bands against the general table's five: the extra split at
|
|
90
|
+
* 2017-01-01 is the small-business rate itself moving from 3% to 2%, which
|
|
91
|
+
* the general table has no reason to record. So 2% is right for every year
|
|
92
|
+
* this book covers, and 3% would be needed for a pre-2017 year — which the
|
|
93
|
+
* book does not have an entry for and must not silently apply 2% to.
|
|
94
|
+
*
|
|
95
|
+
* `AT1_SCHEDULE_1_RATE_PERIODS` carries the printed table, and a test
|
|
96
|
+
* cross-checks it against these two constants in both directions, so a
|
|
97
|
+
* future edit to either cannot quietly break the agreement. Still worth
|
|
98
|
+
* confirming against the Alberta Corporate Tax Act before filing a
|
|
99
|
+
* pre-2017 year.
|
|
60
100
|
*/
|
|
61
101
|
const AB_TAX_2024 = Object.freeze({
|
|
62
102
|
GENERAL_RATE: .08,
|
|
@@ -240,6 +280,67 @@ function computeAlbertaTax(input, rates = AB_TAX_2024) {
|
|
|
240
280
|
};
|
|
241
281
|
}
|
|
242
282
|
//#endregion
|
|
283
|
+
//#region src/t2/at1/schedules/schedule21-current-year-loss.ts
|
|
284
|
+
/** Lines that are subtotals on the printed form and have no NetFile line code. */
|
|
285
|
+
const SCHEDULE_21_PART_1_PRINT_ONLY = ["013", "015"];
|
|
286
|
+
/**
|
|
287
|
+
* Net capital losses deducted — the CAPITAL pool's applied amount times the
|
|
288
|
+
* inclusion rate.
|
|
289
|
+
*
|
|
290
|
+
* Shared, not duplicated: Schedule 21 line 003 and Schedule 12 line 066 must
|
|
291
|
+
* state the same figure ("Schedule 21 line 061 x Inclusion Rate" is printed over
|
|
292
|
+
* 066), and computing it in two places is how they would drift.
|
|
293
|
+
*/
|
|
294
|
+
function allowableCapitalLossApplied(applied, inclusionRate = .5) {
|
|
295
|
+
return Math.round(inclusionRate * Math.max(0, Math.round(applied)));
|
|
296
|
+
}
|
|
297
|
+
/** A positive whole-dollar amount — every deduction in this part is "entered as a positive". */
|
|
298
|
+
const positive = (v) => Math.max(0, Math.round(v ?? 0));
|
|
299
|
+
/** Normalise −0, which `Math.min(0, …)` and negation both produce. */
|
|
300
|
+
const noNegativeZero = (v) => v + 0;
|
|
301
|
+
function computeCurrentYearNonCapitalLoss(input) {
|
|
302
|
+
const issues = [];
|
|
303
|
+
const netIncome = Math.round(input.netIncome);
|
|
304
|
+
const optional = (v) => v === void 0 ? void 0 : positive(v);
|
|
305
|
+
const l002 = optional(input.rifeDeducted);
|
|
306
|
+
const l003 = input.capitalLossApplied === void 0 ? void 0 : allowableCapitalLossApplied(input.capitalLossApplied, input.inclusionRate);
|
|
307
|
+
const l005 = optional(input.taxableDividendsDeductible);
|
|
308
|
+
const l007 = optional(input.partVI1TaxDeductible);
|
|
309
|
+
const l011 = optional(input.prospectorsShares);
|
|
310
|
+
const l012 = optional(input.nonQualifiedSecurities);
|
|
311
|
+
const l017 = positive(input.section110_5Additions);
|
|
312
|
+
const l019 = optional(input.farmLoss);
|
|
313
|
+
const l013 = [
|
|
314
|
+
l002,
|
|
315
|
+
l003,
|
|
316
|
+
l005,
|
|
317
|
+
l007,
|
|
318
|
+
l011,
|
|
319
|
+
l012
|
|
320
|
+
].reduce((n, v) => n + (v ?? 0), 0);
|
|
321
|
+
const l015 = noNegativeZero(Math.min(0, netIncome - l013));
|
|
322
|
+
const l021 = noNegativeZero(Math.min(0, l015 - l017 + (l019 ?? 0)));
|
|
323
|
+
if (input.federalSection110_5Additions !== void 0 && l017 > positive(input.federalSection110_5Additions)) issues.push(`AT1 Schedule 21 line 017 (${l017}) exceeds federal T2 line 355 (${positive(input.federalSection110_5Additions)}). The specification allows this only to the extent it does not increase AT1 lines 070/071 — confirm before filing.`);
|
|
324
|
+
return {
|
|
325
|
+
lines: {
|
|
326
|
+
"001": netIncome,
|
|
327
|
+
...l002 !== void 0 ? { "002": l002 } : {},
|
|
328
|
+
...l003 !== void 0 ? { "003": l003 } : {},
|
|
329
|
+
...l005 !== void 0 ? { "005": l005 } : {},
|
|
330
|
+
...l007 !== void 0 ? { "007": l007 } : {},
|
|
331
|
+
...l011 !== void 0 ? { "011": l011 } : {},
|
|
332
|
+
...l012 !== void 0 ? { "012": l012 } : {},
|
|
333
|
+
"013": l013,
|
|
334
|
+
"015": l015,
|
|
335
|
+
"017": l017,
|
|
336
|
+
...l019 !== void 0 ? { "019": l019 } : {},
|
|
337
|
+
"021": l021
|
|
338
|
+
},
|
|
339
|
+
currentYearLoss: noNegativeZero(-l021),
|
|
340
|
+
issues
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
243
344
|
//#region src/t2/at1/filing/at1-schedule-line-items.ts
|
|
244
345
|
/**
|
|
245
346
|
* Schedules this module can put into a filing payload. Exported so callers and
|
|
@@ -360,7 +461,27 @@ function schedule17Values(result) {
|
|
|
360
461
|
values
|
|
361
462
|
};
|
|
362
463
|
}
|
|
363
|
-
/**
|
|
464
|
+
/**
|
|
465
|
+
* Field ids per category, from the verified field map.
|
|
466
|
+
*
|
|
467
|
+
* ── KNOWN GAP: 054 is filed short by line 053 ───────────────────────────────
|
|
468
|
+
*
|
|
469
|
+
* Shares are not like the other five. The page prints TWO grids: the shares
|
|
470
|
+
* grid leaves its column D unnumbered, and the shares gain is struck below it
|
|
471
|
+
* at 054 *after* line 053 has added federal Schedule 6 line 160 in. See
|
|
472
|
+
* `../forms/schedule18.ts`, where 054 is now modelled as that sum.
|
|
473
|
+
*
|
|
474
|
+
* This builder still files the raw `category.gain` at 054, and files nothing
|
|
475
|
+
* at 053 at all, because `AlbertaSchedule18Input` has no field for the federal
|
|
476
|
+
* amount — so a corporation with a Schedule 6 line 160 figure transmits a
|
|
477
|
+
* shares gain missing it, and `computeAlbertaSchedule18` carries the same
|
|
478
|
+
* shortfall into line 062 and on to the taxable gain at 076.
|
|
479
|
+
*
|
|
480
|
+
* Closing it needs an optional `federalScheduleSixSharesAddition` on the input
|
|
481
|
+
* (defaulting to 0, so existing callers are unaffected), added to the shares
|
|
482
|
+
* gain in the compute and emitted here as 053. Left as a separate change
|
|
483
|
+
* rather than smuggled into a form-definition fix.
|
|
484
|
+
*/
|
|
364
485
|
const S18_CATEGORY_FIELDS = {
|
|
365
486
|
shares: {
|
|
366
487
|
proceeds: "002",
|
|
@@ -634,7 +755,7 @@ function schedule4970Values(result) {
|
|
|
634
755
|
*/
|
|
635
756
|
function schedule12LossDeductions(alberta, federal = {}, inclusionRate = .5) {
|
|
636
757
|
const applied = (c) => Math.max(0, Math.round(c?.appliedCurrentYear ?? 0));
|
|
637
|
-
const allowable = (c) =>
|
|
758
|
+
const allowable = (c) => allowableCapitalLossApplied(c?.appliedCurrentYear ?? 0, inclusionRate);
|
|
638
759
|
return {
|
|
639
760
|
nonCapital: {
|
|
640
761
|
alberta: applied(alberta.nonCapital),
|
|
@@ -819,7 +940,14 @@ function schedule21Values$1(input) {
|
|
|
819
940
|
lineItemId: at1LineItemId("021", fieldId),
|
|
820
941
|
value
|
|
821
942
|
});
|
|
822
|
-
if (input.
|
|
943
|
+
if (input.currentYearLoss) {
|
|
944
|
+
const printOnly = new Set(SCHEDULE_21_PART_1_PRINT_ONLY);
|
|
945
|
+
for (const [line, value] of Object.entries(input.currentYearLoss.lines)) {
|
|
946
|
+
if (printOnly.has(line) || value === void 0) continue;
|
|
947
|
+
if (!(line === "001" || line === "017" || line === "021" || line === "003") && value === 0) continue;
|
|
948
|
+
put(line, value);
|
|
949
|
+
}
|
|
950
|
+
} else if (input.currentYearNonCapitalLoss !== void 0) put("021", -Math.abs(input.currentYearNonCapitalLoss) + 0);
|
|
823
951
|
for (const [inputKey, poolKey] of Object.entries(POOL_KEY)) {
|
|
824
952
|
const c = input[inputKey];
|
|
825
953
|
if (!c) continue;
|
|
@@ -1094,32 +1222,20 @@ function schedule20Values(input) {
|
|
|
1094
1222
|
put("046", input.maximum.gainsComponent);
|
|
1095
1223
|
put("048", input.maximum.maximumDeduction);
|
|
1096
1224
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
lineItemId: at1LineItemId("020", "092"),
|
|
1105
|
-
value: cf.charitable
|
|
1106
|
-
});
|
|
1107
|
-
if (cf.toCanadaOrProvince !== void 0) values.push({
|
|
1108
|
-
lineItemId: at1LineItemId("020", "094"),
|
|
1109
|
-
value: cf.toCanadaOrProvince
|
|
1110
|
-
});
|
|
1111
|
-
if (cf.culturalProperty !== void 0) values.push({
|
|
1112
|
-
lineItemId: at1LineItemId("020", "096"),
|
|
1113
|
-
value: cf.culturalProperty
|
|
1114
|
-
});
|
|
1115
|
-
if (cf.ecologicalLand !== void 0) values.push({
|
|
1116
|
-
lineItemId: at1LineItemId("020", "098"),
|
|
1117
|
-
value: cf.ecologicalLand
|
|
1118
|
-
});
|
|
1119
|
-
if (cf.medicine !== void 0) values.push({
|
|
1120
|
-
lineItemId: at1LineItemId("020", "100"),
|
|
1121
|
-
value: cf.medicine
|
|
1225
|
+
let occurrence = 0;
|
|
1226
|
+
for (const cf of input.gifts?.carryforward ?? []) {
|
|
1227
|
+
if (cf.yearOfOrigin === void 0) continue;
|
|
1228
|
+
occurrence += 1;
|
|
1229
|
+
const row = (field, value) => values.push({
|
|
1230
|
+
lineItemId: at1LineItemId("020", field, occurrence),
|
|
1231
|
+
value
|
|
1122
1232
|
});
|
|
1233
|
+
row("090", cf.yearOfOrigin);
|
|
1234
|
+
if (cf.charitable !== void 0) row("092", cf.charitable);
|
|
1235
|
+
if (cf.toCanadaOrProvince !== void 0) row("094", cf.toCanadaOrProvince);
|
|
1236
|
+
if (cf.culturalProperty !== void 0) row("096", cf.culturalProperty);
|
|
1237
|
+
if (cf.ecologicalLand !== void 0) row("098", cf.ecologicalLand);
|
|
1238
|
+
if (cf.medicine !== void 0) row("100", cf.medicine);
|
|
1123
1239
|
}
|
|
1124
1240
|
return {
|
|
1125
1241
|
scheduleId: "020",
|
|
@@ -3032,7 +3148,15 @@ function computeAlbertaReturn(input) {
|
|
|
3032
3148
|
federalTaxableIncome: input.federalTaxableIncome,
|
|
3033
3149
|
allocationFactor,
|
|
3034
3150
|
activeBusinessIncome: input.activeBusinessIncome,
|
|
3035
|
-
...input.businessLimit !== void 0 ? { businessLimit: input.businessLimit } : {}
|
|
3151
|
+
...input.businessLimit !== void 0 ? { businessLimit: input.businessLimit } : {},
|
|
3152
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
3153
|
+
...input.wasCcpcThroughoutYear !== void 0 ? { wasCcpcThroughoutYear: input.wasCcpcThroughoutYear } : {},
|
|
3154
|
+
...input.isAssociated !== void 0 ? { isAssociated: input.isAssociated } : {},
|
|
3155
|
+
...input.allocatedBusinessLimit !== void 0 ? { allocatedBusinessLimit: input.allocatedBusinessLimit } : {},
|
|
3156
|
+
...input.periodStart && input.periodEnd ? {
|
|
3157
|
+
periodStart: input.periodStart,
|
|
3158
|
+
periodEnd: input.periodEnd
|
|
3159
|
+
} : {}
|
|
3036
3160
|
}, rates);
|
|
3037
3161
|
const issues = [];
|
|
3038
3162
|
let iegGroup;
|
|
@@ -3088,14 +3212,25 @@ function computeAlbertaReturn(input) {
|
|
|
3088
3212
|
}
|
|
3089
3213
|
const schedulePayloads = [];
|
|
3090
3214
|
const sched = input.schedules;
|
|
3215
|
+
const schedule4 = sched?.foreignInvestmentTaxCredit;
|
|
3216
|
+
const otherDeductionsCredits = sched?.otherDeductionsCredits ? computeSchedule3({
|
|
3217
|
+
...sched.otherDeductionsCredits,
|
|
3218
|
+
mad: {
|
|
3219
|
+
taxPayableBeforeDeduction: albertaTax.basicTax,
|
|
3220
|
+
line070: albertaTax.smallBusinessDeduction,
|
|
3221
|
+
line071: input.manufacturingDeduction ?? 0,
|
|
3222
|
+
line072: schedule4?.totalAllowableCredit ?? 0,
|
|
3223
|
+
line074: input.politicalContributionsTaxCredit ?? 0
|
|
3224
|
+
}
|
|
3225
|
+
}) : void 0;
|
|
3091
3226
|
if (sched?.smallBusinessDeduction) {
|
|
3092
3227
|
schedulePayloads.push(schedule1Values$1(sched.smallBusinessDeduction));
|
|
3093
3228
|
issues.push(...sched.smallBusinessDeduction.result.issues);
|
|
3094
3229
|
}
|
|
3095
3230
|
if (sched?.allocation) schedulePayloads.push(schedule2Values$1(sched.allocation));
|
|
3096
|
-
if (
|
|
3097
|
-
schedulePayloads.push(schedule3Values(
|
|
3098
|
-
issues.push(...
|
|
3231
|
+
if (otherDeductionsCredits) {
|
|
3232
|
+
schedulePayloads.push(schedule3Values(otherDeductionsCredits));
|
|
3233
|
+
issues.push(...otherDeductionsCredits.issues);
|
|
3099
3234
|
}
|
|
3100
3235
|
if (sched?.foreignInvestmentTaxCredit) {
|
|
3101
3236
|
schedulePayloads.push(schedule4Values(sched.foreignInvestmentTaxCredit));
|
|
@@ -3161,9 +3296,12 @@ const at1Engine = {
|
|
|
3161
3296
|
return raw;
|
|
3162
3297
|
},
|
|
3163
3298
|
compute(input) {
|
|
3299
|
+
const iso = (d) => d.toISOString().slice(0, 10);
|
|
3164
3300
|
const result = computeAlbertaReturn({
|
|
3165
3301
|
...input,
|
|
3166
|
-
taxYear: input.taxYear ?? input.period.end.getFullYear()
|
|
3302
|
+
taxYear: input.taxYear ?? input.period.end.getFullYear(),
|
|
3303
|
+
periodStart: input.periodStart ?? iso(input.period.start),
|
|
3304
|
+
periodEnd: input.periodEnd ?? iso(input.period.end)
|
|
3167
3305
|
});
|
|
3168
3306
|
return {
|
|
3169
3307
|
jurisdiction: "CA-AB",
|
|
@@ -3709,6 +3847,23 @@ const AT1_EDI_LINE_ITEMS = [
|
|
|
3709
3847
|
fmt: "text"
|
|
3710
3848
|
}
|
|
3711
3849
|
];
|
|
3850
|
+
/**
|
|
3851
|
+
* Every Line-Item ID the EDI schedule can file.
|
|
3852
|
+
*
|
|
3853
|
+
* Derived from the table above rather than restated, so the two cannot
|
|
3854
|
+
* disagree. Exported because a consumer's INTERFACE needs it: the return
|
|
3855
|
+
* editor labels these boxes "Software Certification Code (line EDI001)", and
|
|
3856
|
+
* that number is a promise to the preparer that what they type lands there.
|
|
3857
|
+
*
|
|
3858
|
+
* Every other schedule's citations are checked against a `FormDefinition`.
|
|
3859
|
+
* The EDI schedule has none — it exists only in the Net File XML, and spec
|
|
3860
|
+
* §3.3.6.1 is not vendored into this package — so this list is what makes the
|
|
3861
|
+
* claim checkable at all. A wrong line number is worse than no line number:
|
|
3862
|
+
* it files a real figure against the wrong box and nothing looks broken.
|
|
3863
|
+
*/
|
|
3864
|
+
const AT1_EDI_LINES = AT1_EDI_LINE_ITEMS.map((li) => li.id);
|
|
3865
|
+
/** The FIELD half of each EDI id — `EDI001001` → `001`, which is what a preparer sees. */
|
|
3866
|
+
const AT1_EDI_FIELDS = AT1_EDI_LINES.map((id) => id.slice(3, 6));
|
|
3712
3867
|
//#endregion
|
|
3713
3868
|
//#region src/t2/at1/filing/at1-netfile-renderer.ts
|
|
3714
3869
|
/**
|
|
@@ -4442,6 +4597,23 @@ function albertaCurrentYearLoss(result) {
|
|
|
4442
4597
|
*
|
|
4443
4598
|
* Rates per CRA T4012 / ITR Schedule II. T2 CCA amounts are whole dollars (GIFI
|
|
4444
4599
|
* convention), so the CCA calculator works in integer dollars — NOT cents.
|
|
4600
|
+
*
|
|
4601
|
+
* @statutory-data
|
|
4602
|
+
* book: CCA_RATE_BOOK
|
|
4603
|
+
* covers: 2024
|
|
4604
|
+
* status: partially-sourced
|
|
4605
|
+
* verified: never
|
|
4606
|
+
* sources:
|
|
4607
|
+
* - research/sources/legislation/ITR-section-1100-cca-deductions.txt —
|
|
4608
|
+
* the Reg 1100(1) allowance rates these classes are drawn from.
|
|
4609
|
+
* - research/sources/legislation/ITR-schedule-III-class-13-leasehold.txt —
|
|
4610
|
+
* class 13, which is straight-line and deliberately NOT in this table.
|
|
4611
|
+
* gaps:
|
|
4612
|
+
* - The per-class rates are transcribed from ITR Schedule II, which is not
|
|
4613
|
+
* vendored; ITR s.1100 above is the deduction mechanism, not the class list.
|
|
4614
|
+
* - No class rate has been checked against a primary document on a recorded
|
|
4615
|
+
* date. Class rates move rarely, so staleness is a lower risk here than in
|
|
4616
|
+
* the year-tagged tax tables — but it is unmeasured, not measured-as-fine.
|
|
4445
4617
|
*/
|
|
4446
4618
|
const CCA_DECLINING_BALANCE_RATES_2024 = Object.freeze({
|
|
4447
4619
|
"1": .04,
|
|
@@ -5474,7 +5646,7 @@ const nn$22 = (v) => Math.max(0, v ?? 0);
|
|
|
5474
5646
|
* side is a real override and must not be swallowed by the default, so the
|
|
5475
5647
|
* check is on `undefined` rather than falsiness.
|
|
5476
5648
|
*/
|
|
5477
|
-
function
|
|
5649
|
+
function resolveCarryforwardRow(federal, alberta) {
|
|
5478
5650
|
const f = federal ?? {};
|
|
5479
5651
|
const a = alberta ?? {};
|
|
5480
5652
|
const pick = (k) => a[k] !== void 0 ? a[k] : f[k];
|
|
@@ -5492,6 +5664,30 @@ function resolveCarryforward(federal, alberta) {
|
|
|
5492
5664
|
}
|
|
5493
5665
|
return out;
|
|
5494
5666
|
}
|
|
5667
|
+
/**
|
|
5668
|
+
* Resolve every carryforward row, and drop the ones that say nothing.
|
|
5669
|
+
*
|
|
5670
|
+
* The row count is the LONGER of the two sides: an Alberta-only year (a
|
|
5671
|
+
* carryforward federal does not recognise) must survive, and so must a federal
|
|
5672
|
+
* year with no Alberta override.
|
|
5673
|
+
*
|
|
5674
|
+
* A row that resolves to `{}` is discarded rather than filed. `schedule20Values`
|
|
5675
|
+
* gates each occurrence on `yearOfOrigin` being present — 090 is mandatory
|
|
5676
|
+
* whenever any of 092-100 has a value — so an empty row would either transmit
|
|
5677
|
+
* nothing and still consume an occurrence number, shifting every row after it,
|
|
5678
|
+
* or transmit figures with no year against them. Neither is a return TRA can
|
|
5679
|
+
* read.
|
|
5680
|
+
*/
|
|
5681
|
+
function resolveCarryforward(federal, alberta) {
|
|
5682
|
+
const f = federal ?? [];
|
|
5683
|
+
const a = alberta ?? [];
|
|
5684
|
+
const rows = [];
|
|
5685
|
+
for (let i = 0; i < Math.max(f.length, a.length); i += 1) {
|
|
5686
|
+
const row = resolveCarryforwardRow(f[i], a[i]);
|
|
5687
|
+
if (Object.keys(row).length > 0) rows.push(row);
|
|
5688
|
+
}
|
|
5689
|
+
return rows;
|
|
5690
|
+
}
|
|
5495
5691
|
function computeSchedule20(input) {
|
|
5496
5692
|
const openingBalance = nn$22(input.openingBalance);
|
|
5497
5693
|
const expired = nn$22(input.expired);
|
|
@@ -6196,6 +6392,28 @@ function federalSchedulePayloads(r) {
|
|
|
6196
6392
|
*
|
|
6197
6393
|
* Never mutate a shipped year — add a new {@link RateBookEntry} for the new
|
|
6198
6394
|
* year (in the host book) so prior-year returns stay reproducible.
|
|
6395
|
+
*
|
|
6396
|
+
* @statutory-data
|
|
6397
|
+
* book: CORP_TAX_RATE_BOOK
|
|
6398
|
+
* covers: 2024
|
|
6399
|
+
* status: partially-sourced
|
|
6400
|
+
* verified: never
|
|
6401
|
+
* sources:
|
|
6402
|
+
* - research/sources/legislation/ITA-section-123.4-general-rate-reduction.txt —
|
|
6403
|
+
* GENERAL_RATE_REDUCTION (13%).
|
|
6404
|
+
* - research/sources/legislation/T4012-lines-638-639-general-tax-reduction.txt —
|
|
6405
|
+
* the general tax reduction as CRA states it on the return.
|
|
6406
|
+
* - research/sources/legislation/ITA-section-191.1-part-vi-1-tax.txt —
|
|
6407
|
+
* the PART_VI_1_* rates.
|
|
6408
|
+
* gaps:
|
|
6409
|
+
* - The rate stack itself (BASIC_RATE 38%, FEDERAL_ABATEMENT 10%, SBD_RATE 19%)
|
|
6410
|
+
* is transcribed from ITA s.123/124/125, which are NOT vendored.
|
|
6411
|
+
* - The thresholds (BUSINESS_LIMIT, TC_GRIND_*, AAII_*, SRED_*) and the
|
|
6412
|
+
* refundable fractions have no vendored source.
|
|
6413
|
+
* - No value in this file has been checked against a primary document on a
|
|
6414
|
+
* recorded date, which is what `verified: never` means. It is a REFERENCE
|
|
6415
|
+
* table: a host filing a real return supplies CRA-published figures through
|
|
6416
|
+
* CORP_TAX_RATE_BOOK.
|
|
6199
6417
|
*/
|
|
6200
6418
|
const CORP_TAX_2024 = Object.freeze({
|
|
6201
6419
|
BASIC_RATE: .38,
|
|
@@ -6478,6 +6696,21 @@ function blendProvinceRateTable(baseTable, changes, periodStart, periodEnd) {
|
|
|
6478
6696
|
* ⚠ REFERENCE VALUES for tax year 2024 — verify against each province's current
|
|
6479
6697
|
* schedule before filing. They are year-versioned in {@link PROVINCE_RATE_BOOK}
|
|
6480
6698
|
* so a host wires the authoritative figures without an engine change.
|
|
6699
|
+
*
|
|
6700
|
+
* @statutory-data
|
|
6701
|
+
* book: PROVINCE_RATE_BOOK
|
|
6702
|
+
* covers: 2024
|
|
6703
|
+
* status: reference-only
|
|
6704
|
+
* verified: never
|
|
6705
|
+
* sources: none
|
|
6706
|
+
* gaps:
|
|
6707
|
+
* - All 22 figures (11 provinces × general + small-business) are unsourced.
|
|
6708
|
+
* Each province legislates its own rate and publishes its own schedule;
|
|
6709
|
+
* none of those are vendored, and several provinces have changed rates
|
|
6710
|
+
* since 2024 — so these values are a plausible starting shape, not a
|
|
6711
|
+
* filing authority, and the header above says so.
|
|
6712
|
+
* - A host MUST supply its own PROVINCE_RATE_BOOK before filing a T2 with a
|
|
6713
|
+
* Schedule 5. This is the single largest provenance gap in the package.
|
|
6481
6714
|
*/
|
|
6482
6715
|
/** 2024 reference rates (general / small-business). Host overrides via the book. */
|
|
6483
6716
|
const PROVINCE_RATES_2024 = Object.freeze({
|
|
@@ -9255,6 +9488,21 @@ function formatConformanceReport(summary) {
|
|
|
9255
9488
|
* 2026-04-29 — wire that year via the rate book.
|
|
9256
9489
|
*
|
|
9257
9490
|
* Never mutate a shipped year — add a host rate-book entry for a new year.
|
|
9491
|
+
*
|
|
9492
|
+
* @statutory-data
|
|
9493
|
+
* book: QC_TAX_RATE_BOOK
|
|
9494
|
+
* covers: 2024
|
|
9495
|
+
* status: reference-only
|
|
9496
|
+
* verified: never
|
|
9497
|
+
* sources: none
|
|
9498
|
+
* gaps:
|
|
9499
|
+
* - GENERAL_RATE (11.5%), SMALL_BUSINESS_RATE (3.2%), BUSINESS_LIMIT and
|
|
9500
|
+
* SBD_HOURS_THRESHOLD (5,500) are transcribed from the Taxation Act (Québec)
|
|
9501
|
+
* and Revenu Québec guidance, neither of which is vendored. The CO-17 forms
|
|
9502
|
+
* under research/sources/rq-forms carry line captions, not rates.
|
|
9503
|
+
* - The doc comment above notes the SBD rate rises (small-business rate 2.2%)
|
|
9504
|
+
* for tax years beginning after 2026-04-29. That year is NOT in this book —
|
|
9505
|
+
* resolving 2026 returns the 2024 entry. A host must wire it.
|
|
9258
9506
|
*/
|
|
9259
9507
|
const QC_TAX_2024 = Object.freeze({
|
|
9260
9508
|
name: "Québec",
|
|
@@ -9982,4 +10230,4 @@ function computeMpDeduction(input, rates = MP_RATES_2024) {
|
|
|
9982
10230
|
};
|
|
9983
10231
|
}
|
|
9984
10232
|
//#endregion
|
|
9985
|
-
export { computeSchedule6 as $,
|
|
10233
|
+
export { computeSchedule6 as $, resolveAlbertaTaxRates as $i, resolveCcaRates as $n, computeIeg as $r, dividendsDeductibleS112 as $t, LRIP_INVESTMENT_CORPORATION_MULTIPLE as A, at1LineItemId as Ai, AT1_RESERVE_LINES as An, renderRsiHeader as Ar, computeExcessIfe as At, computeZetm as B, schedule21Values$1 as Bi, CLASS_14_1_MINIMUM_DEDUCTION as Bn, assertAt1MandatoryComplete as Br, assessEifel as Bt, runConformance as C, computeSchedule3 as Ci, AT1_DONATION_INCOME_RATE as Cn, RSI_NEGATIVE_PREFIX as Cr, EIFEL_STANDARD_RATIO_FROM as Ct, SCHEDULE_88_MAX_URLS as D, computeAt4970 as Di, SECTION_34_2_GROSS_UP as Dn, formatRsiDate as Dr, computeBorrowings as Dt, computeSchedule101 as E, computeAllocationFactor as Ei, AT1_DISPOSITION_CATEGORIES as En, formatRsiAmount as Er, ratioOfPermissibleExpenses as Et, LARGE_CORPORATION_THRESHOLD as F, schedule16Values as Fi, computeAlbertaSchedule13 as Fn, AT1_EDI_LINES as Fr, computeLossPortionFromIfe as Ft, computeCde as G, allowableCapitalLossApplied as Gi, computeClass13 as Gn, xmlEscape as Gr, PROVINCE_RATES_2024 as Gt, computeBusinessLimitAllocation as H, schedule2Values$1 as Hi, CLASS_14_1_TRANSITIONAL_RATE as Hn, assertCriticalFields as Hr, computeRifeUnderSubsection111_8 as Ht, computeTaxableCapital as I, schedule17Values as Ii, UnsupportedCcaClassError as In, At1CriticalFieldMissingError as Ir, computePartnershipIfe as It, computeCumulativeForeignResource as J, computeAlbertaSbd as Ji, computeClass141RecaptureReduction as Jn, allocateIegEvenly as Jr, resolveProvinceRates as Jt, computeCee as K, computeCurrentYearNonCapitalLoss as Ki, computeClass14 as Kn, at1Engine as Kr, PROVINCE_RATE_BOOK as Kt, computeSchedule31 as L, schedule18Values as Li, computeCcaClass as Ln, At1MandatoryFieldMissingError as Lr, computePartnershipIfeAddBack as Lt, computeSchedule54 as M, schedule12LossDeductions as Mi, computeAlbertaSchedule17 as Mn, renderAt1NetFile as Mr, computeInterestAndFinancingExpenses as Mt, computeGrip as N, schedule12Values as Ni, assistanceFrom as Nn, AT1_CRITICAL_MANDATORY_FIELDS as Nr, computeInterestAndFinancingRevenues as Nt, normalizeSchedule88 as O, AT1_SCHEDULES_WITHOUT_BUILDERS as Oi, computeAlbertaSchedule18 as On, formatRsiText as Or, computeCapitalizedIfe as Ot, computeSchedule43 as P, schedule13Values as Pi, computeAlbertaSchedule16 as Pn, AT1_EDI_FIELDS as Pr, computeLoans as Pt, computeSpecifiedForeignExploration as Q, AB_TAX_RATE_BOOK as Qi, isDecliningBalanceClass as Qn, IEG_2024 as Qr, computeTaxableIncome as Qt, ITC_RECAPTURE_PERIOD_YEARS as R, schedule1Values$1 as Ri, computeCcaSchedule as Rn, At1TaxPayableMismatchError as Rr, computeResourceIfe as Rt, formatConformanceReport as S, schedule4Values as Si, AT1_DONATION_GAIN_RATE as Sn, RSI_DELIMITER as Sr, EIFEL_STANDARD_RATIO as St, computeFederalT2 as T, SINGLE_JURISDICTION_ALBERTA_FACTOR as Ti, computeSchedule20 as Tn, RsiLineItemError as Tr, computeEifelLimitation as Tt, computeSchedule21 as U, schedule4970Values as Ui, MAX_LEASEHOLD_PERIODS as Un, at1TaxPayableDeductions as Ur, FOREIGN_TAX_CREDIT_GROSS_UP as Ut, allocateEvenly as V, schedule29Values as Vi, CLASS_14_1_RECAPTURE_REDUCTION_RATE as Vn, assertAt1TaxPayableReconciles as Vr, computeEifelCapacity as Vt, computeSchedule13 as W, SCHEDULE_21_PART_1_PRINT_ONLY as Wi, MIN_LEASEHOLD_PERIODS as Wn, at1YesNo as Wr, computeAdjustedTaxableIncome as Wt, computeForeignExploration as X, computeDayWeightedGeneralTax as Xi, CCA_DECLINING_BALANCE_RATES_2024 as Xn, computeIegAgreement as Xr, dayWeightedRate as Xt, computeDepletion as Y, AB_GENERAL_RATE_BANDS as Yi, leaseholdPeriods as Yn, allocateIegExpenditureLimit as Yr, blendProvinceRateTable as Yt, computeSchedule12ResourceDeductions as Z, AB_TAX_2024 as Zi, CCA_RATE_BOOK as Zn, computeIegGroupFigures as Zr, charitableDonationsDeduction as Zt, QC_TAX_2024 as _, computeFedeSuccessor as _i, computeRifeContinuity as _n, toRsiHeader as _r, terminalLossDeduction as _t, computeCanadianMPProfits as a, computeCcogpeRegular as ai, computeAggregateInvestmentIncome as an, albertaDispositionAdjustments as ar, computePart4Rdtoh as at, T2_LINE_META as b, schedule15Values as bi, computeLimitedPartnershipLossRow as bn, toRsiSchedule as br, partVI1DeductionMultiple as bt, computeSmallManufacturerTest as c, computeCdeSuccessor as ci, CORP_TAX_2024 as cn, albertaResourceDeductionDifference as cr, amortizationAddBack as ct, t2Engine as d, computeCfreRegular as di, federalSchedulePayloads as dn, reconcileAlbertaNetIncome as dr, computeSchedule1 as dt, earliestRateYear as ea, computeIegBaseAmount as ei, netCapitalLossApplied as en, albertaAbilDifference as er, computeProvincialAllocation as et, renderCo17DraftReturn as f, computeCfreSuccessor as fi, parseT2LineItemId as fn, LossCarrybackError as fr, deferredIncomeTaxProvisionAddBack as ft, computeQuebecTax as g, computeFedeRegular as gi, computeOtherLossByYearOfOrigin as gn, validateAt1Transmitter as gr, recaptureAddBack as gt, computeQuebecAllocationFactor as h, computeEdaSuccessor as hi, computeNonCapitalLossByYearOfOrigin as hn, assertAt1TransmitterValid as hr, mealsAndEntertainmentAddBack as ht, SMALL_MANUFACTURER_INCOME_THRESHOLD as i, resolveRates as ia, computeAlbertaSchedule15 as ii, computeAdjustedAggregateInvestmentIncome as in, albertaCurrentYearLoss as ir, REFUNDABLE_PART_I_RATE as it, LRIP_INVESTMENT_INCOME_FACTOR as j, schedule10Values as ji, AT1_RESERVE_TOTAL_LINES as jn, renderRsiLineItem as jr, computeExemptIfe as jt, computeSchedule55 as k, AT1_SCHEDULES_WITH_BUILDERS as ki, AT1_RESERVE_KINDS as kn, renderAt1Rsi as kr, computeClause95Amounts as kt, computeT2Settlement as l, computeCeeRegular as li, CORP_TAX_RATE_BOOK as ln, albertaTerminalLossDifference as lr, assertSchedule1Fileable as lt, computeQuebecReturn as m, computeEdaRegular as mi, T2_CERTIFICATION_FIXTURES as mn, At1TransmitterInvalidError as mr, incomeTaxProvisionAddBack as mt, MP_GROSS_REVENUE_THRESHOLD as n, hasExactRateYear as na, computeIegEligibleExpenditures as ni, computeCcpcActiveBusinessTax as nn, albertaCcaDifference as nr, computeSchedule4Losses as nt, computeMpDeduction as o, computeCcogpeSuccessor as oi, computeBusinessLimit as on, albertaRecaptureDifference as or, computeSchedule2 as ot, co17Engine as p, computeCmedb as pi, t2LineItemId as pn, computeLossCarryback as pr, findSchedule1LineDefects as pt, computeCogpe as q, computeAlbertaTax as qi, computeClass141AdditionalAllowance as qn, computeAlbertaReturn as qr, isSchedule5Province as qt, MP_RATES_2024 as r, latestRateYear as ra, iegT661SourceLine as ri, computePartITax as rn, albertaCcaScheduleAdjustments as rr, PART_IV_RATE as rt, computePart2MPProfits as s, computeCdeRegular as si, computeSBD as sn, albertaReserveDifference as sr, Schedule1NotFileableError as st, MP_EXCLUDED_ACTIVITIES as t, extendRateBook as ta, computeIegReductionFactor as ti, nonCapitalLossApplied as tn, albertaCapitalGainDifference as tr, computeSchedule5 as tt, renderT2DraftReturn as u, computeCeeSuccessor as ui, resolveCorpTaxRates as un, computeSchedule12 as ur, ccaDeduction as ut, QC_TAX_RATE_BOOK as v, computeSfedeCountryRegular as vi, computeLossSchedule as vn, toRsiJacketSchedules as vr, PART_VI_1_DEDUCTION_BANDS as vt, runConformanceSuite as w, schedule3Values as wi, computeDonationMaximum as wn, RSI_WORD_GAP as wr, EIFEL_TRANSITIONAL_RATIO as wt, foldT2Lines as x, computeSchedule4 as xi, computeLimitedPartnershipLosses as xn, RSI_COLUMN_GAP as xr, EIFEL_FIRST_YEAR_START as xt, resolveQuebecTaxRates as y, computeSfedeCountrySuccessor as yi, computeLossContinuity as yn, toRsiLineItems as yr, computePartVI1Deduction as yt, computeItcRecapture as z, schedule20Values as zi, computeSchedule8 as zn, albertaBalanceUnpaid as zr, EIFEL_EFFECTIVE_FROM as zt };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Statutory data — provenance and revision
|
|
2
|
+
|
|
3
|
+
Every tax figure this package ships has to say **where it came from** and **when it
|
|
4
|
+
was last checked**, in a form a machine can verify. This file is the convention;
|
|
5
|
+
`tests/statutory-data-provenance.test.ts` is the enforcement.
|
|
6
|
+
|
|
7
|
+
The convention is adapted from Equisoft's [`tax-ca`][tax-ca], which puts a
|
|
8
|
+
`Sources` / `Revised` header on each data file. That is a good idea and we took it.
|
|
9
|
+
We added enforcement because they have none — their own coverage is 15 of 34 files,
|
|
10
|
+
and the RESP grants, the CPI, and the pension increase factors all carry live
|
|
11
|
+
numbers with no header while the build stays green. A convention nothing checks is
|
|
12
|
+
documentation of intent, not provenance.
|
|
13
|
+
|
|
14
|
+
## The block
|
|
15
|
+
|
|
16
|
+
Every module that ships statutory data carries an `@statutory-data` block at the
|
|
17
|
+
end of its leading JSDoc:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
/**
|
|
21
|
+
* …the module's ordinary doc comment…
|
|
22
|
+
*
|
|
23
|
+
* @statutory-data
|
|
24
|
+
* book: AB_TAX_RATE_BOOK
|
|
25
|
+
* covers: 2024
|
|
26
|
+
* status: partially-sourced
|
|
27
|
+
* verified: 2026-09-09
|
|
28
|
+
* sources:
|
|
29
|
+
* - research/sources/tra-spec/AT1-Chapter3-2026.4-full.txt §3.2.3.1 line 068 —
|
|
30
|
+
* GENERAL_RATE 8%, as band F of the day-weighted table.
|
|
31
|
+
* gaps:
|
|
32
|
+
* - SMALL_BUSINESS_RATE (2%) appears in NO vendored source.
|
|
33
|
+
*/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Field | Meaning |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `book` | The exported `RateBook` this describes. Omit for effective-dated tables. |
|
|
39
|
+
| `covers` | The years (or effective window) the shipped data holds. **Checked against the real book**, not trusted. |
|
|
40
|
+
| `status` | `primary-sourced` · `partially-sourced` · `reference-only` |
|
|
41
|
+
| `verified` | ISO date the values were last checked against a cited source, or the literal `never`. |
|
|
42
|
+
| `sources` | Cited documents. A `research/sources/...` path **must exist on disk**. |
|
|
43
|
+
| `gaps` | What is *not* sourced. Required unless `status: primary-sourced`. |
|
|
44
|
+
|
|
45
|
+
`verified: never` is a legitimate, honest value. It says nobody has checked these
|
|
46
|
+
figures against a primary document — which is true of most of this package — and it
|
|
47
|
+
is loud precisely because it is allowed rather than faked. Writing today's date to
|
|
48
|
+
make a header look finished is the one thing this convention exists to prevent.
|
|
49
|
+
|
|
50
|
+
## What the test enforces
|
|
51
|
+
|
|
52
|
+
Four things, three of which `tax-ca`'s layout cannot check at all:
|
|
53
|
+
|
|
54
|
+
1. **A `RateBook` export requires a block.** Statutory data is identified
|
|
55
|
+
*structurally*, not from a list, so a new rate table without provenance fails.
|
|
56
|
+
You cannot forget.
|
|
57
|
+
2. **Cited vendored documents must exist.** `tax-ca` cites URLs — one of them
|
|
58
|
+
`taxtips.ca`, a secondary source; one a dead `cra-arc.gc.ca` link — and nothing
|
|
59
|
+
notices when they rot. Our primary documents are checked into
|
|
60
|
+
`research/sources/`, so a citation is a path that resolves or fails the build.
|
|
61
|
+
(Skipped when the research tree is absent, e.g. installed from npm.)
|
|
62
|
+
3. **`covers:` must match the book's actual years,** read from the imported book.
|
|
63
|
+
4. **The debt roster is pinned.** The set of `reference-only` and `verified: never`
|
|
64
|
+
files is asserted explicitly. It can shrink; it cannot grow without a
|
|
65
|
+
deliberate edit a reviewer sees.
|
|
66
|
+
|
|
67
|
+
It does **not** judge whether a rate is correct. It asserts that every rate
|
|
68
|
+
declares its authority and that the declaration is not stale in a way a machine can
|
|
69
|
+
see. Correctness is what the vendored documents and the engine suites are for.
|
|
70
|
+
|
|
71
|
+
## Current position
|
|
72
|
+
|
|
73
|
+
> **Every reference rate book in this package stops at 2024.**
|
|
74
|
+
|
|
75
|
+
That is asserted by the test, not merely written here. The rate book is a *seam*:
|
|
76
|
+
a host supplies authoritative figures per year through `CORP_TAX_RATE_BOOK` and its
|
|
77
|
+
siblings, and `apps/server` does exactly that. But a fork that installs this package
|
|
78
|
+
and files a 2025+ return against the shipped values will file wrong numbers, so the
|
|
79
|
+
fact is pinned where it cannot be missed.
|
|
80
|
+
|
|
81
|
+
| File | Status | Verified |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `t2/at1/rates/general-rate-bands.ts` | primary-sourced | 2026-09-09 |
|
|
84
|
+
| `gst-hst/rates.ts` | primary-sourced | 2026-07-04 |
|
|
85
|
+
| `t2/at1/rates/alberta-rates.ts` | partially-sourced | 2026-09-09 |
|
|
86
|
+
| `t2/rates/corporate-rates.ts` | partially-sourced | never |
|
|
87
|
+
| `t2/rates/cca-rates.ts` | partially-sourced | never |
|
|
88
|
+
| `t2/co17/rates/quebec-rates.ts` | **reference-only** | never |
|
|
89
|
+
| `t2/rates/province-rates.ts` | **reference-only** | never |
|
|
90
|
+
|
|
91
|
+
`province-rates.ts` is the largest gap: 22 figures (11 provinces × general +
|
|
92
|
+
small-business), none sourced, several stale since 2024. A host **must** supply its
|
|
93
|
+
own `PROVINCE_RATE_BOOK` before filing a T2 with a Schedule 5.
|
|
94
|
+
|
|
95
|
+
## Revising a year
|
|
96
|
+
|
|
97
|
+
1. Add a **new** `RateBookEntry` for the year. Never mutate a shipped year — a
|
|
98
|
+
reprint of a 2024 return must stay correct forever.
|
|
99
|
+
2. Update `covers:` to match. The test fails until it does.
|
|
100
|
+
3. Update `sources:` and set `verified:` to the date you actually checked. If you
|
|
101
|
+
did not check against a primary document, leave it `never` and record the gap.
|
|
102
|
+
4. Prefer **vendoring** the document into `research/sources/` over citing a URL.
|
|
103
|
+
A checked-in document is the difference between a citation that can be verified
|
|
104
|
+
in five years and one that 404s.
|
|
105
|
+
5. If the change moves a file between statuses, update the pinned rosters in
|
|
106
|
+
`tests/statutory-data-provenance.test.ts` in the same commit — that diff is the
|
|
107
|
+
reviewable record of provenance debt changing.
|
|
108
|
+
|
|
109
|
+
[tax-ca]: https://github.com/Equisoft/tax-ca
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/ca-tax",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
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",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
"format:baseline": "biome check --write src/ tests/"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"@classytic/primitives": ">=0.
|
|
72
|
+
"@classytic/primitives": ">=0.27.0",
|
|
73
73
|
"@classytic/tax-core": ">=0.3.0"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@biomejs/biome": "^2.4.10",
|
|
77
77
|
"@classytic/dev-tools": "^0.2.1",
|
|
78
|
-
"@classytic/primitives": "^0.
|
|
78
|
+
"@classytic/primitives": "^0.27.0",
|
|
79
79
|
"@classytic/tax-core": "^0.3.0",
|
|
80
80
|
"@types/node": "^25.6.0",
|
|
81
81
|
"tsdown": "^0.22.3",
|