English source · 7 min
Configurable furniture: one connected purchasing workflow
This app connects the material library, validated dimensions and a bounded price
rule with native company approval, checkout and reusable order lists. Its business
code and Manifest live in extensions/apps/furniture-configurator/. It adds no
physical database table and no second cart, price calculator or approval queue.
Public acceptance, 21 October: a buyer configured Walnut Select, 260 × 80 cm,
saved the selection and bought after a separate account's approval: EUR 78
surcharge and EUR 427 total. Updating the same material to Walnut Select Plus
changed the saved-list reorder to EUR 98 surcharge and EUR 447 total, requiring
fresh approval. The original order retained its old configuration and price;
return/reload retained empty carts. The initial check combined browser purchases
with native API approval. After the combined release, a separately signed-in buyer
and approver completed the entire path in the browser: RAC-34c09fc1, EUR 447.
Approval inbox and reopened customer/company orders display their frozen material,
dimensions and surcharge. See the
exact public steps and screenshots
and current release.
The earlier hosted app workflow covers pattern creation, private material writes, immutable version, reviewed sandbox install and selected publication. All these purchasing tests use synthetic customers and simulated payment. Real settlement and the wider business-capability programme remain separate.
Build and try it
For a standalone local Core, use its normal storefront address
http://127.0.0.1:<port>/?shop=<tenant>&lang=de-DE. The /s/<alias> path belongs
to a separately mounted Experience and is not a standalone Core storefront link.
Product price refreshes preserve configuration inputs and their saved confirmation;
the catalogue refreshes after cart changes and purchase. Completed-order choices
remain on the receipt rather than affecting a new catalogue purchase. The same
read-only summary appears in checkout, confirmation, native order details and app
purchase history. Accepted public field/choice/material labels and the shop main
language are frozen with the order; later app or material edits cannot rename its
choices. Older snapshots use their saved input values without fetching a newer
package. Reordering resolves current rules and creates a fresh summary.
- Open Developers → New app → Configurable furniture. This clones the app-owned pattern to an editable, namespaced Manifest. Review Business goal, assumptions, material model, actions and frozen examples. The contextual agent exports/imports the same definition; it does not receive provider secrets.
- Create a private environment, save an immutable version and stage it through the ordinary consent/digest review. The material table and form use the existing native App Studio renderer. Add materials and their EUR-cent surcharges.
- Test the product configurator. Select a material and enter integer dimensions in centimetres. The library loads bounded server pages and resolves an existing selected material by ID. Inputs and prices are validated again on the server.
- For company purchasing, select a native company/unit and configure its approval policy, employee permissions, catalogue and budget. These are shared B2B rules, not duplicated app settings. A buyer cannot approve their own request.
- Review the native cart and request approval. Approval binds the complete priced cart revision. Checkout rechecks the installed package, material revision and guest result before stock, order and spending commit together.
- Save the current cart as a private or shared company order list. The list stores product quantities and configuration inputs, not accepted old prices.
- Apply the list to a new permitted company cart. Current material/rule versions calculate a new price. Any necessary approval must be obtained for that cart.
- Under the installed app's data view, open configured purchases. Cards retain the original material label, dimensions, source-currency fee, package version and rule revision. Open the native order for fulfilment and documents.
The installed app data editor uses the shared content-language selector and
translation fields. Full regional codes such as de-DE and the configured main
language work without creating short-code duplicates or copying inherited text
into new translations. Read-only controls remain disabled. A failed purchase-
history page request keeps the current page and its navigation position.
Sandbox testing excludes real orders/provider effects. The existing staging review selects app package and material records separately. A live purchasing approval, customer, order or spending record is never published from a sandbox.
Actual local browser views
Dated workflow evidence: Local simulated order confirmation for EUR 517
These captures use synthetic local data and simulated payment. They do not show public deployment or an actual provider settlement. The standard product image and specifications remain catalogue data; this pattern does not generate a 3D render or rewrite product specifications from selected dimensions.
The rule and its frozen checks
The bundled package supports widths 80–400 cm and depths 40–200 cm. A width over 240 cm adds EUR 48 to the material surcharge. The native commerce engine converts the explicit source currency and applies its normal taxes, quantity pricing, promotions and checkout checks.
| Input | Material fee | Expected configuration fee |
|---|---|---|
| 240 × 80 cm | EUR 0 | EUR 0 |
| 241 × 80 cm | EUR 0 | EUR 48 |
| 240 × 80 cm | EUR 20 | EUR 20 |
| 260 × 80 cm | EUR 20 | EUR 68 |
| Width 401 cm | EUR 0 | Rejected |
| Width supplied as text | EUR 0 | Rejected |
| Caller supplies an undeclared price | EUR 0 | Rejected |
These synthetic cases execute through the same field validator and fuel/memory- bounded guest on immutable save, preview installation and publication. A changed rule with unchanged expected results fails at its example's JSON Pointer. Explicit new expectations require review; a model must not rewrite them merely to obtain a pass. Cases test their declared inputs, not every possible business situation.
For example, increasing the oversized-dimension surcharge to EUR 58 initially fails the frozen checks. After the intended examples are explicitly updated and the new version is reviewed/published, the saved 260 cm walnut configuration is recalculated under the new version. Its previous completed order remains unchanged.
Shared contracts and rights
Pattern version 1.0.1 adds the material library to the app's native AI context
and namespaced graph. The same authorized API/MCP list supplies current material
names and EUR-cent surcharges, with tenant, package version and record revision.
It creates no second knowledge store and does not turn a surcharge into a complete
product price or a confirmed product claim. The original 1.0.0 package is
retained inside the app's versions/ directory. Its upgrade is explicit and keeps
the existing material records; installed shops are never silently upgraded.
- Structured
configuration.inputsdeclares up to eight required integer, boolean or printable string fields and their existing field validation. An optional public library record supplies the fee. The guest accepts only declared integer/boolean arguments; it has no filesystem, network, clocks or host imports. - Existing engraving/message contracts retain their serialization and length argument. Structured contributions may declare an ISO source currency. Existing contracts without it keep their legacy pricing behavior.
- Public form, HTTP action and
app.<app-id>.configureMCP action use the same owner. Current cart capability, channel, company membership, CAS and terminal guards apply. MCP opt-out blocks discovery/direct MCP calls without disabling the ordinary form. Configure actions cannot run as background Flows. - Material writes use native app-record schema/CAS/history and current catalogue
rights. Purchased-configuration reads always need
orders.read, even if a package omits an action permission. No buyer PII or other app's configuration is included in this purchase projection. - The existing outbox emits
app.configuration.changedatomically with a changed cart configuration. Its minimized payload contains app/cart/product references, channel, revision and operation; it contains no cart token, free input text, customer identity or credentials. The native Rule/Flow Builder can react to it. - Selections are bounded; libraries and purchase histories use keyset pages. Fixed shared storage and bounded reads do not establish large-fleet throughput.
Acceptance and remaining work
The registered business_capability suite exercises actual material records,
structured field/ABI rejection, MCP configuration and opt-out, wrong-channel and
foreign-buyer denial, Flow completion, independent approval, native stock/order,
private input-only lists, UCP quote consistency, changed-material checkout denial,
current-price reorder, failed frozen examples, selected package release and old
order immutability. Existing app/component/B2B, currency, POS, manual-order and
checkout regressions remain required.
The workflow source lives with the app at
extensions/apps/furniture-configurator/tests/workflow.py; the registered host
script only invokes it. The extended local acceptance additionally checks an
original-package upgrade without losing material records, exact API/MCP/public
graph projections, and a completed second purchase after rule/material changes.
An old approval cannot authorize that reorder. A separate approver must approve
the new cart; replay creates neither a second order nor another stock deduction.
The first order keeps its original price, presentation and package snapshot.
These additional checks are local until new hosted evidence is recorded.
The full concept additionally requires general core-object extensions, native order/offer lifecycle extensions, historical whole-business replay, source build hosting, Crater compatibility operations, a demonstrated Shopware extension port and operated Enterprise cells. This app is a connected implementation case, not acceptance of those separate capabilities.