Codebase map · read from source

Artisan Supply Co — Laravel application map

A human-governed AI operations demo. Laravel owns the truth; a model proposes; a person decides; nothing leaves the building. Click any box on the architecture map, or step through the governance flow with a scenario selected.

What this application is

A fictional specialty coffee retailer built as a Laravel Cloud technical demonstration. Support, returns, wholesale and gift-code messages arrive on a queue; the AI SDK classifies, extracts and drafts; a staff member approves, edits or rejects; and only an approved proposal may write to a held outbox. No email, payment or refund is ever actually sent — AI_STUB=true runs the whole workflow deterministically with no API keys and no network.

92
PHP classes under app/
5
queues, one Horizon supervisor
0.70
confidence gate before a human sees a draft
£50.00
refund at or above which a manager is required
27
test files (22 Pest · 5 Playwright)

The spine

Laravel 12 on PHP 8.4, Livewire 3 for every UI surface, Eloquent as the single system of record.

  • Public: catalogue, product, checkout, contact, wholesale
  • Staff: approvals inbox, safe outbox, products, orders, image studio
  • Read-only JSON catalogue API for the satellite

The AI layer

laravel/ai with a single structured-output agent. Anthropic first, OpenAI as failover, deterministic fixtures when stubbed.

  • TriageAgent — JSON-schema output, policy docs in the instructions
  • TriageService — prompt, provider list, referral override
  • TriagePayloadValidator — re-validates what came back

The async spine

Redis + Horizon, five named queues, each with its own wait threshold and job tags.

  • triage — classification
  • outbound — approved effects
  • media — image transformations (the second model call)
  • storefront — signed cache invalidation
  • default — everything else

The satellite

A Next.js 16 App Router storefront in apps/storefront that owns no writes at all.

  • Tagged fetches against /api/catalog
  • Secret-checked /api/revalidate from Laravel
  • Same Reverb channel as the Laravel UI for live stock

Read from the repository source on 20 August 2026. Every class name, route, queue and threshold on this page was taken from the source, not inferred.

Runtime architecture

One Laravel application is the authority for product, order, proposal and outbox truth. Everything else — queues, the model, the socket server, the object store, the Next.js storefront — is an attachment that can be swapped without changing who is allowed to write.

Laravel 12 · PHP 8.4 — system of record Redis · Horizon — one supervisor, five queues dispatch outbound writes Customer browser Livewire storefront + checkout Staff browser agent · managerauth + staff middleware Public surfaces Catalogue · ProductShowCheckout · ContactFormWholesaleForm Staff console Inbox · Outbox · OrdersProducts · ImageStudioHorizon dashboard Catalogue API GET /api/catalogGET /api/catalog/{slug}read-only, no auth Actions SubmitInboundMessagePlaceOrderUpdateProductPrice Domain state machinesrefund + referral policyauthorizers Data 11 models · 18 migrationsSQLite local / Postgresappend-only event tables Domain events · Pennant flags ProposalCreated · ProposalReviewed · StockChangedProductUpdated · ReferralDiscountActivated triage classification outbound approved effects media image variants storefront revalidation default demo failure Storefront visitor separate domain, separate deploy Next.js 16 satellite apps/storefront — App Router, React 19force-cache fetches tagged catalog / product:{slug}POST /api/revalidate behind a shared secretowns no product or order writes Reverb — WebSockets private-approvals → inbox + badge refreshproduct.{id} → live stock in both storefronts AI providers laravel/ai · Anthropic → OpenAI failoverstructured output against a JSON schemastubbed by default (AI_STUB=true) Object storage — Flysystem private image variants, streamed to staff onlylocal disk → S3 / Laravel Object Storage Nightwatch web + worker runtimes, one intentional failing job
People Laravel domain Queues & workers AI providers Realtime Next.js satellite Storage & observability
Next.js → Catalogue API — tagged read-only fetches triage queue → AI providers — the classification call media queue → object storage — private image variants storefront queue → Next.js — secret-checked cache invalidation outbound queue → data — writes the held outbox row domain events → Reverb → both storefronts and the staff inbox

Reverb also pushes back to the staff browser and the Laravel product page — those arrows are left off to keep the map readable. On a narrow screen, scroll the diagram sideways.

The governed path: message in, held reply out

This is the core story of the app. Pick a scenario to see where the path bends — the interesting engineering is in the branches, not the happy case.

Where the governance is actually enforced

"Human in the loop" is a claim until you can point at the line that stops the machine. These are those lines.

Where things live

92 PHP classes under app/, organised by responsibility rather than by Laravel's default folders.

NamespaceFilesWhat it holds

Routes

Thirteen web routes, two read-only API routes, one health check.

RouteHandlerGuard

Demo controls

Seven artisan commands drive the live demo deterministically.

CommandWhat it does