AGRONEAT / ENGINEERING & OPERATIONS / 12 OCTOBER 2026

From farm activity
to trusted records.

A detailed atlas of AgroNeat’s implemented workflows and service interactions. 29 focused diagrams cover access, offline entry, operations, review, money, AI, subscriptions and exports.

Evidence: local AgroNeat-BACKEND and AgroNeat-WEB source. This is a code-derived description, not proof of deployment. Mobile internals and the separate backend-review checkout are outside this atlas. Short arrow labels map to detailed message rows below each sequence.

Choose your reading path

Start with the nine flowcharts for decisions and business rules. Use the sequence diagrams to trace message order, transaction boundaries and integration handoffs. Every arrow now has a step number matching its detail row.

A green result identifies the focal outcome, not every successful step. Dashed filled arrows are returns; dashed open arrows publish events. A combined ALT frame contains alternative outcomes. Notes identify omitted branches and grouped components. Each source includes method entry lines and a content fingerprint. Source links open the GitHub implementation repositories; the diagrams and explanations remain readable when the HTML is shared alone.

Back to contents ↑
01 / FLOWCHART / DOC-WIDE

Account to working farm

Sign in, create or select a farm, then begin recording against an explicit farm scope.

Account to working farmSign in, create or select a farm, then begin recording against an explicit farm scope.YESNOCONTINUESign in or registerEmail verification / passwordLoad account and membershipsAccount-scoped requestNeed a new farm?Create farm within plan limitFirst owned farm starts trialSave farm and OWNER membershipDefault timezone: Africa/LagosSelect active farmX-Farm-Id for scoped requestsOpen farm workspaceRecord daily activityChoose existing farmContinue at Select active farmOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • Registration and sign-in are separate account operations. Password sign-in requires verified email; OTP sign-in consumes a valid code.
  • Farm creation checks FARMS_MAX after starting a first-farm trial. Farm and owner membership are created transactionally with audit events.
  • The existing-farm branch visibly rejoins Select active farm, bypassing creation and membership insertion.

Implementation sources

Back to contents ↑
02 / FLOWCHART / DOC-WIDE

Farm request authorization

The common gate decides scope, permissions, feature access, and whether records may be changed.

Farm request authorizationThe common gate decides scope, permissions, feature access, and whether records may be changed.YESYESNONOAuthenticated farm requestAccount routes use separate scopeResolve farm membershipHeader or sole membershipFarm accesspermitted?Resolve owner planFarmPlan and feature entitlementPlan allows access?Set farm context and authoritiesClear context after completionRun domain operationRow-level checks still applyRefuse requestScope / role / farm access failureReturn plan restrictionMissing feature or frozen farmOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • When several memberships exist, the request must supply X-Farm-Id. An explicit farm header requires membership in that farm.
  • Auth, profile, personal inbox, account billing, incoming transfers and platform operations bypass this farm resolution path.
  • Feature checks precede frozen-record write checks. Role rules also restrict team management, expense review, portfolio views and exports.

Implementation sources

Back to contents ↑
03 / FLOWCHART / DOC-WIDE

Daily entry with poor connectivity

A local acknowledgement means queued, while a server acknowledgement means saved.

Daily entry with poor connectivityA local acknowledgement means queued, while a server acknowledgement means saved.YESNOOpen record formFarm date and active groupPreserve draft and build payloadUUIDv7 record ID; exact unitsSend requestBearer token + farm headerServer reached?Apply server resultValidation stays visible in formRefresh affected viewsSaved state or actionable errorKeep farm-bound queue itemReplay through offline syncOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • The web API client queues eligible non-GET mutations when fetch fails; auth calls are excluded. A queue acknowledgement must not be presented as a committed server record.
  • Authenticated JSON reads may use a farm-scoped cached response after a network failure, with stale-read feedback.
  • Money is a decimal naira string over HTTP and integer kobo in storage. Weight is a decimal kg string over HTTP and integer grams in storage. Egg quantities are individual eggs.

Implementation sources

Back to contents ↑
04 / SEQUENCE / DOC-WIDE

Verified sign-in

Representative password sign-in; OTP sign-in uses the same token-issuance path after consuming the code.

Verified sign-inRepresentative password sign-in; OTP sign-in uses the same token-issuance path after consuming the code.01 CREDENTIALS02 SIGN IN03 LOAD USER04 USER05 LOCK USER06 ACCOUNT07 STORE HASH08 TOKENS09 WORKSPACEFarmerWeb clientAuthServicePostgreSQLSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Web client · callFarmer submits email and password.
02Web client → AuthService · callCall password sign-in with normalized email.
03AuthService → PostgreSQL · callRead active user and stored password hash.
04PostgreSQL → AuthService · returnReturn account and password state.
05AuthService → PostgreSQL · callAfter password, email verification and active-state checks, lock the account for token issuance.
06PostgreSQL → AuthService · returnReturn account session version.
07AuthService → PostgreSQL · callPersist SHA-256 hash of new refresh token; publish UserAuthenticated event.
08AuthService → Web client · successReturn access token, refresh token and user ID.
09Web client → Farmer · returnLoad profile and memberships, then route to farm workspace or onboarding.

