Industry Extensions consists of three optional .NET libraries: Finance, HR, and Auction. They expose side-effect-free static calculations and stable Errors. They are not business modules integrated into the API host: there are no endpoints, DI registrations, permissions, features, persistence, tenant context, centralized configuration, or automated tests.
1. Three assemblies
| Assembly | Public capability | Dependency |
|---|---|---|
| Finance | Brackets, income tax, mortgage, private-loan detail, penalty | Domain |
| HR | Annual/marriage/maternity/paternity/bereavement/medical leave and policy schedule | Domain |
| Auction | Default/custom bracket commission and fixed-rate commission | Domain + Finance |
Finance is also referenced by LegalCalculators for TaxBracket and the bracket engine. It is therefore not consumed only through an explicitly selected industry profile; it is already a compile-time transitive dependency of LegalCalculators.
2. Runtime boundary
All three projects are in the solution, but the API host does not reference them. A governance marker is hosted in BitzOrcas.Platform.Application, so the Registry can report an IndustryExtensions module identity even when the calculator assemblies are not loaded. Operations must distinguish catalog presence from callable capability.
3. Public calculators
| Calculator | Current scenarios |
|---|---|
BracketTaxCalculator | Quick formula and progressive brackets |
IncomeTaxCalculator | Comprehensive income, labor-service withholding, annual bonus |
MortgageCalculator | Equal-installment/equal-principal amounts, interest, schedules |
LoanDetailCalculator | Four-times-LPR checks, period/segment interest, allocation, compound ceiling |
PenaltyCalculator | Agreed/daily/LPR reference and a 130% adjustment suggestion |
LeaveCalculator | Annual/prorated/marriage/maternity/paternity/bereavement/medical leave |
AuctionCommissionCalculator | Default/custom brackets and a fixed rate |
These are type-level APIs, not CQRS use cases. Earlier instructions to inspect request contracts, handlers, post-commit events, cache, and audit did not match this implementation.
4. Minimal Finance use
// The caller first proves tax year, residence, jurisdiction, and policy version.var taxableIncome = annualIncome - basicDeduction - socialInsuranceDeduction - specialAdditionalDeduction;
// The current decimal-only API stores none of that evidence and returns no bracket lines.var tax = IncomeTaxCalculator.CalcIndividualIncomeTax(taxableIncome);
// Error has a stable code; success is rounded to two places AwayFromZero.if (tax.IsFailure) return tax.Error;return tax.Value;The seven comprehensive-income brackets match the current official table, but the API has no TaxYear. The separate-tax method for an annual bonus relies on a policy currently extended through 2027-12-31; the hard-coded method will not expire automatically.
5. Minimal HR use
// A preset is only a reference snapshot; production should load an approved version.var policy = LeavePolicies.Guangdong;
// The current engine always adds 15 days for difficult labor.var days = LeaveCalculator.CalcMaternityDays( schedule: policy, isDifficultLabor: true, multipleBirthCount: 1);
// Persist policy version and source with the result, never the final number alone.if (days.IsFailure) return days.Error;return days.Value;Official local rules can use a different difficult-labor increment, which the current schedule cannot express. Preset EffectiveFrom also defaults to the process date rather than the legal effective date.
6. Minimal Auction use
// The owner first establishes contract terms, auction type, and paying party.var result = AuctionCommissionCalculator.CalcCommissionByRate( hammerPrice: 2_500_000m, commissionRate: 0.03m);
// The current API rejects every rate above 5% without distinguishing legal scenarios.if (result.IsFailure) return result.Error;
// The decimal does not say seller/buyer, tax treatment, contract, or bracket evidence.return result.Value;Article 56 of the Auction Law first permits an agreed commission. Its no-agreement rule and Article 57’s specific category use a 5% ceiling. A single universal cap is broader than that legal structure.
7. Official-authority check
- The annual-bonus tax announcement says the separate method runs through 2027-12-31;
- the Supreme People’s Court private-lending interpretation uses four times the one-year LPR at contract formation and includes transitional rules;
- the Civil Code contract interpretation treats 30% as a general indicator and requires multi-factor judicial assessment;
- the annual-leave implementation measures use remaining/elapsed calendar days, not months divided by twelve;
- the special rules on female employee protection establish national maternity, difficult-labor, and multiple-birth baselines;
- the Auction Law distinguishes agreed, unagreed, and specific-property commission cases.
These links demonstrate the need for versioned policy. Runtime code must not scrape a webpage and activate text without review.
8. Deterministic is not reproducible
Most methods are pure for identical numeric inputs. The same business fact is not reproducible because inputs omit PolicyId/Version, TaxYear, ContractDate, Jurisdiction, DayCountConvention, and RoundingPolicy. LeavePolicies also takes DateTime.Today, producing different value objects on different startup dates.
A commercial result needs normalized facts, rule version and hash, source reference, effective interval, calculation time, rounding contract, line-by-line breakdown, and actor/approval evidence.
9. Numeric and date boundaries
Amounts use decimal and most final results round two places AwayFromZero. BracketTaxCalculator itself does not round, while schedules round each period. Total-interest APIs and schedule sums can therefore differ by cents.
InterestSegment documentation calls both endpoints inclusive; code subtracts dates and excludes EndDate. Segments are not validated for order, overlap, or gaps, and reverse or same-day segments are silently skipped.
10. Validation gaps
The bracket engine does not validate ascending limits, final coverage, rates, quick deductions, or duplicates. LeavePolicy validates strict ordering and nonnegative top-level leave days, but not nonnegative tier years/days. Mortgage has no upper bound for years * 12, decimal exponentiation, or schedule size.
Error descriptions are hard-coded Chinese. Several helpers return bare decimal rather than Result, including a ratio that accepts negative values.
11. Chapter map
- Packaging, governance, and runtime covers optional assemblies, dependency direction, registry presence, integration wrappers, and security;
- Finance calculators covers tax, mortgage, lending, penalty, brackets, numeric, and date contracts;
- HR leave policies covers presets, statutory baselines, prorating, dates, and policy change;
- Auction, testing, operations, and GA covers commission authority, validation, golden cases, shadow calculation, audit, and gates.
12. Commercial-GA red lines
- Bind every result to Jurisdiction, PolicyId/Version, EffectiveFrom/To, and SourceHash;
- select legal and regional rules from an approved policy store, not implicit static defaults;
- return a breakdown, input snapshot, rounding rule, and date convention;
- correct the broad Auction 5% cap, mechanical Penalty 130% suggestion, and month-based leave proration;
- resolve InterestSegment inclusivity and validate order, overlap, and gaps;
- add strict input and capacity limits for brackets, mortgage, and leave policy;
- put authorization, tenant, privacy, audit, idempotency, and use restrictions in an application wrapper;
- operate an ingest-review-approve-publish-supersede regulatory workflow;
- require golden, property, boundary, independent-reference, and expert-signoff evidence;
- eliminate the current zero-test condition before any production consumption.
13. Source navigation
# Public calculators, records, and error catalogs.rg -n "^public (static |sealed )?(class|record)|public static (Result|decimal|int)" \ src/Platform/IndustryExtensions -g '*.cs'
# Prove host absence and the Finance consumers.rg -n "IndustryExtensions" src/Hosts src/Platform -g '*.csproj' -g '*.cs'
# Policy evidence, endpoints, and tests should currently have no complete implementation.rg -n "PolicyVersion|SourceHash|EffectiveTo|GenerateEndpoint|\[Fact\]" \ src/Platform/IndustryExtensions tests -g '*.cs'