NNO Docs
Architecture

Neutrino Platform

Documentation for Neutrino Platform

Date: 2026-03-30 Status: Agreed — Ready for Detailed Expansion Scope: Full platform architecture from meta-platform layer down to feature packages


1. Vision

Neutrino is a platform orchestration layer that allows clients to compose infrastructure-backed applications from a curated catalogue of feature packages — either predefined by Neutrino or authored by the client and submitted for review.

The key mental model:

Neutrino = Infrastructure provisioner + Feature package runtime + Multi-tenant shell + CLI toolchain

A client subscribes to Neutrino. Neutrino provisions their Cloudflare infrastructure and a managed code repository. The client's users interact with a console shell that statically bundles whatever feature packages the tenant has activated — auth, billing, analytics, or any NNO-built features.

Features can be activated individually (standalone) or grouped into Stacks — named, versioned collections of features that share a common set of Cloudflare resources (D1, R2, KV). Stacks are the preferred activation path for multi-feature applications. See stacks.md.


2. System Layers

┌────────────────────────────────────────────────────────────────────────────┐
│  Layer 0: Neutrino Core (NNO)                                              │
│  The meta-platform. Neutrino itself, deployed on its own Cloudflare infra. │
│  Manages all downstream platforms. Shares the same CF account (Phase 1).  │
└───────────────────────────────────┬────────────────────────────────────────┘
                                    │ provisions & manages
┌───────────────────────────────────▼────────────────────────────────────────┐
│  Layer 1: Platform                                                         │
│  A client's top-level environment. One platform = one client/product.      │
│  Resources co-hosted on NNO's Cloudflare account, isolated by naming.      │
└───────────────────────────────────┬────────────────────────────────────────┘
                                    │ partitions into
┌───────────────────────────────────▼────────────────────────────────────────┐
│  Layer 2: Tenant / Sub-Tenant                                              │
│  Logical isolation within a platform. Can be a business unit, region,      │
│  customer, or team. Sub-tenants nest under tenants.                        │
│  Each gets its own provisioned resource set.                               │
└───────────────────────────────────┬────────────────────────────────────────┘
                                    │ runs
┌───────────────────────────────────▼────────────────────────────────────────┐
│  Layer 3: Console Shell                                                    │
│  Thin React shell. Statically bundles activated feature packages at build. │
│  Deployed to Cloudflare Pages. Rebuilt by CF Pages on every repo change.  │
└───────────────────────────────────┬────────────────────────────────────────┘
                                    │ composed of
┌───────────────────────────────────▼────────────────────────────────────────┐
│  Layer 4: Feature Packages & Stacks                                        │
│  Feature packages authored by NNO.                                         │
│  Each package = UI + optional backend Worker + optional storage.           │
│  Stacks group features into cohesive applications sharing CF resources.    │
│  See stacks.md for full Stack architecture.                                │
└────────────────────────────────────────────────────────────────────────────┘

3. Layer 0 — Neutrino Core (NNO)

Neutrino itself is deployed on Cloudflare using the same naming convention it enforces for clients:

nno-{nno-platform-id}-{service}[-stg]

Suffix convention: no suffix for production, -stg for staging. Example: nno-k3m9p2xw7q-registry (prod), nno-k3m9p2xw7q-registry-stg (staging).

\{nno-platform-id\} = k3m9p2xw7q — this is the fixed NanoID assigned to the Neutrino meta-platform itself. All NNO Core resource names resolve to the prefix nno-k3m9p2xw7q-. Example: nno-k3m9p2xw7q-registry-stg.

Cloudflare Account Model

Phase 1 (current): NNO Core and all client platform resources share the same Cloudflare account. Isolation is enforced entirely through the naming convention (\{platform-id\}-\{stack-id\}-...). This keeps operational complexity low while the platform is being established.

Phase 2 (future): Migrate to per-client Cloudflare accounts (BYOC — see Section 4) once account-level isolation is required for enterprise compliance.

NNO Core Services

┌────────────────────────────────────────────────────────────────────┐
│                         NNO CORE                                   │
│                                                                    │
│  ┌──────────────┐  ┌──────────────────────────────────────────┐   │
│  │   Gateway    │  │  Zero (backoffice + tenant mgmt)         │   │
│  │ (Hono Worker)│  │  (@neutrino-io/feature-zero — separate    │   │
│  └──────┬───────┘  │   repo: nno-app-zero, CF Pages app)      │   │
│         │          └──────────────────────────────────────────┘   │
│  ┌──────▼─────────────────────────────────────────────────────┐   │
│  │                  NNO Internal Services                      │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │   │
│  │  │ Registry │ │   IAM    │ │Provision │ │   Billing    │  │   │
│  │  │ Service  │ │ Service  │ │ Service  │ │   Service    │  │   │
│  │  └────┬─────┘ └──────────┘ └──────────┘ └──────────────┘  │   │
│  │                                                             │   │
│  │  ┌───────────────────────┐ ┌──────────────────────────┐    │   │
│  │  │ Stack Registry Service│ │ CLI Service (repo+builds) │    │   │
│  │  └───────────────────────┘ └──────────────────────────┘    │   │
│  └─────────────────────────────────────────────────────────────┘   │
│         │                                                          │
│  ┌──────▼──────────────────────────────────────────────────────┐  │
│  │         NNO Registry D1 (source of truth)                   │  │
│  │  platforms · tenants · resources · features · billing       │  │
│  └─────────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────────┘
NNO ServiceResponsibility
GatewaySingle API entry point. Routes to internal services. Auth via NNO IAM. Full middleware pipeline (9 registrations: rate limiting, security, tracing, and more) with service-to-service JWT auth via ServiceTokenCache. See gateway.md.
RegistrySource of truth: all platforms, tenants, sub-tenants, resources, active features
IAMIdentity and access for NNO itself. Issues API keys per platform.
Auth Service (Template)Per-platform auth worker template (services/auth/). Not an NNO-operated service — deployed by CLI Service during platform onboarding. See services/auth.md
ProvisioningCalls Cloudflare API to create Workers, Pages, D1, R2, KV resources (Phase 1). Queue provisioning planned for Phase 2.
Stack RegistryVersioned catalogue of NNO-authored Stack templates. NNO operators publish stack definitions; platform admins activate them. No submission or review pipeline — NNO-only authorship. See stack-registry.md
BillingUnified service: per-platform Stripe billing (subscriptions, payments) + NNO-level usage metering, quota enforcement, and invoicing
CLI ServiceManages per-platform GitHub repos. Applies feature config changes, triggers CF Pages builds

3.1 Gateway Detail

Routes all API traffic to internal NNO services. Routing table, auth middleware, CORS, health endpoint, resilience, and service bindings are documented in gateway.md.


4. Layer 1–2 — Platform & Tenant

Provisioning Model

Phase 1 — Full Control (current)

NNO owns and operates the Cloudflare account. When a client onboards:

  • NNO creates all Cloudflare resources (Workers, Pages, D1, R2, KV) via the CF API
  • NNO holds the CF_API_TOKEN and CF_ACCOUNT_ID
  • Client interacts only with NNO Portal and their console URL
  • Resources are named using the NNO convention and tracked in the Registry

Phase 2 — BYOC (future)

Client provides their own Cloudflare account credentials:

  • Client generates a scoped CF_API_TOKEN from their own account
  • NNO Provisioning deploys into the client's account using their token
  • NNO Registry still tracks all resources (reference only, not ownership)
  • Client retains full Cloudflare account sovereignty
  • Required for enterprise compliance, data residency, or cost ownership requirements

Per-Stack Resource Set

[Updated for DNS architecture] Resources are now organised by Stack rather than by individual tenant entity. The entity hierarchy is Platform → Tenant → Stack → apps + services.

Every stack provisioned for a platform gets a corresponding set of Cloudflare resources:

{platform-id}-default-auth           ← Auth Worker          (default stack, always provisioned)
{platform-id}-default-auth-db        ← Auth D1 Database     (default stack, always provisioned)
{platform-id}-{stack-id}-db          ← Shared D1            (per stack, if sharedD1: true)
{platform-id}-{stack-id}-storage     ← Shared R2            (per stack, if sharedR2: true)
{platform-id}-{stack-id}-kv          ← Shared KV            (per stack, if sharedKV: true)
{platform-id}-{stack-id}-{name}      ← App/service Worker   (per app or service in stack)

Staging variants append -stg (e.g. \{platform-id\}-default-auth-stg). Production resources carry no environment suffix.

Each resource is tracked in the NNO Registry with its CF resource ID, status, and config.

Stack Resource Independence

Platform: k3m9p2xw7q (AcmeCorp)

  Default stack (auth, auto-created):
  ├─ k3m9p2xw7q-default-auth            ← Auth Worker (prod)
  └─ k3m9p2xw7q-default-auth-db         ← Auth D1 (prod)

  Stack x7y8z9w0q1 (Marketing):
  ├─ k3m9p2xw7q-x7y8z9w0q1-dashboard    ← Pages app (prod)
  ├─ k3m9p2xw7q-x7y8z9w0q1-db           ← Shared D1 (prod)
  └─ k3m9p2xw7q-x7y8z9w0q1-kv           ← Shared KV (prod)

  Stack r4s5t6u7v8 (Analytics Pro):
  ├─ k3m9p2xw7q-r4s5t6u7v8-analytics    ← Worker (prod)
  ├─ k3m9p2xw7q-r4s5t6u7v8-db           ← Shared D1 (prod)
  └─ k3m9p2xw7q-r4s5t6u7v8-storage      ← Shared R2 (prod)

The Platform → Tenant → Stack entity hierarchy is tracked in the NNO Registry. Resource names encode only platform-id and stack-id — the full hierarchy lives in the registry, not in the resource name.


5. Layer 3 — Console Shell

The current apps/console is the Neutrino shell application. It already contains a feature registry pattern; this architecture formalises and extends it.

Shell Responsibilities

┌────────────────────────────────────────────────────────────────────┐
│  CONSOLE SHELL                                                     │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐ │
│  │  Chrome Layer                                                │ │
│  │  Sidebar · Header · Theme · Search · Notifications          │ │
│  └──────────────────────────────────────────────────────────────┘ │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐ │
│  │  Feature Runtime                                             │ │
│  │  Feature Registry → Route Generator → Sidebar Generator     │ │
│  │  Permission Gate → Feature Loader → Context Injector        │ │
│  │  (Registry resolves FeatureDefinition.navigation[] for      │ │
│  │   collapsible sub-menus; resolves icon strings to lucide)   │ │
│  └──────────────────────────────────────────────────────────────┘ │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐ │
│  │  Foundation                                                  │ │
│  │  Auth Gate · TanStack Router · TanStack Query · Providers   │ │
│  └──────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
         │                   │                   │
         ▼                   ▼                   ▼
   Feature Pkg A       Feature Pkg B       Feature Pkg C
   (static import)     (static import)     (static import)

What the Shell Does NOT Do

  • It does not contain business logic
  • It does not know what features exist until they register
  • It does not decide which features load — the tenant's feature manifest (baked in at build time from NNO Registry) decides

Shell Configuration Source (Current — Auto-Discovery + Static Build)

At build time:
1. Vite neutrino-feature-discovery plugin scans installed @neutrino-io/feature-* packages
2. Generates virtual:feature-registry module with static imports + manifests
3. features.config.ts merges: auto-discovered manifests + local features + overrides
   (NNO CLI Service may also update features.config.ts and package.json — Phase 2)
4. Vite bundles all discovered feature packages statically

At runtime:
1. Shell boots with the statically bundled feature set
2. Authenticates the user via auth service
3. Reads embedded feature manifest → activates registered features
4. Generates routes and sidebar dynamically from registered features
5. Renders the app

6. Layer 4 — Feature Packages

The Feature Package Contract

Every feature package — Type 1, 2, or 3 — must export a FeatureDefinition:

// features/[name]/src/feature.ts

export interface FeatureDefinition {
  // Identity
  id: string; // unique slug, e.g. 'analytics'
  version: string; // semver
  displayName: string;
  description: string; // short description shown in marketplace / help
  icon?: string; // lucide icon name (optional)

  // Shell Integration
  routes: FeatureRoute[]; // TanStack Router route definitions
  navigation: FeatureNavItem[]; // sidebar entries this feature contributes
  permissions: FeaturePermission[]; // required permissions, e.g. ['analytics:read']

  // Backend
  serviceEnvKey?: string; // env var name for service URL, e.g. 'VITE_ANALYTICS_API_URL'
  requiresService?: boolean; // false = UI-only feature

  // Lifecycle (optional)
  onRegister?: (shell: ShellContext) => void;
  onActivate?: (shell: ShellContext) => void;
  onDeactivate?: (shell: ShellContext) => void;
  providers?: FeatureProvider[]; // context providers to inject at shell level
}

Contract source: @neutrino-io/sdk/feature — the single source of truth for FeatureDefinition, FeatureRoute, FeatureNavItem, FeaturePermission, FeatureProvider, and ShellContext.

Package Types

┌─────────────────────────────────────────────────────────────────────┐
│  TYPE 1: Core Packages (NNO-maintained, always present)             │
│  @neutrino-io/feature-settings · @neutrino-io/ui-auth* · ...              │
│  Stable API. Versioned. Bundled into every platform shell.          │
│  * @neutrino-io/ui-auth is a UI library that exports authFeatureDefinition;  │
│    it is not a pluggable feature package like the features/ packages │
├─────────────────────────────────────────────────────────────────────┤
│  TYPE 2: Domain Packages (NNO-maintained, selectable)               │
│  @neutrino-io/feature-billing · @neutrino-io/feature-stacks · ...         │
│  Activatable per tenant via NNO Portal. Maps to a backend Worker.   │
│  Maintained and versioned by NNO.                                   │
├─────────────────────────────────────────────────────────────────────┤
├─────────────────────────────────────────────────────────────────────┤
│  TYPE 3: Client Packages (client-authored, curated)                 │
│  @acme/feature-dashboard · @acme/feature-inventory · ...            │
│  Developed using NNO CLI + @neutrino-io/sdk. Submitted for NNO review  │
│  before listing. Private to the submitting platform by default.     │
└─────────────────────────────────────────────────────────────────────┘

No open marketplace. All feature packages — including client-authored ones — go through NNO review before they can be activated on any platform. This ensures quality, security, and compatibility with the shell contract.

Feature Package Location

All activatable feature packages live in the features/ workspace (features/*), separate from shared libraries in packages/. Each feature package:

  • Exports a FeatureDefinition (typically from src/feature.ts) — runtime contract
  • Exports a featureManifest (from src/index.ts) — build-time discovery metadata
  • Declares "neutrino": \{"type": "feature"\} in its package.json to opt in to auto-discovery
  • Uses dts: false in tsup (not statically imported by TypeScript consumers)
  • Is automatically registered via the Vite neutrino-feature-discovery plugin — no manual entry in features.config.ts needed
PackageTypeLocationStatus
@neutrino-io/feature-settingsType 1features/settings/✅ Built, wired in shell
@neutrino-io/feature-billingType 2features/billing/✅ Built, registered with enabled: false
@neutrino-io/feature-stacksType 2features/stacks/🔧 Planned

Feature Auto-Discovery

Feature packages are auto-discovered at build time by the Vite neutrino-feature-discovery plugin. Packages following the @neutrino-io/feature-* convention with a "neutrino": \{"type": "feature"\} marker in their package.json are automatically imported and registered — no manual configuration needed. The shell can override any auto-discovered defaults via features.overrides.ts.

The discovery pipeline runs during Vite's configResolved phase:

pnpm add @neutrino-io/feature-billing


Vite plugin scans apps/console/package.json
  → finds @neutrino-io/feature-billing
  → reads its package.json: neutrino.type === "feature" ✓


Generates virtual:feature-registry
  → static import * as _f0 from '@neutrino-io/feature-billing'
  → exports discoveredManifests array


features.config.ts merges:
  1. Auto-discovered manifests (from virtual module)
  2. Console-local features (home, help, error pages)
  3. Shell overrides (features.overrides.ts)


FeatureRegistry boots with complete feature set

See Shell Feature Config — Auto-Discovery for the full specification, including the FeatureManifest type and override authority model.

Feature ↔ Service Mapping

Each feature package that requires a backend maps 1:1 to a Cloudflare Worker:

Feature PackageWorker Service (prod)D1 Database (prod)Notes
@neutrino-io/ui-auth\{pid\}-default-auth\{pid\}-default-auth-dbAlways required, default stack
@neutrino-io/feature-settings(none)UI-only, reads from auth
@neutrino-io/feature-billing\{pid\}-\{stackId\}-billingshared stack D1 or dedicatedOptional
Client custom app/service\{pid\}-\{stackId\}-\{name\}\{pid\}-\{stackId\}-db (shared)Provisioned on activation

7. Development & Deployment Model

Each client platform is deployed via a dedicated NNO-managed GitHub repository created from the nno-stack-starter template. Feature activation triggers the NNO CLI Service to commit features.config.ts to the platform repo. A GitHub Actions workflow in the repo (inherited from nno-stack-starter) runs wrangler pages deploy to CF Pages on every push — the same pattern used by the NNO operator console. Phase 2 will evolve this to Remote Module Federation for hot-swappable features without shell rebuilds.

Phase 1 deployment detail and roadmap: System Architecture Phase 1 Plan.

NNO CLI Toolchain

The NNO CLI (nno) is the universal command-line interface for the Neutrino platform. It uses a namespaced architecture — nno <namespace> <command> — so capabilities can be added incrementally without breaking existing commands.

nno project   ← local dev, build, deploy for a platform project  (P1)
nno feature   ← scaffold, develop, validate, submit feature packages (P1)
nno marketplace ← browse catalogue, manage submissions (P1)
nno platform  ← platform provisioning and management (P2)
nno ops       ← NNO operator tooling (P2)

Project workflow (platform developers):

# Start local dev — validates config, applies migrations, starts all services
nno project dev

# Build console shell for staging
nno project build --env stg

# Validate config + secrets before deploying
nno project check --env stg

# Full deploy: check → build → wrangler deploy → migrations → pages deploy
nno project deploy --env stg
nno project deploy --env prod

Feature package workflow (feature developers):

# Scaffold a new feature package
nno feature init my-feature

# Start local dev with mock NNO shell
nno feature dev

# Validate FeatureDefinition contract
nno feature validate

# Submit to NNO Marketplace for review
nno feature submit --message "Initial submission"

# (NNO admin) Approve and list
nno marketplace approve sub_9x2m4k7p1q

Provisional design — subject to revision. nno feature submit and the full marketplace submission/review pipeline are Phase 2 capabilities, contingent on lifting the NNO-only authorship restriction (see Q4 in the Architecture Decisions Log, Section 13). Phase 1 supports only NNO-authored feature packages.

Feature development flow:

nno feature init my-feature
         │ scaffolds package using feature-sdk template

nno feature dev
  → mock shell + feature Vite dev + local Wrangler service


nno feature validate
  → checks FeatureDefinition contract (V01–V20)
  → checks service binding config
  → checks permission declarations


(Phase 2) nno feature submit
  → packages and uploads to NNO Stack Registry review queue
  → NNO team reviews (security, contract compliance, quality)


(Phase 2) nno marketplace approve (NNO admin action)
  → lists package in Stack Registry
  → available for activation on eligible platforms

8. End-to-End Data Flow

Client Onboarding Flow

Phase 2 adds self-serve onboarding: user registers → email verification → onboarding wizard (stack selection, tier, billing setup) → automated ONBOARD_PLATFORM job → real-time progress tracking → platform active.

Client signs up on NNO Portal


NNO IAM creates platform record
  → generates platform NanoID (10 chars)
  → generates default tenant NanoID
  → Platform created in 'pending' status (awaiting email verification and billing setup)


User completes onboarding wizard (email verification, stack selection, billing setup)
NNO Provisioning runs ONBOARD_PLATFORM job:
  → creates platform + entity records in Registry
  → creates Stripe customer + subscription in Billing
  → enqueues BOOTSTRAP_PLATFORM job for CF resource creation
  → Platform transitions to 'provisioning' status while CF resources are created


NNO Provisioning (BOOTSTRAP_PLATFORM) creates Cloudflare resources
  → deploys auth Worker (k3m9p2xw7q-default-auth)
  → creates auth D1 (k3m9p2xw7q-default-auth-db)
  → connects CF Pages project for console app
  → runs auth migrations, sets secrets
  → registers DNS hostname (auth.svc.default.k3m9p2xw7q.nno.app) via CF4SaaS
  → Platform transitions to 'active' status. The client can now access their platform console.


NNO CLI Service creates platform repo
  → creates nno-platform-k3m9p2xw7q in NNO GitHub org
  → configures with Core packages (auth, settings)
  → triggers initial CF Pages build


NNO Registry records all provisioned resources + active features


Client accesses their console at:
  https://<name>.app.default.<platformId>.nno.app          (NNO-assigned DNS hostname via CF4SaaS)
  https://app.acmecorp.com                                 (optional custom domain via CF4SaaS)

Feature Activation Flow

Admin activates a feature (e.g. 'analytics') via NNO Portal


NNO Registry validates feature exists in the NNO feature catalogue and is compatible with the platform's plan


NNO Provisioning creates:
  → analytics Worker  (k3m9p2xw7q-x7y8z9w0q1-analytics)
  → analytics D1      (k3m9p2xw7q-x7y8z9w0q1-analytics-db)
  → runs analytics migrations, sets secrets


NNO CLI Service updates platform repo:
  → adds @neutrino-io/feature-{feature} to package.json
  → updates features.config.ts
  → commits and pushes


GitHub Actions deploy workflow triggers → wrangler pages deploy → updated shell live
  → analytics routes and navigation are now bundled in the shell

Runtime Request Flow

User opens a feature page in console


Console Shell (CF Pages)
  → TanStack Router matches route registered by the feature package
  → Renders feature page component


Page makes API call to the feature Worker
  → Authorization header: Better Auth JWT
  → URL resolved from VITE_{FEATURE}_API_URL (set in CF Pages env vars)


Feature Worker (CF Workers)
  → Validates JWT via auth service
  → Queries its own D1 database
  → Returns response

9. Billing Model

Neutrino uses a hybrid model: a flat base tier covers infrastructure and platform access, with usage-based charges for overages.

Tiers

TierMonthly BaseIncluded ResourcesTypical Use Case
StarterFixed flat fee1 platform, 2 tenants, 3 features, limited invocations + storageEarly-stage / evaluation
GrowthMid flat fee3 platforms, 10 tenants, unlimited features, moderate usageGrowing product
ScaleHigher flat feeUnlimited platforms + tenants, priority support, audit logsEnterprise

Usage Overages (above tier limits)

MetricUnitMeasured Via
Worker invocationsPer millionCloudflare Analytics Engine
D1 read operationsPer million rowsCloudflare D1 usage metrics
D1 write operationsPer million rowsCloudflare D1 usage metrics
R2 storagePer GB/monthCloudflare R2 metrics
R2 operationsPer millionCloudflare R2 metrics
KV readsPer millionCloudflare KV metrics

Metering Architecture

CF Analytics Engine / Cloudflare API
         │ usage data (polling or push)

NNO Billing Service
  → aggregates usage per platform-id + stack-id
  → stores daily snapshots in billing D1
  → runs monthly invoice generation
  → marks tier upgrades when thresholds are crossed


NNO Portal → Billing dashboard (usage charts, invoices, upgrade prompts)

Phase 1: Manual invoice generation + Stripe. Phase 2: Automated metering with real-time usage dashboard and auto-upgrade suggestions.


10. Existing Codebase Mapping

Implementation status and gap tracking: System Architecture Phase 1 Plan.


11. Repository Structure (Target)

nno-app-builder/            ← NNO core monorepo
├── apps/
│   └── console/            ← Reference shell (used as template for platform repos)
│                              NNO operator console = console shell + role-gated routes

├── packages/
│   ├── sdk/                ← @neutrino-io/sdk — FeatureDefinition contract + shared utils/hooks/types
│   │                          (merged from ui-shared + feature-sdk)
│   │                          subpaths: ./feature · ./utils · ./hooks · ./hooks/auth · ./types · ./constants
│   ├── ui-core/            ← @neutrino-io/ui-core — Layer 1: base components (Radix, Shadcn, Recharts)
│   ├── ui-auth/            ← @neutrino-io/ui-auth — auth providers, guards, hooks, Better Auth integration
│   ├── core/               ← @neutrino-io/core — naming, types, constants
│   │                          subpaths: ./naming · ./types · ./constants
│   └── cli/                ← @neutrino-io/cli — single binary + NnoPlugin registry
│                              subpaths: . (bin) · ./plugin (external plugin authoring)

├── features/               ← Activatable feature packages (dynamically loaded by the shell)
│   ├── settings/           ← @neutrino-io/feature-settings — Type 1: always-present settings UI
│   ├── billing/            ← @neutrino-io/feature-billing — Type 2: per-tenant billing UI

├── services/
│   ├── iam/                ← NNO IAM Worker: auth-core + /api/nno/session (global)
│   ├── auth/               ← Auth Worker (thin per-platform wrapper; imports @neutrino-io/service-iam/core)
│   ├── billing/            ← Billing Worker: per-platform Stripe + NNO-level metering/invoicing
│   ├── registry/           ← NNO Registry Worker: source of truth (platforms, tenants, resources, features)
│   ├── gateway/            ← NNO API Gateway Worker: stateless proxy + auth enforcement
│   ├── provisioning/       ← NNO Provisioning Worker: CF resource job state machine
│   ├── stack-registry/     ← NNO Stack Registry Worker: NNO-authored stack template catalogue (no submissions/review)
│   └── cli/                ← NNO CLI Service (directory: cli/, worker name: nno-{platformId}-cli-service-{env})

├── tooling/
│   ├── github/
│   └── tsconfig/

└── docs/
    └── architecture/
        ├── overview.md          ← this document
        ├── README.md
        ├── concepts/
        │   ├── feature-sdk.md          ← Feature Package SDK spec
        │   ├── stacks.md               ← Stack architecture
        │   ├── cli.md                  ← NNO CLI spec
        │   ├── shell-config.md         ← Shell feature config & auto-discovery
        │   └── module-federation.md    ← Module Federation (Phase 2 stub)
        ├── services/
        │   ├── auth.md                 ← Multi-tenant auth model
        │   ├── billing.md              ← Billing & metering spec
        │   ├── cli-service.md          ← CLI Service spec
        │   ├── gateway.md              ← Gateway routing, auth, resilience
        │   ├── provisioning.md         ← NNO Provisioning state machine
        │   ├── registry.md             ← NNO Registry schema & API
        │   └── stack-registry.md       ← Stack Registry (was marketplace.md)
        ├── cross-cutting/
        │   ├── cloudflare-naming.md    ← naming convention
        │   └── observability.md        ← Observability spec (future design)
        ├── operator/
        │   └── zero.md                 ← NNO operator backoffice (Zero) — see nno-app-zero repo
        └── decisions/

Per-stack repos (managed by NNO, separate GitHub repos):

nno-stack-{stack-id}/           ← generated from nno-stack-starter template
├── src/
│   └── config/
│       └── features.config.ts  ← managed by NNO CLI Service
├── package.json                ← managed by NNO CLI Service
└── wrangler.toml               ← CF Pages project config

12. Technology Decisions

ConcernTechnologyRationale
Shell FrameworkReact 19 + ViteCurrent, performant, strong ecosystem
RoutingTanStack RouterType-safe, file-based + programmatic; feature registry already uses it
Server StateTanStack QueryAlready established; features bring their own queries
Service FrameworkHono.js on CF WorkersLightweight, CF-native, already in use
DatabaseCloudflare D1 (raw D1 API for most services; Drizzle ORM in services/iam and services/registry)Edge-native, zero cold starts; already in use
AuthBetter AuthMulti-provider, CF Workers compatible; already in use
ID GenerationNanoID (10 chars, [a-z0-9])CF-safe alphabet, collision-resistant (see naming doc)
Type SafetyTypeScript + ZodEnd-to-end; existing standard
Feature Loading (Phase 1)Static bundling via ViteSimple, fast, no runtime complexity
Feature Loading (Phase 2)Vite Plugin FederationModule Federation for hot-swappable remote packages
Platform Repo HostingGitHub (NNO org)neutrino-io org; repos created from nno-stack-starter template
Shell CI/CDGitHub Actions → wrangler pages deploy → CF PagesSame pattern as apps/console; org-level CF_API_TOKEN secret inherited by all platform repos; no CF dashboard OAuth per project

13. Architecture Decisions Log

#QuestionDecisionPhase
Q1Feature loading modelStatic bundling now. NNO CLI manages platform repos; CF Pages builds on push. Remote Module Federation in a future phase.P1 now, P2 future
Q2NNO hostingSame Cloudflare account as client platforms. Isolation via naming convention only. Separate accounts considered for Phase 2.P1
Q3Provisioning scopeFull control — NNO manages the CF account and holds credentials. BYOC (client-owned CF account) is a future phase for enterprise.P1 now, P2 future
Q4Feature authorship modelNNO-only. All feature packages are NNO-authored. No client-submitted feature packages. Platform clients activate NNO features via standalone activation or Stack templates.P1
Q5Billing modelHybrid. Flat monthly base tier per platform + usage-based overages for Workers, D1, R2, KV. Metered via Cloudflare Analytics Engine.P1
Q6Feature registration mechanismAuto-discovery via Vite plugin (Phase 1.5). Feature packages opt in by declaring "neutrino": \{"type": "feature"\} in package.json and exporting featureManifest. The shell retains full override authority via features.overrides.ts. Manual registration in features.config.ts is no longer required for @neutrino-io/feature-* packages.P1.5

14. NNO API Conventions

Error Response Envelope

All NNO services return errors in a single canonical JSON shape. This format applies to every Hono Worker in the NNO stack (Gateway, Registry, IAM, Provisioning, Billing, CLI Service, Stack Registry).

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Platform not found",
    "details": { "platformId": "k3m9p2xw7q" },
    "requestId": "req_abc123xyz"
  }
}
FieldTypeRequiredDescription
codestringMachine-readable error identifier. Use SCREAMING_SNAKE_CASE.
messagestringHuman-readable description. Safe to surface to API consumers.
detailsRecord<string, unknown>optionalStructured context (field names, IDs, limits) — aids debugging.
requestIdstringoptionalEchoes the x-request-id / requestId assigned by the request logger.

Enforcement: A Zod schema NnoErrorEnvelopeSchema and an ErrorCode enum are exported from @neutrino-io/core/errors. Import these when building response helpers or writing integration tests.

import {
  NnoErrorEnvelopeSchema,
  ErrorCode,
  makeErrorEnvelope,
} from "@neutrino-io/core/errors";

// Build a compliant error response in a Hono handler
return c.json(
  makeErrorEnvelope(ErrorCode.NOT_FOUND, "Platform not found", {
    details: { platformId },
    requestId: c.get("requestId"),
  }),
  404,
);

Common codes (full enum in @neutrino-io/core/errors):

CodeHTTPWhen
UNAUTHORIZED401Missing or invalid auth credentials
FORBIDDEN403Authenticated but lacks permission
NOT_FOUND404Resource does not exist
VALIDATION_ERROR422Zod / input validation failed
CONFLICT409Duplicate key, state conflict
RATE_LIMITED429Rate limit exceeded
INTERNAL_ERROR500Unhandled server error

Service-specific codes (e.g. JOB_NOT_FOUND, STRIPE_ERROR, QUOTA_EXCEEDED) are defined in each service's own constants but must still be returned inside the same \{ error: \{ code, message, ... \} \} envelope.


15. Areas for Detailed Expansion

Roadmap and expansion areas: System Architecture Phase 1 Plan.


Status: Agreed — architecture decisions locked, detailed expansion in progress For implementation phase tracking, see Implementation Plans. Document Owner: Neutrino Platform Team

On this page