Rules and alternative paths

  • Invalid credentials, unverified password accounts and suspended accounts stop this success path. OTP consumes a valid unexpired code and can mark email verified.
  • The event is emitted inside the authentication transaction; downstream event delivery is intentionally omitted. Raw refresh tokens are not stored in PostgreSQL.

Implementation sources

Back to contents ↑
05 / SEQUENCE / DOC-WIDE

Session refresh and rotation

Concurrent web requests share one refresh promise because each refresh token is spent once.

Session refresh and rotationConcurrent web requests share one refresh promise because each refresh token is spent once.01 SESSION02 REFRESH03 LOCK USER04 ACCOUNT05 LOCK TOKEN06 VALID TOKEN07 ROTATE08 NEW TOKENS09 RESUMEWeb requestsAPI clientAuthServicePostgreSQLSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Web requests → API client · callExpired session requests converge on refreshAccessToken.
02API client → AuthService · callSend the current refresh token; refresh is never queued offline.
03AuthService → PostgreSQL · callValidate JWT type and lock account; require active state and matching session version.
04PostgreSQL → AuthService · returnReturn current session version.
05AuthService → PostgreSQL · callFind refresh token by hash and lock it; require active state.
06PostgreSQL → AuthService · returnReturn valid stored refresh token.
07AuthService → PostgreSQL · callRevoke old token and store hash of newly issued refresh token in one transaction.
08AuthService → API client · successReturn replacement access and refresh tokens.
09API client → Web requests · returnPending callers share the result and resume their requests.

Rules and alternative paths

  • A server refusal can end the session. A failed network refresh preserves credentials for later and does not imply revocation.
  • No global exactly-once guarantee is inferred from UUID usage; token rotation is enforced explicitly by row locks and active-token checks.

Implementation sources

Back to contents ↑
06 / SEQUENCE / DOC-WIDE

Offline replay and refusal

Replay keeps the original body ID and farm scope, and separates temporary failures from permanent refusals.

Offline replay and refusalReplay keeps the original body ID and farm scope, and separates temporary failures from permanent refusals.ALT[Replay accepted][Replay failed]01 READ QUEUE02 READY ITEMS03 REPLAY04 MUTATION05 ACCEPTED06 DONE07 REMOVE ITEM08 FAILURE09 PROBLEM10 RETAIN ITEMSync hookLocal queueAPI clientBackendSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Sync hook → Local queue · callOnline event or 30-second interval starts one guarded flush.
02Local queue → Sync hook · returnRemove legacy auth items; skip rejected items and records held for another farm.
03Sync hook → API client · callSend eligible item with its stored body and original farm scope; disable re-queue on failure.
04API client → Backend · callSubmit authenticated farm mutation.
05Backend → API client · returnBackend accepts mutation.
06API client → Sync hook · returnReplay resolves successfully.
07Sync hook → Local queue · successDelete successfully sent queue item.
08Backend → API client · returnAlternative: HTTP problem or network failure.
09API client → Sync hook · returnPropagate failure to queue flusher.
10Sync hook → Local queue · callRetry network/5xx/401/408/429 later; mark other 4xx rejected for user action.

Rules and alternative paths

  • The ALT frame shows two alternative outcomes, not two responses to the same request. Each flush snapshots the queue and processes eligible items serially.
  • Rejected items wait for an explicit retry or discard. UUID preservation supports identity across retries; deduplication must be verified per endpoint.

Implementation sources

Back to contents ↑
07 / SEQUENCE / DOC-WIDE

Create a distinct animal cohort

Each acquisition establishes its own population denominator and economics.

Create a distinct animal cohortEach acquisition establishes its own population denominator and economics.01 NEW COHORT02 CHECK BREED03 AVAILABLE04 UNIQUE CODE05 SAVE GROUP06 OPEN COUNT07 AUDIT08 COHORTFarmerGroup serviceBreed directoryPostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Group service · callSubmit breed, acquired quantity, purchase details, optional expense link and opening balance.
02Group service → Breed directory · callRequire breed available to this farm.
03Breed directory → Group service · returnReturn available breed capability.
04Group service → PostgreSQL / audit · callSuggest or validate a unique farm-local group code.
05Group service → PostgreSQL / audit · callPersist a new cohort using supplied record ID, acquired quantity and purchase details.
06Group service → PostgreSQL / audit · callIf supplied positive, save reason-coded opening balance dated in the farm timezone.
07Group service → PostgreSQL / audit · callPublish create audit for group and any opening adjustment.
08Group service → Farmer · successReturn group with derived current population and mortality rate.

Rules and alternative paths

  • A purchase creates a new group rather than adding acquired animals to an existing one. Opening adjustment is separate from the acquired quantity.
  • This service stores an optional purchaseExpenseId supplied by the request; it does not itself create a purchase expense. All create-path writes share a transaction.

Implementation sources

Back to contents ↑
08 / SEQUENCE / DOC-WIDE

Egg collection create or correction

One group/date record is updated when that day already exists.

