Skip to content

mbackschat/spec-driven-platform-experiment

Repository files navigation

Experimental Spec-Driven Application Platform

A generic, domain-agnostic spec-driven runtime for business applications. Domain specifications (.spec files) define entities, workflows, actions, and views — the runtime executes them with full effect tracing and governance. The platform is not tied to any specific industry; it can drive insurance, logistics, HR, finance, or any OLTP domain.

The included insurance claims module (domain/insurance/claims/) is a reference implementation that demonstrates the full vertical slice: Spec DSL → Semantic Model → Runtime Engine → React UI.

Experimental Work

This project implements the Spec-Driven Development platform concept along with the derived Runtime architecture specification (both developed in various chat sessions in ChatGPT and Claude). The key idea is to create such a platform from scratch and implement it iteratively with AI coding agents.

Architecture

┌──────────────────────────────────────────────────────────┐
│                    React Frontend (:3000)                  │
│  Spec-driven renderers: SpecFormView · SpecListView      │
│  SpecCreateForm · FieldRenderer · WorkflowStepper · SSE  │
└────────────────────────┬─────────────────────────────────┘
                         │ HTTP / SSE (proxied via Vite)
┌────────────────────────┴─────────────────────────────────┐
│             Domain-Agnostic Fastify Runtime (:3001)       │
│  Action Routes · Query Routes · Meta Routes · Auth · SSE │
│  Loads DomainModules → merges graphs, scripts, resolvers │
├──────────────────────────────────────────────────────────┤
│                  Action Orchestrator                      │
│  12-step cycle: resolve → guards → transaction →         │
│  script → collect effects → validate → commit → project  │
├──────────────────────────────────────────────────────────┤
│     Workflow Engine · Rule Engine · Effect Validator      │
├──────────────────────────────────────────────────────────┤
│         Platform Persistence (AuditLog · Outbox)         │
│  Kysely (SQLite dev / PostgreSQL prod) · Migrations      │
└──────────────────────────────────────────────────────────┘
         ↑ DomainModule registry
┌────────┴─────────────────────────────────────────────────┐
│           Domain Module(s) — pluggable per domain        │
│  e.g. domain/insurance/claims/module.ts                  │
│  .spec files · Action Scripts · Capabilities · Hooks     │
│  Data Routes · Seed Data                                 │
└──────────────────────────────────────────────────────────┘

The runtime is domain-agnostic. It contains zero references to claims, policies, or any business concept. All domain-specific code lives under domain/ and registers itself via the DomainModule contract. A lint check (pnpm lint:boundaries) enforces this separation.

Delta-Merge enables structured domain evolution: instead of editing .spec files directly, changes are formulated as typed deltas (add/modify/remove) in delta.spec files, validated against the live graph, previewed non-destructively via graph overlay, and atomically merged.

Spec-Driven Navigation: The frontend discovers all views from GET /api/meta/views and builds sidebar navigation + routes automatically. Adding a view spec creates a UI page — no React code changes needed.

Spec DSL

Domain specifications are written in a custom DSL that is domain-agnostic. The @platform/spec-dsl parser reads .spec files at startup, resolves cross-references (including entity inheritance, weak entities/aggregates, lookups, invariants, and policies), assigns semantic IDs, and registers everything into the AppGraph. Specs are the live source of truth — edit a .spec file and the runtime picks it up on next start. See SPEC-REF.md for the complete DSL reference.

Example action spec (from the insurance demo):

action ApproveClaim for Claim in claims
  input
    claimId : UUID    required
    comment : String  optional

  guards
    actor hasRole "Adjuster"
    claim.status == InReview

  effects
    transitions Claim from InReview to Approved
    updates Claim.approvedAt, Claim.approvedBy
    emits ClaimApproved
    audits "claim-approval"

  output
    claimId       : UUID
    newStatus     : ClaimStatus
    approvalMode  : String

  script "./scripts/ApproveClaim.ts"
end

Effect System

Every action declares what effects it will produce. During execution, the scripting host records what actually happened. After execution, the validator compares declared vs. observed:

Effect Meaning Example
updates Field changed updates Claim.status
creates New entity creates ApprovalTask
transitions Workflow state change transitions Claim from InReview to Approved
emits Domain event emits ClaimApproved
calls External capability calls FraudEngine.ScoreClaim
audits Compliance trail audits "claim-approval"

Violations (undeclared effects) block the action. Mismatches (missing declared effects) are logged as warnings. All traces stored in the effect_traces table.

CLI

