What Versable Foundry is for, restated once so it does not have to be re-derived
from chat. Sources: the owner's answers of 2026-08-17 (this session), the
owner's replatform-thoughts.md, app-overhaul.tech.md.md, and
versable-v2-thoughts.product.md in versable-builder/user_docs/, and the
five instance breakdowns in instances/. Where this doc restates the owner
in cleaner words, the restatement is mine and the owner can correct it.
Audience: anyone about to build a module or an app, or edit this tree.
The problem, in the owner's terms#
App V5 (enhancement-product) built up a lot of capabilities that were
largely self-contained. Then customers needed a radically different
workflow, which meant shipping MVPs (speedway, walmart-mvp) with a
different data model and a tailored feature set, even though ninety percent
of the module capability was the same. The result was copy-pasted code, and
QA, edge cases, logging, observability, credits, and storage all done again
per app.
Two things are both bad: cramming everything into one monolithic module, and duplicating everything per app. The target is a system generic enough to plug into any app, extensible in some ways, and, when something radically different is needed for the same goal (capability, compliance, shipping speed), swappable: several versions of the same capability running across several apps, without two weeks of dev time to upgrade any of them.
Three pain points name the design goal precisely: ease of swapping, ease of upgrading, graceful degradation.
The two things this tree describes#
A module is one capability, exposed as a service, callable from any app
or directly over an API. Content generation (services-api today), image
generation, part-type matching, attribute normalization, data extraction
(extractor today). A module is one API call plus the ecosystem it needs to run
in production: persistence, caching, worker
capacity, credits, team RBAC arriving from more than one app, logs a caller
can read, a way to re-run and inspect.
An app composes modules for a customer. The Workflow Console is the first one built on this tree. It owns the things a module should not: the customer's account, the workflow orchestrator, the per-customer configuration, the review surfaces, the specific UI each module needs (customers will not write JSON configs; per-module UI is real work and the kit exists to make it cheap).
Where the line sits#
The seam that separates a module's generic machinery from its domain work has
now been drawn independently three times, in three stacks, and it lands in
the same place each time (canon/01-runner-and-payload.md). Building on
that: the module owns everything up to and including "run this capability
over these items and tell the caller what happened"; the app owns everything
about "why, for whom, in what order, and what happens to the result".
Concretely, in the module:
- accepting work from an identified caller on behalf of a tenant
- running it: dispatch, concurrency, retries, cancel, resume, idempotency
- recording what happened: outcomes per item, errors, usage, cost, logs
- reporting status and results back, with pagination and search
- caching, so the same expensive question is not asked twice
- health, versioning, a manifest of what it can do
And in the app:
- the orchestrator loop (assess, find the gap, pick the cheapest way to close it, act, re-check) and the definition of done per customer
- the SKU state machine (flowing, held, waived, complete) and the review queue
- per-customer configuration: taxonomy, schema, accepted values, templates, load-sheet shape
- users, sessions, orgs, workspaces, roles; the module only ever sees a verified caller and a tenant id
- billing plans and limits; the module meters, the app enforces
Two things sit on the line and are decided per concern rather than by this
paragraph: job state (a module may keep its own, or mirror state the
caller owns; canon/03-jobs-and-state.md) and human-in-the-loop (a
module can emit "needs review" as an outcome; the queue that holds it belongs
to the app; canon/10-human-in-the-loop.md).
Prescriptive, with a feedback path#
This tree leans prescriptive. A module built against it should be checkable
against contracts/, and a "should" in canon/ is a real should. But the
rules come from a small number of real services and will meet cases they did
not anticipate. So every rule cites the instance it came from, every instance
breakdown carries a Lapses section, and a lapse that keeps recurring, or that
turns out to be right, changes the rule. The first couple of modules and the
first use of the Workflow Console are expected to rewrite parts of this.
Two working principles#
Suggestibility instead of proclamation. Business and product input (Christina's note, the PM's notes) is taken seriously as what the people closest to the customer want, and adopted through this team's own systemization. It never lifts straight into a canon "must". Where such input implies an engineering choice, the choice is named, defaulted, and put to the owner. Owner, 2026-08-17.
A divergence is called out and decided, never smoothed over. When a prior doc, a prior service, and this contract disagree, the disagreement is written down with citations and a stated default, and the decision about what works better for the case is explicit. Prior code is allowed to differ; it is not allowed to differ silently. Owner, 2026-08-17.
Providers#
All of the named providers are in scope, and, in the owner's words, "some are more equal than others". GCP is the default deployment target (startup credits; workers, storage, Firestore, and the rest come with it). App V5's microservice suite is mature on Render, and Render also hosts the Redis used for V5-wide caching. The Workflow Console and the versable-builder UI deploy on Vercel. Cloudflare is domains, and workers only if it must be. Oxylabs is scraping. Langfuse is tracing.
Swappability means two different things and only one is a near-term goal:
- Different modules on different clouds under one contract: needed now. Each app currently has a different auth model, and modules will sit on GCP and Render at the same time. The contract has to make that a non-event.
- Redeploying one module onto another cloud: nice to have, design the abstractions so it is not painful, do not pay for it up front.
Anything in this tree that only works on one vendor says so.
Who calls a module#
Mainly the apps, across clouds, usually on behalf of a human (directly, or via
a workflow run that then calls each module and needs logs, re-runs, detailed
inspection, and the ability to step back and forth). Direct API and LLM-agent
calls are the building and debugging path, and that path matters: "works on
my machine, not on prod" has been a large, recurring source of friction, and
the local and debugging story is a first-class concern here, not an
afterthought (canon/13-local-dev-and-debugging.md).
What the MVPs are for#
speedway and walmart-mvp are evidence. They are the apps that had to
ship before this could be built, and they proved that separate apps with
different configuration, sources, and DNA can serve the same customers who
were onboarded to App V5. They will not be ported onto this contract. The
hypothetical of porting them is a useful way to ground a rule (would this
have worked for walmart?), as long as no rule bends to fit them.
Terms#
| Term | Meaning here |
|---|---|
| Versable Foundry | This doc set, plus the recipes and template code that grow out of it. Internal name. |
| V6 | The current work sprint, business-side wording for "the next iteration after App V5". This tree is the first big step under that umbrella. Not a version of any one artifact. |
| App V5 | enhancement-product, the module-per-click toolbox generation. |
| Workflow Console | The customer-facing app that comes out of V6: a workflow orchestrator plus the fixed things (auth, credits, caching), where modules plug into a workflow composer. First app built on this tree. |
| Module | One capability as a service (its variants and judges included), callable from any app or over API, with the ecosystem it needs to run in production. Co-hosting a second capability in one deployment is the stated exception in canon/14. |
| Capability | What a module does (content generation, part-type matching, extraction). A module exposes one or more capabilities; the manifest names them. |
| App | Something that composes modules for a customer and owns the customer relationship: users, orgs, config, orchestration, review UI. |
| Runner | The generic machinery inside a module or app that accepts, dispatches, runs, records, and reports work. |
| Payload | The domain work the runner runs. The thing that differs between modules. |
| Job | One submitted unit of work: a capability over N items, from one caller for one tenant. |
| Item | One element of a job's input. A SKU, a part, a row. |
| Outcome | What happened to one item: a result, a terminal error, or a request for review. |
| Caller | The verified identity that submitted a job. An app, a service, a person, or an agent. |
| Tenant | The org or workspace the work is for. Every job has exactly one. |
| Instance | A real, running service examined in instances/. |
| Witness | An instance that independently arrived at the same design, cited as evidence for a rule. |
| Peer apps | enhancement-product, walmart-mvp, speedway, versable-builder. |
| Vocabulary | payloads, runner, modules (and connectors), fittings, apps, contracts, reference data, canon, plus the bespoke label: the working words for kinds of thing in the factory, 01-system-classes.md; overlapping by design, one kind (app-side engines) still unnamed; tagged as working names by the owner 2026-08-18. Two estate-level names sit above them: forge, the product app (App V6 and successors), and foundry, versable-builder plus this contract tree. |