Egg collection create or correctionOne group/date record is updated when that day already exists.ALT[Existing group/day][No existing group/day]01 COLLECTION02 GROUP03 EGG CAPABLE04 FIND DAY05 DAY RECORD06 UPDATE DAY07 UPDATED08 CREATE DAY09 CREATEDFarmerEggServiceGroup directoryPostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → EggService · callSubmit group, farm date and individual egg counts.
02EggService → Group directory · callResolve farm-owned group and its breed production capabilities.
03Group directory → EggService · returnReturn group; require an egg-laying breed.
04EggService → PostgreSQL / audit · callFind an existing collection for this group and collectedOn.
05PostgreSQL / audit → EggService · returnReturn existing collection or no row.
06EggService → PostgreSQL / audit · callExisting day: update counts and audit field changes.
07EggService → Farmer · successReturn corrected daily collection.
08EggService → PostgreSQL / audit · callOtherwise: persist new row using supplied ID and publish create audit.
09EggService → Farmer · returnReturn new collection.

Rules and alternative paths

  • Egg quantities are individual eggs. Crates are a display and pricing conversion at 30 eggs per crate.
  • Collection and sales are independent; a sale need not wait for a collection entry.

Implementation sources

Back to contents ↑
09 / SEQUENCE / DOC-WIDE

Feed consumption and linked cost

Feed weight and optional money are recorded atomically.

Feed consumption and linked costFeed weight and optional money are recorded atomically.OPT[cost supplied]01 FEED ENTRY02 VALIDATE03 REFERENCES04 COST ENTRY05 EXPENSE06 EXPENSE ID07 SAVE FEED08 RECORDEDFarmerFeed serviceGroup / feed typesLinked expensesPostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Feed service · callSubmit date, unit, quantity, optional bag weight and cost.
02Feed service → Group / feed types · callRequire open farm-owned group, available feed type and date within group lifetime.
03Group / feed types → Feed service · returnReturn validated group and type.
04Feed service → Linked expenses · callWhen cost supplied, create a linked FEED expense allocated to this group.
05Linked expenses → PostgreSQL / audit · callPersist expense through the common owner-versus-review approval policy.
06Linked expenses → Feed service · returnReturn linked expense ID.
07Feed service → PostgreSQL / audit · callNormalize unit to integer grams; preserve entered units; save consumption and audit.
08Feed service → Farmer · successReturn feed consumption view after transaction commits.

Rules and alternative paths

  • Bag entries require their actual weight per bag. KG entries must not carry a bag weight. Weight conversion refuses excess precision.
  • Cost is optional; the COST ENTRY block is omitted when no linked expense is needed. Feed and cost share the same transaction. Updating or deleting feed keeps the linked expense consistent.
  • Weight samples, growth summaries, feed performance and forecasts consume recorded data; forecast output does not post an expense.

Implementation sources

Back to contents ↑
10 / SEQUENCE / DOC-WIDE

Weight sampling for growth analysis

The server derives sample statistics and preserves individual measurements when supplied.

Weight sampling for growth analysisThe server derives sample statistics and preserves individual measurements when supplied.01 WEIGHT02 CHECK GROUP03 GROUP04 SAVE SAMPLE05 WEIGHTS06 AUDIT07 SAMPLE VIEWFarmerWeight serviceGroup directoryPostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Weight service · callSubmit date and either summary entry or individual weight measurements.
02Weight service → Group directory · callRequire open farm-owned group and date within its lifetime.
03Group directory → Weight service · returnReturn group used for sample validation.
04Weight service → PostgreSQL / audit · callValidate mode, derive sample size/average/min/max as applicable and persist integer-gram summary.
05Weight service → PostgreSQL / audit · callPersist individual measurement rows when provided.
06Weight service → PostgreSQL / audit · callPublish sample create audit in the transaction.
07Weight service → Farmer · successReturn saved summary and measurement details for growth views.

Rules and alternative paths

  • Summary mode and individual measurement mode have distinct validation. Values are normalized to grams rather than stored as binary floating-point kilograms.
  • Growth and feed-performance calculations read these samples and feed records. A sample entry does not itself record a feed cost or post money.

Implementation sources

Back to contents ↑
11 / SEQUENCE / DOC-WIDE

Mortality and concurrent population

Deaths compete with animal sales and adjustments for the same available population.

Mortality and concurrent populationDeaths compete with animal sales and adjustments for the same available population.01 DEATH COUNT02 LOCK GROUP03 GROUP04 POPULATION05 AVAILABLE06 SAVE RECORD07 RECORDEDFarmerMortality servicePopulation servicePostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Mortality service · callSubmit group, quantity, date, suspected cause and notes.
02Mortality service → PostgreSQL / audit · callResolve and lock the group belonging to the active farm. The create path does not call the open-state guard.
03PostgreSQL / audit → Mortality service · returnReturn locked farm-owned group.
04Mortality service → Population service · callCalculate animals currently alive from committed group facts.
05Population service → Mortality service · returnReturn current count; reject mortality exceeding available population.
06Mortality service → PostgreSQL / audit · callPersist mortality record with supplied ID and create audit in one transaction.
07Mortality service → Farmer · successReturn mortality entry; subsequent population reads include the deaths.

Rules and alternative paths

  • Raising a previous death count checks only the increase against remaining population under the same group lock. Correcting the count downward is allowed.
  • Deleting a death returns animals to derived population. Update and delete explicitly refuse closed groups. Mortality creation uses a different helper without that check; the diagram records this implementation gap rather than implying uniform enforcement.

