Prox OS Internal Docs
PlatformArchitectureRepo

Package Boundaries

Package boundaries are enforced through three signals:

Package boundaries are enforced through three signals:

  1. Directory taxonomy under packages/<layer>/<package>.
  2. Nx project tags stored in package manifests.
  3. dependency-cruiser rules in .dependency-cruiser.js.

The goal is not paperwork. The goal is to keep browser bundles free of server implementation, keep contracts implementation-neutral, and make future AI agents choose the right package boundary before writing code.

Nx Tags

Each workspace package should carry tags in package.json:

{
  "nx": {
    "tags": ["layer:feature", "runtime:browser", "scope:os"]
  },
  "proxos": {
    "layer": "feature",
    "runtime": "browser",
    "category": "features",
    "importableBy": ["runtime", "app-package", "app"]
  }
}

Layer Tags

  • layer:ui
  • layer:feature
  • layer:contract
  • layer:runtime
  • layer:studio-engine
  • layer:data
  • layer:backend
  • layer:devtool
  • layer:app-package

Runtime Tags

  • runtime:browser for packages that may ship to the browser.
  • runtime:server for Node/Workers/backend-only packages.
  • runtime:shared for serializable contracts and safe shared helpers.
  • runtime:tooling for repo tools and generator packages.

Scope Tags

Scopes describe the product area, not the runtime:

  • scope:os
  • scope:admin
  • scope:founder
  • scope:workspace
  • scope:ai
  • scope:data

dependency-cruiser Rules

The dependency-cruiser config owns hard import boundaries:

  • Browser layers (packages/ui, packages/features, packages/apps) must not depend on packages/backend.
  • Runtime packages must not depend on packages/backend unless an explicit architecture exception exists.
  • Contracts must not import implementation layers: ui, features, runtime, backend, or app packages.
  • Browser packages must not import server data packages such as packages/data/db.
  • UI packages must not depend on provider SDKs or server-only SDKs.

Existing package-specific rules remain in place for @prox-os/os-ui, @prox-os/app-contract, @prox-os/app-registry, @prox-os/os-apps, and the frontend primitives. The new layer rules make the default posture explicit as more packages arrive.

@prox-os/connectors and @prox-os/embed-runtime are lightweight App Hub aggregation packages. They are browser-safe shared runtime packages that may be imported by app packages. They must stay limited to serializable types, mock data, and safe policy helpers until real connector clients, sync engines, permission enforcement, URL intelligence, or screenshot services are designed behind stronger boundaries.

Browser / Server / Shared / Tooling

RuntimeAllowed responsibilitiesExamples
BrowserReact UI, view models, action intents, mock adapters, Storybook examples.@prox-os/files, @prox-os/os-ui, @prox-os/os-apps.
ServerProvider bindings, DB clients, auth, billing, storage presigners, audit persistence, AI adapters.@prox-os/db, future @prox-os/auth.
SharedSerializable contracts and manifest data with no environment binding.@prox-os/app-contract, @prox-os/data-contract.
ToolingRepo generators, static analysis, test helpers, build helpers.future @prox-os/testing-utils.

Platform Runtime Product Packages

These packages define the current platform frame. They split platform navigation, Alma, inspection, runtime chrome, and runtime contracts so future agents do not put every visible product surface back inside the app host.

PackagePathLayerImportable byOwnsMust not own
@prox-os/platform-navigationpackages/features/platform-navigationFeatureapps/os-shell, browser runtime hostsGlobal Platform Navigation, platform frame, Left Panel host, Alma Rail host, platform-level layout state contracts.Window manager, app lifecycle, backend data clients.
@prox-os/almapackages/features/almaFeatureapps/os-shell, future platform hostsAlma UI, prompts, command cards, context badges, quick actions, fullscreen mode.Direct runtime store ownership, secret-bearing model clients, backend execution.
@prox-os/inspectorpackages/features/inspectorFeatureapps/os-shell, future platform hostsInspector UI, object/record/app/connector/permission/runtime placeholder sections.Primary runtime hosting, app launch ownership.
@prox-os/runtime-chromepackages/runtime/runtime-chromeRuntimeapps/os-shell, future runtime hostsRuntime Command Strip, Runtime Canvas frame, mode surfaces, runtime-facing visible chrome.Platform navigation entries, Alma command model, server-only permissions.
@prox-os/os-runtimepackages/runtime/os-runtimeRuntimeBrowser hosts, contracts, runtime chromeRuntime modes, context snapshots, lifecycle/event contracts, singleton versus multi-window capability rules.React presentation, platform navigation, backend enforcement.

Studio Engine Packages

Studio Engine packages live under packages/studio-engines/*. They are browser packages, but they are not generic UI primitives and not user Studio instances. A package represents a renderer family such as Block, Board, or Flow, while a Studio instance remains user data.

Extract a Studio Engine package when one of these is true:

  • the engine owns a heavy dependency that should not sit in the Shell initial bundle;
  • the engine has a stable renderer boundary shared by routes, demos, or future hosts;
  • the engine can consume host callbacks instead of importing Shell stores.

Current extracted engines:

PackageOwnsDependency ownership
@prox-os/block-studio-engineBlock Studio rendererBlockNote and block-editor CSS.
@prox-os/board-studio-engineBoard Studio rendererExcalidraw and board CSS.
@prox-os/flow-studio-engineFlow Studio rendererReact Flow / xyflow and graph CSS.

apps/os-shell must lazy-load these components. The Shell may pass callbacks for opening apps, showing context menus, and supplying runtime context, but engine packages must not import apps/os-shell, private app ids, window manager state, or Zustand stores.

Desktop, Atlas, Grid, and Ops are not extracted yet. Desktop still depends on Shell-specific runtime shape. Atlas, Grid, and Ops are lightweight v0 renderers without enough package-level reuse or dependency weight to justify extraction. IDE and App Studio are local-only development engines under /dev/studios/*. Do not extract engines for symmetry alone.

App Category Packages

packages/apps/system-apps is no longer the container for every official app. Apps are grouped by category package, not one package per app:

PackageResponsibility
@prox-os/os-appsOS-level apps such as App Store, About, Support, System, and Trust.
@prox-os/user-appsPersonal work, media, health, workspace, and user-owned surfaces.
@prox-os/user-connector-appsMock connector shells and permission-aware source surfaces.
@prox-os/dev-appsDeveloper tools, route maps, and local development workbenches.
@prox-os/admin-appsAdmin, backend, deploy, and operations control surfaces.
@prox-os/game-appsBrowser-native games and game collection surfaces.
@prox-os/founder-appsFounder, pricing, waitlist, roadmap, and growth surfaces.
@prox-os/community-appsCommunity and community admin surfaces.
@prox-os/hub-appsPlatform and productized hub cockpit surfaces.
@prox-os/app-sharedShared app primitives, manifest helpers, and proxied runtime UI.

This keeps packages reviewable without creating a package per app. The Shell registry composes manifests from these packages, while localAppComponents.tsx maps app ids to components. Category packages should export app components and manifests from their root barrel and avoid deep imports from Shell code.

Avoiding Provider Key Leaks

Provider SDKs, secret-bearing clients, token refresh logic, presigned upload generation, billing APIs, and DB clients belong in server packages or deployable apps with server runtimes. Browser packages should receive:

  • redacted metadata,
  • mock data,
  • action intent,
  • a typed contract,
  • or a runtime callback supplied by the app host.

If a browser package needs to display a provider state, create a serializable view model in a contract or feature package. Do not import the provider client.

Keeping Contracts Pure

Contracts must stay safe to import from browser, server, tools, docs, and tests. They should contain:

  • IDs and serializable object shapes,
  • enums and discriminated unions,
  • manifest and capability types,
  • event payload contracts.

They should not import React, shell code, app packages, DB clients, provider SDKs, runtime adapters, or environment variables.

Exceptions

Exceptions are allowed only when the import is deliberate and documented. Use one of these paths:

  • Add an ADR under docs/platform/architecture/decisions.
  • Add a focused note to this document when the exception is broad and ongoing.
  • Add a package-specific dependency-cruiser exception with a precise comment.

Do not add a wide ignore rule to make a build pass. The exception should explain why the boundary is safe, who owns it, and when it should be revisited.

On this page