Skip to content

Architecture ​

Accepted architecture · 1 October 2026, option 2

Agentfy hosts the harness; Store Deputy API exposes the single MCP; the OpenCart module exposes a protected REST/JSON API. Store Deputy governs connections, actor/shopper context, permissions, approvals and audit without building another harness. Connect → login/register → secure pairing → automatic agent provisioning in Agentfy with Store Deputy MCP → return to the module. App contains teams, agents, account, billing and per-agent chat.

This replaces the earlier same-day direct-module-MCP design. Existing code and prototypes below do not implement the new integration. Shopper sessions and the real OpenCart cart have separate scoped bindings; cookies stay in the shop. See the accepted central MCP decision for boundaries, delivery stages and remaining contract work.

Status · 1 October 2026. Three of the five parts have code — the API, the app and a first draft of the website — and they run only on a developer's machine. The docs site is published. The admin panel is not built. No real store has been connected: everything described as built was exercised only against two local test shops.

Store Deputy is laid out as five parts in one repository — API, app, admin, website and docs — plus a small module installed in the shop. The founder named the five parts on 1 October 2026. The code follows CleanSlice, the architecture standard this project uses for NestJS and Nuxt applications. CleanSlice covers the API, the app and the admin panel; it does not describe a marketing website, a documentation site or PHP code, and those pages say so.

The parts ​

PartWhat it is forWho uses itBuilt withStatus
APIKnows the people, teams, roles and connected stores. The only part that talks to a shopThe app; later the admin panel and the agentsNestJS, Prisma, PostgreSQLFoundation built; runs locally
AppWhere a person signs in and confirms connecting a storeShop owners and their teamsNuxt, Vue 3, Pinia, TailwindSign-in, registration and connecting built; runs locally
AdminA panel for whoever operates Store Deputy itselfPlatform operatorsNuxt, if built as CleanSlice describesNot built; scope undecided
WebsiteThe marketing site: what a shop owner reads before deciding to try the productBuyersNuxt, Vue 3, TailwindFirst draft built: one page; runs locally
DocsInternal: research, decisions, specifications and design prototypesThe team and the agents working on the productVitePressPublished
Shop moduleInstalled in OpenCart. Carries out signed requests from the API and gives the owner Connect, Pause and DisconnectThe shop owner; the APIPHP 7.3+, OpenCart 3.0.3.5+Connecting built; run on local test shops only

The shop module is specified in REST 1.0 and is not repeated here.

How the parts talk ​

buyer ─────▶ website             marketing page; links to the app
owner ─────▶ app ──────┐         sign in, register, connect a store
operator ──▶ admin ────┤         not built
                       ▼
                      API ─────── PostgreSQL
                       │
                       │  Bridge Protocol v1: signed requests
                       ▼
               module in the shop (OpenCart 3)
  • The browser parts talk only to the API. The app's API client is generated from the API's own description of its routes, not written by hand.
  • Only the API talks to a shop. It does so through REST 1.0. The app never calls a shop.
  • Connecting a store crosses three parts. The owner presses Connect in the shop module and lands in the app with a one-time code. The app asks the API to connect. The API sends a signed request to the module, and the owner is returned to the module page they started from.

What CleanSlice asks of the code ​

CleanSlice combines two ideas. Code is grouped by feature, and inside each feature it is separated by responsibility.

  • A slice is one feature in one folder. Everything a feature needs lives together. Adding a feature means adding a folder; understanding one means reading one folder.
  • Three layers inside a slice. Presentation accepts input and shapes output: controllers and request shapes in the API, pages and components in a browser app. Domain holds the rules and the contracts for anything outside. Data fulfils those contracts by talking to the database or to another service.
  • Rules never depend on plumbing. The domain layer states what it needs as a contract, called a gateway. The data layer implements it. A rule such as "only an owner or an admin may connect a store" can be read and tested without a database or a network.
  • Setup slices and feature slices. Setup slices carry shared plumbing: the database connection, the error format, the theme, the API client. Feature slices carry the product.
  • Related slices share a namespace folder. Sign-in, teams and membership sit together under user/. The parent folder holds no code of its own.
  • Slices meet through their domain. One slice may use another's rules and types, never its data layer.
  • Names. Slice folders are singular (user, store); routes are plural (/teams).
  • A fixed stack. NestJS and Prisma for the API; Nuxt, Vue 3, Pinia and Tailwind for browser apps.
  • Four agreed phases. High-level plan, detailed plan, implementation, review — each agreed before the next, and the API before the app.

When sources disagree, the order in this repository is: CleanSlice, then the repository's agent guide, then existing code.

Where this repository departs from CleanSlice ​

CleanSliceHereWhy
The prisma-import package merges each slice's database schemaA small script of our own merges themRecorded reason: the package was last published in February 2024 for Prisma 4
An interceptor formats errorsA global exception filter formats themAn interceptor never sees an error thrown by the sign-in check, so "not signed in" would come back in a different shape
Its NestJS standard shows a controller calling a gateway; its layers page shows a controller calling a serviceController → service → gateway everywhereRole rules are business rules and belong in a service
The reference app includes a dependency-injection setup sliceThe app has noneNot needed yet. CleanSlice itself reserves it for slices that need mock or offline implementations
UI components generated by shadcn-vueFive hand-written components in the same styleDecided 29 September 2026. Return to shadcn-vue when dialogs, menus or tables are needed
Every component folder has a Provider.vueThe app's shared page-header folder has noneObserved on 1 October 2026; not a recorded decision

Local addresses ​

Everything below is a developer's machine. The product has no public address.

PartPortNote
App4140
Admin4141Reserved; nothing listens
API4142Interactive route description at /api
Test shops4143, 4144OpenCart 3.0.3.5 and 3.0.5.1
API database4145PostgreSQL in Docker
Docs4146Preview of a production build on 4147
Local dashboard4152Links, service status and logs for a developer; not part of the product
Website4148
  • API — the slices that exist, and one request followed through the layers.
  • App — what a person can do today and how the app is put together.
  • Admin — what is reserved and what must be decided before it is built.
  • Website — the marketing site: what is on it, how it is arranged and what to decide next.
  • Docs — how this site is arranged and why CleanSlice does not govern it.
  • Implementation proposal — the target design for catalog work, approvals and jobs, none of which is built.