Implementation sources

Back to contents ↑
12 / SEQUENCE / DOC-WIDE

Health activity and its linked expense

Vaccination or treatment records can carry a cost without separating the operational fact from its money.

Health activity and its linked expenseVaccination or treatment records can carry a cost without separating the operational fact from its money.OPT[cost supplied]01 HEALTH02 FARM GROUP03 GROUP04 HEALTH COST05 EXPENSE06 EXPENSE ID07 SAVE HEALTH08 RECORDEDFarmerHealth serviceGroup directoryLinked expensesPostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Health service · callSubmit record type, substance, date, treated quantity, next due date and optional cost.
02Health service → Group directory · callRequire an available group belonging to the active farm.
03Group directory → Health service · returnReturn farm-scoped group.
04Health service → Linked expenses · callIf cost supplied, create category-appropriate linked expense through common approval policy.
05Linked expenses → PostgreSQL / audit · callPersist linked expense and its audit.
06Linked expenses → Health service · returnReturn linked expense reference.
07Health service → PostgreSQL / audit · callSave health record and create audit in the same transaction.
08Health service → Farmer · successReturn health record with next-due and linked-cost details.

Rules and alternative paths

  • On update, a linked expense amount and date are kept aligned with the health record. Deleting a costed health record also deletes the linked expense.
  • The diagram describes recording a farmer-entered treatment or vaccination; it does not imply AI diagnosis or automatic prescription.

Implementation sources

Back to contents ↑
13 / FLOWCHART / DOC-WIDE

Closing an animal cohort

A group closes only after every remaining animal is accounted for, then stores its financial snapshot.

Closing an animal cohortA group closes only after every remaining animal is accounted for, then stores its financial snapshot.YESNOCONTINUERequest closureDate, reason, notesLock farm-owned groupReject already closed groupLiving animalsremain?Require full closing adjustmentReason-coded; all living animalsSave negative adjustment and auditOPENING_BALANCE is invalid hereRead financial snapshotRevenue, cost, contributionClose group and preserve snapshotKeep pre-adjustment live countSkip closing adjustmentContinue at Read financial snapshotOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • A positive remainder does not prohibit closure. It requires a reason-coded adjustment whose quantity equals the full living population.
  • The adjustment, status change, financial snapshot and audit writes are in one transaction. The stored live-at-closure count preserves the pre-adjustment count.
  • Group results are contributions because farm overhead is unallocated. New acquisitions create new cohorts; they do not enlarge an existing one.

Implementation sources

Back to contents ↑
14 / FLOWCHART / DOC-WIDE

Expense submission and booking

Only the owner books their own spending immediately. Manager and staff spending enters review.

Expense submission and bookingOnly the owner books their own spending immediately. Manager and staff spending enters review.NOYESEnter expense and allocationsOptional initial payment entriesValidate farm references and splitsExact kobo and feed-weight totalsSave expense, allocations, paymentsOne transaction with attributionOwner booksspending?Place in pending reviewManager spending also needs reviewDifferent owner / manager reviewsNo approval of own submissionBook only after approvalApproved expense locks for editingApprove owner spendingIncluded in approved reportingOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • All-explicit allocation amounts must reconcile exactly; otherwise the service derives shares using largest remainder. Feed purchase allocation weights also reconcile.
  • Query and reject require comments. Reopening an approved expense requires a reason, removes it from approved books, and allows correction.
  • Linked feed and health expenses use the same approval decision. Paying an expense and approving it are separate facts.

Implementation sources

Back to contents ↑
15 / FLOWCHART / DOC-WIDE

Expense review outcomes

Approval, query and rejection have different effects on books and correction paths.

Expense review outcomesApproval, query and rejection have different effects on books and correction paths.YESNONONOYESYESPending expenseSubmitted spending awaits reviewEligible reviewer?Approve thisexpense?Ask for correction?Reject expense and notifyExcluded from approved booksRefuse reviewKeep recorded approval stateApprove and lockInclude in approved reportingQuery and notify submitterCorrect, then resubmit for reviewOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • This flow starts after a non-owner expense has been submitted. The owner’s own spending is approved on creation and skips review.
  • Queried or rejected records can be resubmitted according to model state rules and authority. Approved spending must be reopened with a reason before corrections.
  • The review thread persists decision, actor, comment and time, alongside approval-state audit changes.

Implementation sources

Back to contents ↑
16 / SEQUENCE / DOC-WIDE

Review, query and correction

A queried expense returns to its submitter with an attributable review thread.

Review, query and correctionA queried expense returns to its submitter with an attributable review thread.01 QUERY02 LOCK COST03 EXPENSE04 SAVE REVIEW05 NOTIFY06 QUERIED07 REASON08 RESUBMIT09 PENDING10 IN REVIEWOwner / managerReview servicePostgreSQL / auditNotification moduleSubmitterSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Owner / manager → Review service · callSubmit a query with required comment.
02Review service → PostgreSQL / audit · callLoad farm-owned expense for update.
03PostgreSQL / audit → Review service · returnReturn expense and creator; reject reviewing own submission.
04Review service → PostgreSQL / audit · callSet QUERIED, persist review event and approval-status audit.
05Review service → Notification module · asyncPublish MessageRequested for the submitter.
06Review service → Owner / manager · returnReturn query result.
07Notification module → Submitter · asyncDeliver configured notification with review reason.
08Submitter → Review service · callSubmitter corrects the expense and requests resubmission.
09Review service → PostgreSQL / audit · callValidate resubmission authority/state and record RESUBMITTED review plus audit.
10Review service → Submitter · successReturn expense to pending review.

Rules and alternative paths

  • Approve books spending; reject excludes it. Query and reject notify the submitter. This diagram follows query and resubmit; approve/reject are parallel service operations.
  • Approved records are locked for everyone. An owner or manager must reopen with a reason before a correction. Resubmission permits the original submitter or an actor with approval authority.

Implementation sources

Back to contents ↑
17 / SEQUENCE / DOC-WIDE

Expense settlement and owner investment

Expense payments derive the remaining balance and may record owner-funded capital separately.

Expense settlement and owner investmentExpense payments derive the remaining balance and may record owner-funded capital separately.01 ADD PAYMENT02 LOCK COST03 LEDGER04 SAVE PAY05 CAPITAL06 RECALCULATE07 NEW BALANCEFarmerPayment servicePostgreSQL / auditSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Payment service · callSubmit payment UUID, amount, date, method and optional owner contribution.
02Payment service → PostgreSQL / audit · callRequire settleable farm expense and read current payment ledger.
03PostgreSQL / audit → Payment service · returnReturn expense, prior payments and any matching supplied ID.
04Payment service → PostgreSQL / audit · callValidate payment does not exceed remaining balance; persist payment.
05Payment service → PostgreSQL / audit · callWhen owner contribution is supplied, persist linked capital contribution separately.
06Payment service → PostgreSQL / audit · callDerive amount paid, payment status and date from payment rows; publish audit.
07Payment service → Farmer · successReturn updated expense ledger and remaining balance.

Rules and alternative paths

  • An already used payment ID returns the prior ledger only if farm, expense, amount, date, method, reference, notes and owner contribution agree. A conflicting reuse is rejected.
  • Owner investment is capital, not sales revenue. Rejected expenses cannot be paid. On approved expenses, only owner/manager can add payments; existing payment entries cannot be edited or deleted until the expense is reopened.

Implementation sources

Back to contents ↑
18 / FLOWCHART / DOC-WIDE

Sales and population protection

Egg sales and animal sales follow different validation paths, then share exact pricing and payment calculation.

Sales and population protectionEgg sales and animal sales follow different validation paths, then share exact pricing and payment calculation.YESNOCONTINUEEnter saleProduct, quantity, price, customerValidate customer belongs to farmOptional registered customerAnimal sale?Lock group and check populationGroup open; quantity availableValidate pricing modeCrate / egg / animal / weightCalculate total and paymentServer derives total in koboSave sale and auditAnimal sales affect populationValidate optional egg groupContinue at Validate pricing modeOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • Eggs may be sold without any matching production record. PER_CRATE applies only to eggs, and quantities remain individual eggs.
  • Animal sales require a group. The group lock protects available population from competing sales, mortality and adjustments.
  • Payment.resolve derives settled amount and status. An edit cannot switch the sale product, group or pricing mode.

Implementation sources

Back to contents ↑
19 / FLOWCHART / DOC-WIDE

Ownership transfer with renewed consent

Both offer and acceptance check the recipient’s farm capacity.

Ownership transfer with renewed consentBoth offer and acceptance check the recipient’s farm capacity.YESYESNONOOwner offers farm to recipientOptional keep-access preferenceValidate recipient and offer rulesVerified email, capacity, cooldownStore pending offer and notifyRecipient accepts or declinesLock accounts, offer and farmFixed account order avoids deadlockOffer and farmvalid?Recipient has room?Transfer ownership and rolesReset owned_since; audit; notifyNo ownership changeDecline / cancellation / expiryKeep pending; choose larger planRetry acceptance after upgradeOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • An offer requires another verified account, room in its plan, no current open offer and any ownership-change cooldown to have elapsed. Acceptance locks accounts and offer before validating openness, then locks the farm before owner and plan checks.
  • The recipient becomes OWNER. The former owner becomes MANAGER if keepAccess is true; otherwise their membership is removed.
  • Subscription, saved cards and other farms stay with their original account. Existing farm records remain with the transferred farm.

Implementation sources

Back to contents ↑
20 / SEQUENCE / DOC-WIDE

Transfer acceptance transaction

Fixed-order locks protect capacity when concurrent offers touch the same accounts.

Transfer acceptance transactionFixed-order locks protect capacity when concurrent offers touch the same accounts.01 ACCEPT02 LOCK USERS03 OPEN OFFER04 LOCK FARM05 CAPACITY06 ALLOWED07 TRANSFER08 AUDIT09 NOTIFY10 ACCEPTEDRecipientTransfer serviceEntitlementsPostgreSQL / auditNotification moduleSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Recipient → Transfer service · callAccept an offer addressed to the current user.
02Transfer service → PostgreSQL / audit · callLock sender and recipient accounts in a fixed order, then lock transfer.
03PostgreSQL / audit → Transfer service · returnRequire PENDING and unexpired offer.
04Transfer service → PostgreSQL / audit · callRequire accessible farm still owned by sender.
05Transfer service → Entitlements · callRead recipient plan and count currently owned farms.
06Entitlements → Transfer service · returnRequire FARMS_MAX allows another farm at this moment.
07Transfer service → PostgreSQL / audit · callChange owner and owned_since; reset kept-active choice; update memberships and offer.
08Transfer service → PostgreSQL / audit · callWrite owner, membership and accepted-offer audit changes in the transaction.
09Transfer service → Notification module · asyncPublish notifications for ownership change.
10Transfer service → Recipient · successReturn successful acceptance.

