Skip to content

refactor(arch): give adapters Farm's farm-code rule and image-size errors through its contract - #1121

Merged
mforce merged 1 commit into
mainfrom
refactor/1116-farm-code-image-errors
Oct 6, 2026
Merged

mforce merged 1 commit into
mainfrom
refactor/1116-farm-code-image-errors

Conversation

@mforce

@mforce mforce commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Part of #1116 (cleanup PR C5, the P3 design change). It does not close the issue.

Adapters stop naming Farm internals for two rules they need:

  • Farm code. FarmCode (Domain/Modules/Farm/Contracts/) now holds the one farm-code rule: trimming, the pattern, the reserved set, the Account.SlugInvalid code and text, and the 32-character limit. Account.TryValidateSlug and Account.SlugMaxLength delegate to it. The sign-in validator and the provision-account and rename-account verbs call FarmCode.
  • Image size. FarmImageErrors.LogoTooLarge and BannerTooLarge forward to ImageSanitizer.TooLarge. The logo and banner endpoints call those, and ImageAssetKind stays inside the sanitizer.

CW1004 census (tools/architecture/cw1004-census.sh), on main without C4: 46 → 40, exactly the 6 P3 rows. With C4 (#1120) merged as well, it is 8 → 2, leaving the two P4 rows. Proofs and the design notes follow in an edit.

Design notes (Astra's review, §4 of the design comparison)

  • One farm-code implementation. The trimming, pattern, reserved set, Account.SlugInvalid code and text, and the 32-character limit moved verbatim from Account into FarmCode. Diffed against main's Account.TryValidateSlug, the body is identical apart from member names (SlugPattern → Pattern, ReservedSlugs → Reserved), and the reserved set and regex literals are byte-identical.
  • Compatibility delegates kept where production code calls them. Account.TryValidateSlug and Account.SlugMaxLength are now one-line delegates, used by Account itself, AccountProvisioner, AccountRenameService and the EF mapping. Account.ReservedSlugs was used only by tests, so it was removed rather than delegated; AccountSlugTests reads FarmCode.Reserved.
  • Two asset-specific factories, ImageAssetKind not exposed. FarmImageErrors.LogoTooLarge and BannerTooLarge forward to ImageSanitizer.TooLarge with the same arguments the endpoints passed before. That keeps the configured byte limit, the FarmLogo.TooLarge / FarmBanner.TooLarge codes, the "must be N KB or smaller" message and the 413 mapping (MapFailure) in one place. The sanitizer and its asset kinds stay outside the contract.

Policy review: why these belong in Farm's public API

  • FarmCode. The farm code is a public identifier: people type it at sign-in, and the provision-account and rename-account verbs take it as an argument. Adapters need its length limit and validation. Before this PR they could get them only by naming the Account aggregate, which adapters may not reach. Publishing the rule, and not the aggregate, gives them exactly that. It names no entity.
  • FarmImageErrors. The upload endpoints refuse an over-size body while streaming, before the bytes reach the sanitizer. They need the same refusal the sanitizer would raise. Two error factories expose that and nothing else; they return Error, a kernel type.

Proofs (head 968e1a1e)

Check Result
Census, on main 46 → 40. Exactly the 6 P3 rows: ProvisionAccountCliCommand, RenameAccountCliCommand and LoginRequestValidator → Account; FarmBannerEndpoints → ImageSanitizer and ImageAssetKind; FarmLogoEndpoints → ImageSanitizer
Census, on a merge of this PR and #1120 (C4) 2: only the two P4 rows in AccountProvisioner. The merge has one conflict, a using line in Account.cs (keep this PR's side, without System.Text.RegularExpressions); it builds with 0 warnings and 0 errors
Tenant-bypass re-pin none. TenantBypassRealTreeTests 4/4; no registry member changed (AccountProvisioner and AccountRenameService still call Account.TryValidateSlug)
Purity guard covers the new contract types adding Entity<Guid>? PurityProbe to FarmCode fails ModuleContractRealAssemblyTests; restored
Guard classes (one at a time, all green) TenantBypassRealTreeTests 4, AdapterReachRealTreeTests 2, PeerContractRealTreeTests 1, ModuleContractRealAssemblyTests 1, ContractDerivationTests 1, ModuleLedgerRealTreeTests 2, CouplingMatrixRealTreeTests 3, ModuleEdgeAnalyzerTests 14, NamespaceFolderAgreementTests 10, AdapterTierRealTreeTests 3, AccessOwnershipClaimTests 2, InsightsReadOnlyTests 25, SeamSurfaceRealAssemblyTests 2, TableOwnerRealModelTests 2, CompatibilityExceptionRealTreeTests 2
Unit tests AccountSlugTests 30, ImageSanitizerTests 81
Integration (real Postgres) FarmLogoTests 38, FarmBannerTests 15, FarmLogoRequestBodyCapTests 4: 413 with FarmLogo.TooLarge / FarmBanner.TooLarge on both the streaming cap and the handler path. LoginRequestValidatorTests 7, AccountLifecycleCommandTests 24: Account.SlugInvalid and "'bad code' is not a valid farm code" from rename-account. ProvisionAccountCommandTests 11
Build dotnet build Cluckwork.slnx with repo defaults: 0 warnings, 0 errors

Deslop removed one test-only delegate (Account.ReservedSlugs). A historical plan, docs/plans/732-rename-account-verb/02-implementation-runbook.md, still names Account.TryValidateSlug and is left as written.

…rors through its contract

Part of #1116 (the P3 design change). The sign-in validator and the
provision-account and rename-account verbs named the Account aggregate for
the slug rule, and the logo and banner endpoints named ImageSanitizer and its
asset kinds for the over-size refusal.

- FarmCode, in Farm's Domain contract, now holds the one farm-code rule:
  trimming, the pattern, the reserved set, the error code and text, and the
  32-character limit. Account.TryValidateSlug and Account.SlugMaxLength
  delegate to it.
- FarmImageErrors.LogoTooLarge and BannerTooLarge forward to
  ImageSanitizer.TooLarge, so codes, messages, the configured limit and the
  413 mapping are unchanged and ImageAssetKind stays internal to the sanitizer.

The CW1004 census falls by the 6 P3 rows.
@mforce
mforce force-pushed the refactor/1116-farm-code-image-errors branch from 968e1a1 to 08baa93 Compare October 6, 2026 19:30
@mforce
mforce merged commit cce672b into main Oct 6, 2026
19 checks passed
@mforce
mforce deleted the refactor/1116-farm-code-image-errors branch October 6, 2026 19:39
@mforce mforce mentioned this pull request Oct 6, 2026
16 tasks done
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.

1 participant