Skip to main content

Code Structure And Layer Model designed

This page explains how the codebase is supposed to be read and extended. The goal is simple: engineers should know where a change belongs before they start editing.

The Three Core Code Layers

Layer rule

  • shared is technical plumbing.
  • platform owns reusable business authority.
  • products own customer-facing domain semantics.

What Lives In Each Layer

packages/shared

Use this layer for boring technical primitives:

  • error envelopes;
  • middleware;
  • event helpers;
  • outbox primitives;
  • DB helpers;
  • PKI interfaces;
  • generated transport artifacts;
  • storage/path/read-cache utilities.

Do not put product policy, billing rules, IAM semantics, or registry logic here.

packages/platform

Use this layer for reusable platform authority:

  • IAM / access;
  • billing / metering / payments;
  • audit / evidence;
  • status / ops posture;
  • notification;
  • registry / artifacts;
  • secrets / PKI coordination;
  • policy / entitlements.

If a second product should consume the capability without copying business logic, it probably belongs here.

packages/products

Use this layer for product-owned domain behavior:

  • GPU inventory and SKUs;
  • allocations and provisioning;
  • terminal runtime behavior;
  • product storage surfaces;
  • app catalog and runtime;
  • Token Factory product behavior.

Products compose platform services. They do not own the platform's reusable IAM, billing, audit, or policy truth.

Repo Shape

cmd/ entrypoints and thin route/binary wiring
packages/shared/ technical primitives only
packages/platform/ shared platform business domains
packages/products/ product-owned business domains
doc/api/ contract-first REST and event authority
doc/architecture/ deeper design packets and ownership maps
scripts/ci/ portable validation gates
scripts/ops/ operational harnesses and controlled runbook helpers
packages/web/ Next.js product UI
packages/docs/ Docusaurus documentation portal

Binary And Runtime Layers

LayerCurrent shapeWhat belongs there
Public control planecmd/apiPublic/admin HTTP routes, auth/session validation, thin handler wiring
Background workerscmd/billing-worker, cmd/provisioning-worker, cmd/webhook-worker, cmd/notification-relay, cmd/outbox-relayAsynchronous domain reactions and scheduled work
Edge runtime supportcmd/terminal-gatewayDedicated runtime path for terminal sessions
Node runtimecmd/node-agentPull-based host-side execution under typed task contracts
User/operator CLIcmd/gpuaas-cliContract-first control client, not hidden admin backdoor

Route Ownership Model

Route files in cmd/api are still the public API shell, but business logic should move into the owning domain package.

Examples:

  • routes_platform_* for reusable platform capabilities;
  • routes_gpuaas_* for GPUaaS product behavior;
  • routes_appplatform_* for app platform behavior;
  • routes_tokenfactory_* for Token Factory behavior.

Rule

cmd/api should become thinner over time. It is wiring and HTTP surface, not the long-term owner of domain behavior.

Data Ownership Model

Schema ownership follows the same split:

  • IAM/access tables are platform-owned;
  • billing/ledger tables are platform-owned;
  • allocation/node/runtime tables are GPUaaS-owned;
  • app runtime/catalog tables are app-platform-owned.

If two domains need the same data, the answer is read models, APIs, or events. The answer is not casual cross-domain joins.

How To Decide Where A Change Belongs

If the change is about...Start in...Why
Auth, membership, service accounts, scopes, tenant/project authoritypackages/platform/iamshared access authority
Ledger, metering, payment state, financial attributionpackages/platform/billing or packages/platform/paymentsreusable money system
Audit trail, evidence bundles, release posturepackages/platform/audit, packages/platform/evidence, packages/platform/statusopsreusable control-plane governance
GPU capacity, allocations, terminal, node lifecyclepackages/products/gpuaas/*product-owned runtime behavior
App manifests, app instances, SDK/runtime adapterspackages/products/appplatform/*product-owned app surface
General middleware, error helpers, outbox, eventspackages/shared/*technical primitive, not business owner

What This Means For Engineers

Before editing code, an engineer should be able to answer:

  1. Which contract changes first?
  2. Which route family owns the surface?
  3. Which package owns the business decision?
  4. Which table family owns the data?
  5. Which worker or async path consumes the change?

If those answers point to more than one owner, the change probably needs a platform/product boundary decision first.

Common Mistakes To Avoid

  • putting policy or IAM semantics in shared;
  • letting product code query platform-owned tables directly;
  • hiding business logic inside cmd/api handlers;
  • adding a new product-specific copy of billing, audit, or notification logic;
  • treating deployment separation as the first architecture move instead of ownership separation.

Deployment View

The near-term target is still a modular monolith plus workers, not forced microservices.

The architecture rule is:

separate ownership before separating deployment.

That keeps the repo easy to reshape while contracts, guards, and read models are still stabilizing.