Rules and alternative paths

  • Insufficient capacity leaves the offer pending for upgrade and retry. Expired, inaccessible or changed-owner offers do not reach the ownership update.
  • Former-owner access follows the stored keepAccess preference; billing account and cards are not transferred.

Implementation sources

Back to contents ↑
21 / SEQUENCE / DOC-WIDE

Reports from committed farm facts

Farm-scoped SQL queries assemble financial and operational summaries.

Reports from committed farm factsFarm-scoped SQL queries assemble financial and operational summaries.01 FILTER02 LOOKUP03 MISS04 QUERY VIEWS05 AGGREGATES06 CACHE07 REPORTFarmerReporting serviceReport cachePostgreSQL viewsSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Reporting service · callRequest active-farm report with date/group filters.
02Reporting service → Report cache · callFor cached summary paths, check the report cache.
03Report cache → Reporting service · returnCache-miss path continues to focused query modules.
04Reporting service → PostgreSQL views · callRead farm-filtered reporting views and query modules.
05PostgreSQL views → Reporting service · returnReturn approved expenses, sales, payments, capital and operational totals.
06Reporting service → Report cache · callStore eligible computed summary with its scoped key.
07Reporting service → Farmer · successReturn typed report values for display.

Rules and alternative paths

  • A cache hit returns its stored summary without the SQL path. Not every report endpoint uses this cache.
  • Farm profit and group contribution are different measures. Capital stays separate from revenue; cash received and accrued sale totals remain distinct.
  • Query modules and views are grouped here instead of drawing each SQL aggregation as an actor.

Implementation sources

Back to contents ↑
22 / SEQUENCE / DOC-WIDE

Farm question classification and answer

The model selects intent and period; application reports supply the answer’s numbers.

Farm question classification and answerThe model selects intent and period; application reports supply the answer’s numbers.01 QUESTION02 LOCK USER03 ALLOWANCE04 CLASSIFY05 INTENT06 REPORT07 FACTS08 RELEASE09 ANSWERFarmerQuestion serviceRedis / allowanceAI classifierReporting serviceSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Question service · callAsk an eligible farm question.
02Question service → Redis / allowance · callAcquire per-account asking lock and check monthly question allowance.
03Redis / allowance → Question service · returnReturn available allowance; concurrent or exhausted account exits early.
04Question service → AI classifier · callSend question plus permitted intents and periods.
05AI classifier → Question service · returnReturn MATCHED, UNSUPPORTED or UNAVAILABLE.
06Question service → Reporting service · callFor matched intent, check money authority, derive dates in farm timezone and run matching report.
07Reporting service → Question service · returnReturn trusted numerical facts.
08Question service → Redis / allowance · callRelease the per-account asking lock in finally.
09Question service → Farmer · successBuild application-authored answer with facts, link and remaining allowance.

Rules and alternative paths

  • The current code checks money-question authority after classification, inside answer(), even though the service comment describes a pre-model check. This diagram follows executable behavior.
  • The question classifier receives words and intent options, not the report figures; it does not generate the numerical answer. Health questions receive the defined non-diagnostic response.
  • Weekly narrative and portfolio narration are separate AI paths and should not be assumed to share this classifier-only data boundary.

Implementation sources

Back to contents ↑
23 / SEQUENCE / DOC-WIDE

Receipt or voice to reviewed expense

Extraction proposes fields, and the farmer reviews them before ordinary expense submission.

Receipt or voice to reviewed expenseExtraction proposes fields, and the farmer reviews them before ordinary expense submission.01 MEDIA02 EXTRACT03 EXTRACT04 FIELDS05 DRAFT06 REVIEW07 CONFIRM08 SAVE COST09 SAVEDFarmerExpense formDraft controllerAllowance / AIExpense serviceSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Farmer → Expense form · callChoose receipt image or voice recording.
02Expense form → Draft controller · callSend kind, MIME type and base64 media.
03Draft controller → Allowance / AI · callCheck AI entitlement, MIME and 1 byte to 5 MiB size; spend draft allowance and extract.
04Allowance / AI → Draft controller · returnReturn proposed amount, date and description with available extraction metadata.
05Draft controller → Expense form · returnReturn ExpenseDraft; no expense is posted.
06Expense form → Farmer · returnShow proposed fields for correction.
07Farmer → Expense form · callFarmer confirms complete expense and allocation/payment fields.
08Expense form → Expense service · callSubmit through normal validated and audited expense recording.
09Expense service → Expense form · successReturn saved expense and its approval state.

Rules and alternative paths

  • Feature gate is AI_SUMMARIES; monthly usage gate is AI_DRAFTS_MONTHLY_MAX, shared by receipt and voice draft features.
  • Unsupported media, invalid base64, unavailable providers or exhausted allowance do not create financial records. Manual entry remains available.

Implementation sources

Back to contents ↑
24 / SEQUENCE / DOC-WIDE

Paged farm export and completion history

Dataset exports release their database connection between pages and record the requesting actor throughout.

Paged farm export and completion historyDataset exports release their database connection between pages and record the requesting actor throughout.LOOP[while cursor remains]01 EXPORT02 START LOG03 EXPORT ID04 READ PAGE05 PAGE06 WRITE ROWS07 FINISH LOG08 FILEOwner / managerExport serviceRecorder / PostgreSQLDataset contributorDownload streamSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Owner / manager → Export service · callRequest farm period and allowed export format.
02Export service → Recorder / PostgreSQL · callAcquire limits/permit; insert data_exports record on request thread with requester.
03Recorder / PostgreSQL → Export service · returnReturn export identifier before first response byte.
04Export service → Dataset contributor · callRead one contributor page inside a short read-only transaction.
05Dataset contributor → Export service · returnReturn bounded page and next cursor; database transaction ends.
06Export service → Download stream · callWrite rows with no database connection pinned to the slow download.
07Export service → Recorder / PostgreSQL · callAfter final byte, record counts, bytes and duration as requester; release permit.
08Download stream → Owner / manager · successDeliver archive or workbook.

Rules and alternative paths

  • The LOOP fragment repeats steps 04–06 (read page, return page and write rows) until the cursor is empty, for every selected dataset.
  • Stream failure records failed history and releases the permit. Exceeding the row ceiling fails instead of silently truncating.
  • PDF report figures are collected on the request thread via ReportContributor; that report path differs from the paged dataset loop. Export history is owner-only; downloads allow owner and manager.

Implementation sources

Back to contents ↑
25 / SEQUENCE / DOC-WIDE

Paid plan checkout

Invoice and payment attempt exist before the gateway is called.

Paid plan checkoutInvoice and payment attempt exist before the gateway is called.01 CHECKOUT02 START PAY03 REFERENCE04 INITIALIZE05 PAY URL06 STORE URL07 PAY PAGE08 PAYOwnerCheckout servicePostgreSQLPayment gatewaySOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Owner → Checkout service · callChoose price and optional enabled provider.
02Checkout service → PostgreSQL · callCalculate server quote; create invoice and payment reference in a short transaction.
03PostgreSQL → Checkout service · returnReturn persisted invoice/payment identifiers; release database transaction.
04Checkout service → Payment gateway · callInitialize hosted checkout with reference, expected invoice amount and account email.
05Payment gateway → Checkout service · returnReturn provider session.
06Checkout service → PostgreSQL · callStore checkout URL for recovery.
07Checkout service → Owner · successReturn checkout session; owner opens hosted payment.
08Owner → Payment gateway · callOwner completes provider payment.

Rules and alternative paths

  • This is the positive-charge path. A zero-total upgrade uses settleZeroInvoice; a scheduled downgrade does not charge immediately.
  • A gateway initialization error records an abandoned/failed attempt. A browser return asks the server to verify payment; it does not itself grant a plan.

Implementation sources

Back to contents ↑
26 / SEQUENCE / DOC-WIDE

Webhook receipt and deferred verification

Signed event receipt is separate from applying a paid subscription.

Webhook receipt and deferred verificationSigned event receipt is separate from applying a paid subscription.01 WEBHOOK02 STORE EVENT03 EVENT ID04 NEW EVENT05 ACKNOWLEDGE06 LOAD EVENT07 STORED BODY08 VERIFY09 TRANSACTION10 SETTLE11 OUTCOME12 EVENT STATEPayment gatewayWebhook serviceEvent storeEvent processorSettlement serviceSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Payment gateway → Webhook service · callSend provider event with raw body and signature.
02Webhook service → Event store · callCheck configured source allowlist and raw-byte signature before parsing; deduplicate provider event.
03Event store → Webhook service · returnReturn new event ID, or no ID for an already stored event.
04Webhook service → Event processor · asyncFor a new event, publish GatewayEventReceived to the asynchronous listener.
05Webhook service → Payment gateway · successReturn successful webhook acknowledgement; duplicate events are also acknowledged.
06Event processor → Event store · callLoad stored event; skip previously PROCESSED/IGNORED records.
07Event store → Event processor · returnReturn provider/type/payload for supported-event dispatch.
08Event processor → Payment gateway · callFor charge.success, ask gateway to verify the payment reference rather than trusting webhook amounts.
09Payment gateway → Event processor · returnReturn authoritative gateway transaction.
10Event processor → Settlement service · callUse shared account-attributed settlement transaction.
11Settlement service → Event processor · returnReturn settlement outcome.
12Event processor → Event store · callRecord PROCESSED/IGNORED or FAILED; reconciliation reprocesses recoverable stored events.

Rules and alternative paths

  • Receipt and async processing can overlap in wall-clock time. Their visual order explains the handoff; it does not assert the listener starts only after the HTTP acknowledgement.
  • Invalid signatures or disallowed configured sources are refused before storing. Only a new deduplicated event publishes work.
  • APPLIED, ALREADY_APPLIED, MISMATCH and FAILED settlement outcomes mark charge.success events PROCESSED; UNKNOWN is IGNORED. PENDING verification or processor exceptions leave FAILED event state for recovery. Dispute and refund events use separate processor branches.