Terminal-based access to the platform API. Same endpoints as the frontend, structured JSON output by default (AI-agent-friendly). Run via pnpm cli <args> from the project root.

pnpm cli login -u <email> -p <password>            Authenticate, store JWT
pnpm cli meta <type> [id]                          Explore metadata (views, entities, actions, ...)
pnpm cli describe <actionId>                       Show input schema, guards, effects
pnpm cli form <actionId>                           Show input template (what fields are needed)
pnpm cli execute <actionId> -i <json>              Execute a domain action
pnpm cli validate <actionId> -i <json>             Validate input without executing
pnpm cli query <viewId> [--filter k=v] [--sort]    Query view data (list)
pnpm cli get <viewId> <entityId>                   Get entity detail
pnpm cli batch <file.json>                         Execute multiple operations from file

Global options: --server <url> (default http://localhost:3001), --token <jwt>, --format <json|table|raw>.

Meta types: views, entities, actions, workflows, enums, lookups, stats. Pass an ID to get detail: pnpm cli meta actions <actionId>.

API

POST /api/auth/login                        Login
POST /api/actions/:actionId/execute         Execute a domain action
POST /api/actions/:actionId/validate        Validate input without executing
GET  /api/views/:viewId/data                Query view data (list)
GET  /api/views/:viewId/data/:entityId      Get entity detail
GET  /api/meta/views                        List all view descriptors (drives navigation)
GET  /api/meta/views/:viewId                View descriptor (metadata)
GET  /api/meta/actions/:actionId            Action descriptor
GET  /api/meta/workflows/:workflowId        Workflow descriptor
GET  /api/meta/graph/stats                  AppGraph statistics
GET  /api/meta/lookups                      Lookup reference data (key/label pairs)
GET  /api/meta/enums                        Enum descriptors with labels
GET  /api/data/*                            Domain-registered data endpoints
GET  /api/realtime/subscribe                SSE event stream
GET  /api/health                            Health check (modules, graph stats)

Quick Start

Prerequisites

  • Node.js 22+
  • pnpm 9+

Setup

# Install dependencies
pnpm install

# Build all packages (required before first run)
pnpm build

# Seed the development database (SQLite)
pnpm dev:seed

# Start the API server (port 3001) — keep this terminal open
pnpm --filter @platform/runtime dev

# In a SECOND terminal — start the React frontend (port 3000)
pnpm --filter @platform/frontend dev

Open http://localhost:3000 in your browser. This is the React UI.

Do NOT open port 3001 directly — that is the API server (Fastify) which only serves JSON. The frontend on port 3000 automatically proxies /api requests to port 3001 via Vite.

Insurance Demo

The platform ships with a complete insurance claims domain as a reference implementation. See FEATURE-DEMOS.md for interactive walkthroughs (browser + CLI) covering the full claim lifecycle, lookup fields, spec-driven navigation, role-based views, child views, and weak entities.

Demo Users

User Password Role What they can do
anna.clerk@example.com password123 Clerk Create and submit claims
bob.adjuster@example.com password123 Adjuster Review, approve, reject, pay claims
carol.senior@example.com password123 SeniorAdjuster Approve escalated claims (>25k EUR)
dave.fraud@example.com password123 FraudReviewer Review fraud-flagged claims

Project Structure

platform/
├── packages/                   # Domain-agnostic platform infrastructure
│   ├── core/                 # Types, semantic IDs, AppGraph, engines, DomainModule contract
│   ├── spec-dsl/             # Spec DSL parser, resolver, graph loader
│   ├── runtime/              # Domain-agnostic Fastify server, persistence, auth, SSE
│   ├── frontend/             # React 19 + Redux Toolkit UI
│   ├── cli/                  # pnpm cli: terminal-based platform access
│   └── testing/              # Test harness, effect assertions
├── domain/                     # Pluggable domain modules (one per business domain)
│   └── insurance/claims/     # Reference domain: insurance claims processing
│       ├── package.json      # Workspace package with @platform/core dependency
│       ├── module.ts         # DomainModule entry point (loads .spec files, provides hooks)
│       ├── capabilities/     # FraudEngine + PaymentGateway mocks
│       ├── views/routes.ts   # Domain-specific data endpoints (/api/data/policies, etc.)
│       ├── seed.ts           # Demo data (users + audit in TS, domain entities from seed.spec)
│       ├── scripts/          # 8 action scripts (TypeScript)
│       └── spec/             # Spec files — the live source of truth
│           ├── current/      # Entity, enum, lookup, rule, workflow, action, view, capability, policy specs
│           ├── data/         # Declarative seed data (claims.seed.spec)
│           ├── changes/      # Pending delta-merge changes
│           └── archive/      # Merged changes
├── scripts/
│   └── check-domain-boundaries.sh  # Lint: no insurance terms in runtime
├── migrations/               # Platform infrastructure migrations (audit, outbox, users)
└── data/                     # dev.db (gitignored)

Domain Module Contract

Any business domain plugs into the platform by implementing the DomainModule interface (packages/core/src/types/domain-module.ts):

interface DomainModule {
  name: string;                          // e.g., "insurance.claims", "logistics.shipping"
  registerGraph(graph: AppGraph): void;  // Register entities, actions, workflows, ...
  getScripts(): Map<string, ActionScript>;
  getCapabilities(): Map<string, CapabilityHandler>;
  getHooks?(): Map<string, DomainHook>;  // Escape hatches for custom logic
  registerRoutes?(app, db, authHelpers): void;
  seed?(db): Promise<void>;
  // Optional (reflective runtime handles these if not provided):
  // buildDomainApi?, getViewResolvers?, getEntityResolvers?
}

The runtime discovers modules in packages/runtime/src/bootstrap/load-domain.ts and iterates them at startup to build the AppGraph, collect scripts, wire capabilities, and register routes.

Technology

Layer Technology
Language TypeScript 5 (strict)
Monorepo pnpm workspaces + Turborepo + tsup
Backend Node.js 22 + Fastify 5
Database (dev) SQLite via better-sqlite3
Database (prod) PostgreSQL 16
DB Access Kysely (type-safe query builder)
Frontend React 19 + Redux Toolkit + Vite
CLI Commander (zero-dep arg parser)
Realtime Server-Sent Events
Auth JWT
Validation Descriptor-driven (from entity specs)

The chosen technology stack and build system are not the focus of this experiment — they serve the platform concept, not the other way around.

Agentic Development Workflow

The current approach (after a ramp-up phase) is to derive features from these specification documents, group them in feature sets, and then plan and implement them step by step — while also exploring and experimenting along the way.

Key elements of the workflow:

  • Feature sets (plan/): Features are grouped into coherent sets (e.g., "Localization + Seed Interpreter") and implemented in sessions. plan/backlog.md holds future sets, plan/next.md the active one, plan/done.md completed ones.
  • Red-Green TDD: Every feature starts with failing tests, then implementation to make them pass.
  • Feature Completion Checklist (PLAN.md): After each feature — write feature doc, update all top-level docs, extend E2E demo tests, commit together.
  • ADRs (adrs/): Architectural decisions that deviate from or fill gaps in the original concept and architecture specs are captured as Architecture Decision Records.
  • Feature docs (features/): Each completed feature gets a timestamped doc with context, design decisions, and implementation details.
  • Spec-driven verification: pnpm build && pnpm test && pnpm dev:reset && pnpm lint:boundaries runs after every change.

There are no formal coding guidelines. Cleanup, refactoring, and documentation sweeps happen ad-hoc as the codebase evolves.

Documentation

The doc/ directory contains the foundational specification documents that define the platform's vision and architecture. These were developed iteratively in ChatGPT and Claude sessions and serve as the conceptual blueprint from which the implementation is derived. Everything else in this project traces back to these two documents.

Document Audience Content
doc/integrated-spec.md Architects, contributors Origin spec — the consolidated platform vision: Spec-Driven Development concept, semantic core, effect system design, agentic development approach. This is the "why" and "what" of the platform
doc/platform-runtime-view-v5.md Architects, developers Runtime architecture spec — how the concepts from the integrated spec operationalize at runtime: Semantic Core, Spec-DSL, Delta-Merge, Effect System, Business Scripting, Lenses
SPEC-REF.md Domain modelers Complete DSL reference — syntax, semantics, runtime behavior for all spec types
DOMAIN-CHANGES.md Domain modelers Step-by-step tutorials for extending a domain module (add field, add entity, add action, delta-merge)
FEATURE-DEMOS.md Anyone Interactive walkthroughs of all platform features using the insurance demo
ANALYSIS.md Developers Deep internals — each package, how they connect, execution traces
ADRS.md Developers Architecture decision records (adrs/)
PLAN.md Contributors Roadmap structure — points to plan/ for backlog, current work, done sets
NOTES.md Contributors Design notes index — topic explorations, rationale, concept comparisons (notes/)
features/ Contributors Timestamped feature docs — context, design decisions, implementation details per completed feature

About

Experimental Domain-agnostic Application Platform where .spec files drive schema, persistence, queries, and UI/CLI automatically. Built with and for AI agents.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages