Skip to content

Core Package Boundaries

Doug Fennell edited this page Oct 1, 2025 · 1 revision

Core Package Boundaries

This page defines the architectural boundaries between the three RDCP packages and the import rules that keep them clean and predictable.

Packages and responsibilities

  • @rdcp.dev/core

    • Protocol-only, zero framework assumptions
    • Zod schemas and inferred types
    • Protocol constants: version, headers, paths
    • Error codes and error response schemas
    • Protocol fixtures for testing/examples
    • Dependencies: zod (and type-only deps)
    • No business logic, no IO, no framework code
  • @rdcp.dev/server

    • Framework adapters (Express/Fastify/Koa/Next.js)
    • Authentication middleware and helpers
    • Rate limiting, audit trail integration
    • Multi-tenancy context management
    • Depends on: @rdcp.dev/core
    • May re-export selected core items (transitional); prefer direct imports from core
    • Never depends on @rdcp.dev/client
  • @rdcp.dev/client

    • Fetch-based HTTP client for RDCP endpoints
    • Request builders and response parsing
    • Optional client-side validation
    • Depends on: @rdcp.dev/core
    • Never depends on @rdcp.dev/server

Dependency rules

  • core β†’ (no internal package deps)
  • server β†’ core
  • client β†’ core
  • server ↔ client: not allowed (no edges)

What belongs where

  • Core
    • Protocol version constants, header names, path constants
    • Request/response schemas (Zod) + inferred TypeScript types
    • Error codes and error response schemas
    • Protocol fixtures used across packages
  • Server
    • Adapters for Express/Fastify/Koa/Next.js
    • Auth middleware, rate limiting, audit logging hooks
    • Tenant context helpers and isolation handling
  • Client
    • Typed client wrapper around fetch
    • Request/response shaping and parsing
    • Retry/backoff utilities (when present)

Import rules (examples)

// βœ… Correct
import { controlRequestSchema } from '@rdcp.dev/core'
import { RDCPHttpClient } from '@rdcp.dev/client'

// ⚠️ Transitional (supported, but prefer direct core import)
import { controlRequestSchema as coreSchema } from '@rdcp.dev/server' // re-export

// ❌ Not allowed (breaks boundaries)
import { something } from '@rdcp.dev/server/internals' // deep import
// From client code:
// import { ServerAdapter } from '@rdcp.dev/server'

Versioning guidance

  • Core: any change to schemas, error codes, or protocol constants that affects consumers is a semver major.
  • Server/Client: adopting new core features is usually a minor; internal fixes are patch.
  • Server re-exports of core are deprecated; target removal on the next major to encourage direct core imports.

Enforcement suggestions

  • package.json "exports" per package to block deep imports
  • ESLint import rules (no-restricted-imports / import/no-restricted-paths) to prevent forbidden edges
  • dependency-cruiser (optional) to codify graph: coreβ†’none, serverβ†’core, clientβ†’core only
  • TS Project References to keep compilation boundaries explicit

See also

Clone this wiki locally