Implementation sources

Back to contents ↑
27 / SEQUENCE / DOC-WIDE

Verified payment settlement

Return verification, webhooks and reconciliation converge on the same settlement transaction.

Verified payment settlementReturn verification, webhooks and reconciliation converge on the same settlement transaction.01 VERIFY02 TRANSACTION03 SETTLE04 LOCK PAY05 STATE06 APPLY07 PAID EVENT08 APPLIEDConfirm / hook / jobPayment gatewaySettlement servicePostgreSQL / auditNotification eventsSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Confirm / hook / job → Payment gateway · callUse server-side gateway verification for the payment reference.
02Payment gateway → Confirm / hook / job · returnReturn authoritative gateway status, currency and amounts.
03Confirm / hook / job → Settlement service · callPass verified transaction into shared settlement path.
04Settlement service → PostgreSQL / audit · callResolve payment account; establish BillingActor; lock payment and invoice.
05PostgreSQL / audit → Settlement service · returnReturn stored invoice and prior payment status.
06Settlement service → PostgreSQL / audit · callFor valid success, number/pay invoice, succeed payment, update subscription, optionally save reusable card and audit.
07Settlement service → Notification events · asyncPublish PaymentCollected after recording the successful payment.
08Settlement service → Confirm / hook / job · successReturn APPLIED settlement outcome.

Rules and alternative paths

  • Already successful payments return ALREADY_APPLIED. Unknown references, pending transactions, failed/abandoned payments and mismatches return their respective outcomes.
  • NGN and invoice totals are verified. Recognized provider customer-fee handling permits only a verified exact fee difference. Invoice amount is never taken from the browser.
  • All settlement writes are atomic and attributed to the payment account. The event represents a request for downstream handling, not synchronous notification delivery.

Implementation sources

Back to contents ↑
28 / FLOWCHART / DOC-WIDE

Settlement outcomes and safe retries

The same verified payment may be seen repeatedly without applying a second successful settlement.

Settlement outcomes and safe retriesThe same verified payment may be seen repeatedly without applying a second successful settlement.NOYESYESYESNONOLock known incoming paymentVerified reference; BillingActor setAlready settled?Lock invoice and read gateway stateCard-check payments use own branchGateway success?Verified totalsvalid?Apply atomic settlementInvoice + subscription + paymentALREADY_APPLIEDNo second subscription updatePENDING or FAILEDFailure records attempt/dunningMISMATCHRecord mismatch; do not grant planOVAL START / HANDOFF / END RECTANGLE ACTION DIAMOND DECISION

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Decision detail

Rules and alternative paths

  • Unknown references or non-incoming payments return UNKNOWN before this flow. CARD_UPDATE uses a separate verification and refund path.
  • SUCCESS requires NGN, expected invoice/payment totals (with recognized verified customer-fee handling), an open invoice and, for renewal, an existing subscription.
  • Pending state performs no settlement. Duplicate success checks happen before invoice loading; the diagram preserves that ordering.

Implementation sources

Back to contents ↑
29 / SEQUENCE / DOC-WIDE

Renewal without network-held locks

The renewal scheduler claims work, calls the gateway outside the transaction, then records the outcome.

Renewal without network-held locksThe renewal scheduler claims work, calls the gateway outside the transaction, then records the outcome.01 CLAIM DUE02 SUB STATE03 DECIDE04 CHARGE JOB05 CHARGE CARD06 OUTCOME07 RECORD08 SAVE STATE09 NOTICERenewal schedulerPostgreSQLPayment gatewaySettlement / dunningOwnerSOLID CALL DASHED + FILLED HEAD RETURN DASHED + OPEN HEAD EVENT GREEN PRIMARY RESULT

Scroll the diagram horizontally on smaller screens. The full interaction text follows below.

Message detail

StepInteraction
01Renewal scheduler → PostgreSQL · callClaim subscription with FOR UPDATE SKIP LOCKED; establish account actor.
02PostgreSQL → Renewal scheduler · returnReturn due state and release claim transaction when decision is persisted.
03Renewal scheduler → PostgreSQL · callIssue/remind invoice, expire grace, or create a charge attempt when due.
04PostgreSQL → Renewal scheduler · returnCommit reference and charge job; pending attempts prevent another charge.
05Renewal scheduler → Payment gateway · callCharge saved authorization with no open database lock or transaction.
06Payment gateway → Renewal scheduler · returnReturn verified success/failure, pending status or action-required result.
07Renewal scheduler → Settlement / dunning · callApply shared settlement or dunning/action-required handling.
08Settlement / dunning → PostgreSQL · callUpdate invoice/payment/subscription or next retry state transactionally.
09Settlement / dunning → Owner · asyncRequest configured renewal/payment notice through notification handling.

Rules and alternative paths

  • Invoices issue at configured lead time. Automatic payers charge a day before period end and retry on schedule until grace ends; manual payers receive an invoice/reminders.
  • Gateway reachability failure does not move grace as an owner payment failure would. Grace expiry ends access through the lapsed plan rather than the beta default plan.

Implementation sources