Skip to content

Configurable Worker sales allocation scope by flock assignment #612

Description

@mforce

Context

Discovered during #388 / PR #611 review. #388 scopes a restricted Worker's reads to assigned flocks, but Workers are also intentionally allowed to create and confirm sales (AuthPolicies.SalesFlow, #73 principle). Sale confirmation allocates egg lots FIFO without asking the operator to choose a flock.

PR #611 briefly applied flock scope to EggLotRepository.GetAvailableFifoLockedAsync, which would make a restricted Worker see false EggLot.InsufficientStock whenever assigned-flock stock is insufficient even though the farm has enough stock elsewhere. #388 will preserve current main behavior (farm-wide FIFO allocation) and defer configurable sales allocation to this issue.

Owner decisions (2026-08-27)

  1. Add a persisted farm setting controlling plain-Worker sale allocation:
    • AssignedFlocksOnly — default.
    • AllFarmFlocks — opt-in.
  2. Owner and Manager may change it in Farm Settings.
  3. The setting applies only to plain Workers. Owner, Manager, and Sales-role users always retain farm-wide FIFO allocation.
  4. A Worker whose assigned-flock stock cannot fulfill the order must receive a specific warning when farm-wide stock could fulfill it: explain that an Owner/Manager can allow selling from other flocks.
  5. Trigger that warning for any assigned-stock shortfall, not only zero assigned stock.
  6. If farm-wide stock is also insufficient, keep the normal insufficient-stock error.

Required behavior

Allocation decision

At confirm time, derive effective allocation scope from both the actor and the farm setting:

Actor Farm setting FIFO candidate lots
Owner / Manager / Sales either all account/farm lots
Plain Worker with zero assignment rows or a farm-wide assignment row either all account/farm lots (existing unrestricted semantics)
Restricted plain Worker AssignedFlocksOnly assigned flocks only
Restricted plain Worker AllFarmFlocks all account/farm lots

Do not infer role from the setting or from assignment presence. Use the same effective-role semantics as AuthPolicies/CurrentUserContext.

Insufficient assigned stock discriminator

For AssignedFlocksOnly, if scoped FIFO cannot fulfill a line:

  1. Determine whether the same line/order could be fulfilled by farm-wide eligible stock under the same date, grade, quantity-available, and withdrawal rules.
  2. If yes, return a distinct stable error code (name during design) whose user-facing message says the Worker is limited to assigned-flock stock and an Owner/Manager can enable cross-flock selling in Farm Settings.
  3. If no, return existing EggLot.InsufficientStock.
  4. The probe must not allocate, mutate, or change lock ordering. Design the concurrency/lock semantics explicitly; do not issue an unlocked preflight that can make a promise the locked allocation immediately contradicts.

Settings surface

  • Add the setting to Account farm settings and bump Version when changed.
  • Add one forward migration; InitialCreate remains frozen (feat(eggs): make cracked and dirty eggs sellable stock via condition grades (#396) #407).
  • Update Account/Farm Settings GET + PUT contracts, validators/handlers, API DTOs, generated client types, and SPA Settings UI.
  • UI copy must explain both choices and identify that only plain Workers are affected.
  • Update specs/product/GLOSSARY.md, SPA Help/in-app glossary, and all supported locales (en/es/tl).

Acceptance criteria

  • New farms/default reference account use AssignedFlocksOnly.
  • Owner and Manager can switch the setting; other roles cannot.
  • Plain restricted Worker + default setting allocates only assigned-flock lots.
  • Same Worker + AllFarmFlocks allocates across all farm flocks.
  • Owner, Manager, and Sales-role confirmation remains farm-wide under both setting values.
  • Zero-assignment and farm-wide-assignment Workers remain farm-wide under both values.
  • Assigned stock insufficient + farm-wide sufficient returns the distinct admin-option warning; no partial allocation persists.
  • Farm-wide insufficient returns existing EggLot.InsufficientStock.
  • Withdrawal/future-production eligibility and canonical FIFO lock order remain unchanged.
  • Parallel confirmations preserve pessimistic-lock correctness and never over-allocate.
  • Migration + docs/schema/ regenerated and checked.
  • Settings SPA, GLOSSARY, Help, en/es/tl, and SPA UI verification track: Playwright E2E smoke + canary-under-load over the #243 sim fixture #277 simulation E2E are updated.
  • Mutation checks independently prove: role bypass, both setting branches, zero/farm-wide assignment behavior, warning discriminator, and farm-wide-insufficient fallback.

Non-goals

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions