You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[C] #514 slice 9: Farm contract, with tenant identity staying in Platform #851
Track C is unscheduled. These slices move production code, and the 2026-08 design's own status
line still governs: "proposed architecture; no production refactor is authorized by this
document." Filed so the analysis is tracked work rather than a comment, not as a commitment to
run it.
The 2026-09-14 re-plan
recommends gating Track C on evidence from Tracks A and B: if the #842 ratchet fires repeatedly in
real pull requests, these become worth their cost; if it stays quiet, they do not. Track C is
57–95 focused engineering days and produces no user-visible change.
Read the re-plan before picking any of these up. Several assumptions in the 2026-08 plan are
corrected there.
Farm settings, logo, banner, currency, units and timezone behind a contract, while tenant identity
stays in Platform.
The one rule that must not bend
Tenant identity resolution stays claim-only in Platform. TenantResolutionMiddleware keeps populating TenantContext directly from the JWT account_id claim, before any module contract runs. It must not route through a Farm contract to establish tenant identity — that would either execute
tenant-filtered reads before TenantContext exists, or require bypassing the filters mid-request.
Either weakens the fail-closed tenant boundary (#530, #562, #673).
Farm contracts are called only afterTenantContext is resolved, to read settings. Never to
resolve identity.
Scope
IFarmModule for settings, logo and banner; a small context reader returning an immutable
currency/unit/timezone snapshot.
The lock-aware currency port the Finance pilot introduced becomes Farm's own.
Account and logo endpoints and the farm clock call the contract.
Carries a known cross-module edge
UpdateFarmSettingsHandler.cs:12 injects IEggUnitConversionRepository and :149 calls DiscountCeiling.TryParsePercent (#727) — a real Farm → Commerce read the 2026-08 matrix marks —.
This slice decides whether it becomes a declared contract call or stays a declared edge. It is
legitimate either way; it must stop being accidental.
Done when
Settings, logo and banner HTTP contracts unchanged; SPA tests pass unedited.
Important
Track C is unscheduled. These slices move production code, and the 2026-08 design's own status
line still governs: "proposed architecture; no production refactor is authorized by this
document." Filed so the analysis is tracked work rather than a comment, not as a commitment to
run it.
The 2026-09-14 re-plan
recommends gating Track C on evidence from Tracks A and B: if the #842 ratchet fires repeatedly in
real pull requests, these become worth their cost; if it stays quiet, they do not. Track C is
57–95 focused engineering days and produces no user-visible change.
Read the re-plan before picking any of these up. Several assumptions in the 2026-08 plan are
corrected there.
Farm settings, logo, banner, currency, units and timezone behind a contract, while tenant identity
stays in Platform.
The one rule that must not bend
Tenant identity resolution stays claim-only in Platform.
TenantResolutionMiddlewarekeeps populatingTenantContextdirectly from the JWTaccount_idclaim, before any module contract runs. It mustnot route through a Farm contract to establish tenant identity — that would either execute
tenant-filtered reads before
TenantContextexists, or require bypassing the filters mid-request.Either weakens the fail-closed tenant boundary (#530, #562, #673).
Farm contracts are called only after
TenantContextis resolved, to read settings. Never toresolve identity.
Scope
IFarmModulefor settings, logo and banner; a small context reader returning an immutablecurrency/unit/timezone snapshot.
Carries a known cross-module edge
UpdateFarmSettingsHandler.cs:12injectsIEggUnitConversionRepositoryand:149callsDiscountCeiling.TryParsePercent(#727) — a real Farm → Commerce read the 2026-08 matrix marks—.This slice decides whether it becomes a declared contract call or stays a declared edge. It is
legitimate either way; it must stop being accidental.
Done when
Settings, logo and banner HTTP contracts unchanged; SPA tests pass unedited.
Invalid timezone still fails closed (Deploy: farm timezone provisioning — seeded UTC + undocumented tzdata/ICU image dependency #264, provision-account: optional --timezone at creation (assumed by #537, never built) #603).
The currency-bound-row probe still compiles across every module it spans.
Tenant query-filter and stamping tests pass unedited; EF model digest identical.
Change map in the PR (owner, 2026-10-01). The PR carries a before/after diagram of who calls whom, in the shape of the refactor(finance): put Finance behind an IFinanceModule contract #1010 and refactor(insights): read reports, exports and audit provenance through an Insights facade #1012 change maps: the adapters and module types before and after, any ledger edges added or removed, and the end state of any file another open slice also changes. Put it in the PR body or a PR comment as a fenced text block.
Explicitly not in this slice
TenantResolutionMiddleware,TenantContext, the stamp interceptor and middleware order — allPlatform, all unchanged.