Reference

Module Definition Files

Define Redelay modules in YAML or JSON with IDE validation via JSON Schema.

Module: github.com/redelay/go-framework/core/schema, github.com/redelay/go-framework/core/modfile

Redelay modules can be defined as YAML or JSON files, enabling cross-language module definitions and IDE-assisted editing with JSON Schema validation. This is the recommended approach for modules shared across Go, Python, and JavaScript implementations.

Overview

Every module in Redelay maps to an ir.Module — the canonical intermediate representation. Modules can be defined in three ways:

ApproachUse caseCross-language
YAML/JSON filesShared module definitionsYes — any language
Programmatic (Go)Go-native modules with runtime logicGo only
Import from specsDerive from OpenAPI, AsyncAPI, FlowDSLYes — via importers

All three paths produce the same ir.Module structure that feeds into the compile pipeline.

Module file format

A module definition file is a direct YAML/JSON serialization of ir.Module. All field names use snake_case matching the Go struct json tags.

Minimal example

yaml
# yaml-language-server: $schema=https://redelay.com/schemas/module.schema.json
id: notifications
name: Notifications
description: Email and push notification module
dependencies:
  - users

Full example

yaml
id: auth
name: Auth
description: JWT authentication and token management
version: 1.0.0
dependencies:
  - users

entities:
  - id: auth.refresh_token
    name: RefreshToken
    fields:
      - name: token_id
        type: string
        required: true
      - name: user_id
        type: string
        required: true
      - name: expires_at
        type: datetime
        required: true

events:
  - id: auth.login
    name: auth.login
    entity_type: user
    action: login
    topic: auth
    payload:
      id: auth.login.payload
      name: AuthLoginPayload
      fields:
        - name: user_id
          type: string
          required: true
        - name: email
          type: string
          required: true
  - id: auth.login_failed
    name: auth.login_failed
    entity_type: user
    action: login_failed
    topic: auth

config:
  id: auth
  name: Auth Configuration
  entries:
    - key: AUTH_JWT_SECRET
      type: string
      required: true
      sensitive: true
    - key: AUTH_JWT_ALGORITHM
      type: string
      default: HS256
    - key: AUTH_ACCESS_TOKEN_TTL_MINUTES
      type: integer
      default: 30

settings:
  id: auth
  name: Authentication Settings
  groups:
    - id: auth.tokens
      label: Token Settings
      order: 1
      settings:
        - key: access_token_ttl_minutes
          label: Access Token TTL (min)
          type: integer
          default: 30
        - key: refresh_token_ttl_days
          label: Refresh Token TTL (days)
          type: integer
          default: 7

crud:
  - id: auth.refresh_token
    entity_ref: auth.refresh_token
    operations:
      - kind: create
        emits: [auth.token_refreshed]
      - kind: delete
        emits: [auth.token_revoked]

JSON Schema

JSON Schema files (Draft 2020-12) are generated from the Go IR types via reflection:

SchemaValidatesURI
module.schema.jsonSingle module definitionhttps://redelay.com/schemas/module.schema.json
document.schema.jsonFull IR documenthttps://redelay.com/schemas/document.schema.json

VS Code setup

Add to .vscode/settings.json for automatic validation and autocomplete:

json
{
  "yaml.schemas": {
    "https://redelay.com/schemas/module.schema.json": [
      "**/modules/*.yaml",
      "**/modules/*.yml"
    ],
    "https://redelay.com/schemas/document.schema.json": [
      "**/*.redelay.yaml"
    ]
  }
}

Or add an inline schema reference at the top of any YAML file:

yaml
# yaml-language-server: $schema=https://redelay.com/schemas/module.schema.json

Generating schemas

Schemas are generated from Go IR types via reflection. The core/schema package provides both programmatic and JSON output:

go
import "github.com/redelay/go-framework/core/schema"

// Get module schema as Go map
s := schema.ModuleSchema()

// Get as formatted JSON bytes
data, err := schema.ModuleSchemaJSON()

// Get document schema
data, err := schema.DocumentSchemaJSON()

Schema generator

The underlying schema.Generator can produce JSON Schema for any Go struct type:

go
g := schema.New()
g.RegisterEnum(MyKind(""), []string{"a", "b", "c"})
data, err := g.JSON(MyStruct{}, "https://example.com/my.schema.json", "My Schema")

Features:

  • Maps Go primitives to JSON Schema types (string, integer, number, boolean)
  • Handles time.Time as string with date-time format
  • Named struct types become $defs entries with $ref pointers
  • Recursive types handled via cycle detection
  • Embedded structs flattened into parent properties
  • json tags control property names; omitempty controls required
  • Pointer types treated as optional (not required)
  • Registered enum types emit enum constraints
  • map[string]T becomes object with additionalProperties
  • any/interface{} becomes an unconstrained schema

Field types

The type field in entity/schema/packet fields accepts these values:

TypeDescriptionJSON Schema equivalent
stringText valuestring
integerWhole numberinteger
floatDecimal numbernumber
booleanTrue/falseboolean
arrayList (use items for element type)array
objectNested object (use properties)object
dateDate without timestring + date
datetimeDate with timestring + date-time
uuidUUID stringstring + uuid
binaryBinary datastring + binary
refReference to another entitystring + $ref
enumEnumerated value (use enum list)string + enum
anyAny typeunconstrained

Loading and saving module files

The core/modfile package provides load/save for both module and document files:

go
import "github.com/redelay/go-framework/core/modfile"

// Load a module from YAML
f, _ := os.Open("modules/auth.yaml")
mod, err := modfile.LoadModule(f, modfile.DetectFormat("auth.yaml"))

// Load from JSON
mod, err := modfile.LoadModule(r, "json")

// Save as YAML
modfile.SaveModule(mod, w, "yaml")

// Load a full document
doc, err := modfile.LoadDocument(r, "yaml")

// Format detection from filename
format := modfile.DetectFormat("auth.yaml")  // "yaml"
format := modfile.DetectFormat("auth.json")  // "json"

Exporting and loading module directories

The modfile package supports batch operations for working with directories of module files — the standard layout for an application's module definitions:

go
import "github.com/redelay/go-framework/core/modfile"

// Export modules as individual YAML files to a directory.
// Each module becomes "<id>.module.yaml".
paths, err := modfile.ExportModules(modules, "modules/")
// Returns: ["modules/auth.module.yaml", "modules/users.module.yaml", ...]

// Load all module files from a directory.
// Reads *.module.yaml, *.module.yml, *.module.json in alphabetical order.
modules, err := modfile.LoadDir("modules/")

Generating module files from registered modules

Use app.BootstrapIR() to extract IR from all registered Go modules without connecting to databases or starting the application:

go
import (
    _ "github.com/redelay/go-framework/modules/auth"
    _ "github.com/redelay/go-framework/modules/users"
    "github.com/redelay/go-framework/app"
    "github.com/redelay/go-framework/core/modfile"
)

application, _ := app.BootstrapIR("myapp")
doc := application.IR()
modfile.ExportModules(doc.Modules, "modules/")

Or use the CLI:

shell
# Export an IR document's modules as individual YAML files
redelayctl generate ir-document.yaml modules/

Backend generate command pattern

Each application can have a cmd/generate/ entry point that produces its module YAML files. This enables regeneration whenever core modules are updated:

go
// backend/cmd/generate/main.go
package main

import (
    _ "github.com/redelay/go-framework/modules/auth"
    _ "github.com/redelay/go-framework/modules/users"
    // ... more module imports ...

    "github.com/redelay/go-framework/app"
    "github.com/redelay/go-framework/core/modfile"
)

func main() {
    application, _ := app.BootstrapIR("myapp")
    doc := application.IR()
    modfile.ExportModules(doc.Modules, "modules/")
}

Run with go run ./cmd/generate/ to (re)generate all module YAML files.

Extending core modules

Applications often need to add events, entities, or config to core modules without forking them. The modfile.MergeModule() function provides an overlay mechanism:

go
import "github.com/redelay/go-framework/core/modfile"

// Load the core module (generated or from framework)
base, _ := modfile.LoadModule(baseReader, "yaml")

// Load app-level overlay with additions
overlay, _ := modfile.LoadModule(overlayReader, "yaml")

// Merge: overlay augments the base
merged := modfile.MergeModule(base, overlay)

Merge semantics

Field typeBehavior
Scalars (description, version)Overlay replaces base if non-empty
String slices (dependencies, provides, imports)Deduplicated union
Struct slices (entities, events, commands, ...)Appended from overlay
Config entriesMerged by key — overlay wins on conflict, new entries appended
Setting groupsMerged by ID — overlay wins on conflict, new groups appended

Example: extending auth with MFA

Create modules/auth.overlay.yaml:

yaml
id: auth
events:
  - id: auth.mfa_verified
    name: auth.mfa_verified
    entity_type: user
    action: mfa_verified
    topic: auth
config:
  id: auth
  entries:
    - key: AUTH_MFA_ENABLED
      type: boolean
      default: false
    - key: AUTH_MFA_ISSUER
      type: string
      default: "MyApp"

Load and merge at startup:

go
base, _ := modfile.LoadModule(openBase, "yaml")
overlay, _ := modfile.LoadModule(openOverlay, "yaml")
merged := modfile.MergeModule(base, overlay)
// merged now has all original auth events + auth.mfa_verified,
// all original config entries + AUTH_MFA_ENABLED, AUTH_MFA_ISSUER

Cross-language usage

Module definition files are standard YAML/JSON matching the IR schema. Any language with a YAML/JSON parser can read them:

Python:

python
import yaml

with open("modules/auth.yaml") as f:
    module = yaml.safe_load(f)

print(module["events"][0]["name"])  # "auth.login"

JavaScript:

javascript
import { readFileSync } from 'fs';
import { parse } from 'yaml';

const module = parse(readFileSync('modules/auth.yaml', 'utf8'));
console.log(module.events[0].name);  // "auth.login"

Integration with compile pipeline

Module files integrate with the existing compile pipeline:

go
import (
    "github.com/redelay/go-framework/core/compile"
    "github.com/redelay/go-framework/core/ir"
    "github.com/redelay/go-framework/core/modfile"
)

// Load external module definitions
f, _ := os.Open("modules/notifications.yaml")
mod, _ := modfile.LoadModule(f, "yaml")

// Combine with programmatic modules
doc := ir.NewDocument("MyApp", "1.0")
doc.Modules = append(doc.Modules, mod)

// Compile (validate + resolve + enrich)
result, err := compile.Compile(doc)

Integration with external specs

Module files can coexist with imported specs. Use importers to derive modules from OpenAPI, AsyncAPI, or FlowDSL documents, then merge with explicit module definitions:

go
// Import an AsyncAPI spec -> IR events/channels
asyncDoc, _ := compile.Import("asyncapi", asyncReader)

// Load explicit module definition
mod, _ := modfile.LoadModule(modReader, "yaml")

// Merge into a single document
doc := ir.NewDocument("MyApp", "1.0")
doc.Modules = append(doc.Modules, mod)
doc.Channels = asyncDoc.Channels
doc.Events = append(doc.Events, asyncDoc.Events...)

result, _ := compile.Compile(doc)

SVG diagram generation

Module: github.com/redelay/go-framework/core/modsvg

Generate visual SVG diagrams from module definitions. The diagram shows the module center with surrounding cards for each section (entities, events, config, CRUD, settings, commands, queries, workflows, schedules, consumers, dependencies, provides).

CLI usage

shell
# Output to stdout
redelayctl diagram auth.module.yaml

# Output to file
redelayctl diagram auth.module.yaml auth-diagram.svg

Programmatic usage (Go)

go
import (
    "os"
    "github.com/redelay/go-framework/core/modsvg"
    "github.com/redelay/go-framework/core/modfile"
)

f, _ := os.Open("auth.module.yaml")
mod, _ := modfile.LoadModule(f, modfile.FormatYAML)

// Write to file
out, _ := os.Create("auth.svg")
modsvg.Generate(out, mod)

// Or get as string
svg, _ := modsvg.GenerateString(mod)

Features

  • Hub-and-spoke layout with module name and version at center
  • Color-coded section cards matching the Redelay brand palette
  • Badge counts showing number of items per section
  • Dark mode support via prefers-color-scheme CSS media query
  • Drop shadow effects for depth
  • SVG viewBox for responsive scaling

Module spec UI

Module: github.com/redelay/go-framework/modules/modspec

The modspec module provides an interactive HTML page listing all registered modules with SVG diagrams and YAML spec views — similar to how the openapi module serves Scalar/Swagger UI for API reference.

Endpoints

PathContent-TypeDescription
/modules.jsonapplication/jsonJSON array of all module specs with SVG + YAML
/modulestext/htmlInteractive module browser UI

Configuration

Env varDefaultDescription
MODSPEC_SPEC_PATH/modules.jsonPath for the JSON spec endpoint
MODSPEC_UI_PATH/modulesPath for the HTML UI page

Usage

Add a blank import to your application entry point:

go
import _ "github.com/redelay/go-framework/modules/modspec"

Then visit /modules for the interactive browser or /modules.json for the raw JSON spec.

Module tooling pipeline

Module YAML files are the single source of truth for the full development workflow. Three core packages power validation, scaffolding, and drift detection:

PackageCLI commandPurpose
core/modvalredelayctl validate-moduleValidate naming conventions, reference integrity, required fields
core/modgenredelayctl scaffoldGenerate Go module directory (factory, routes, handlers)
core/modsyncredelayctl auditCompare declared YAML vs runtime module for drift

modval — Module validator

Module: github.com/redelay/go-framework/core/modval

Validates an ir.Module against domain-specific rules:

  • Required fields — ID and name must be present
  • Version format — must be valid semver (e.g. 1.0.0)
  • Entity IDs — must be prefixed with module ID (auth.token, not token)
  • Event names — must contain a dot separator (auth.login)
  • Config keys — must be UPPER_SNAKE_CASE with module prefix (AUTH_JWT_SECRET)
  • Settings keys — must be lower_snake_case
  • CRUD refs — entity references must match declared entities
  • No duplicates — entity and event IDs must be unique
  • No self-dependencies — a module cannot depend on itself

Diagnostic codes use the MV prefix (e.g. MV001, MV010, MV021).

go
import "github.com/redelay/go-framework/core/modval"

diag := modval.Validate(module)
if diag.HasErrors() {
    for _, e := range diag.Errors() {
        fmt.Printf("ERROR [%s] %s\n", e.Code, e.Message)
    }
}

modgen — Module scaffolder

Module: github.com/redelay/go-framework/core/modgen

Generates a working Go module directory from an ir.Module definition:

Generated fileContent
module.goinit() factory, Module struct with modules.IRBase, Startup/Shutdown stubs
routes.goHTTP route registration from CRUD operations (only if module has CRUD)
handlers.goHandler documentation stubs (only if module has CRUD)
go
import "github.com/redelay/go-framework/core/modgen"

result, err := modgen.Scaffold(module, modgen.Options{
    OutputDir: "./modules/orders",
    Package:   "orders",      // defaults to module ID
    Force:     false,          // don't overwrite existing files
})
for _, f := range result.Files {
    fmt.Println(f)  // list generated files
}

The scaffolder is designed for one-time generation: it creates the boilerplate once, then you implement business logic in the generated stubs. Existing files are preserved unless Force is set.

modsync — Drift detection

Module: github.com/redelay/go-framework/core/modsync

Compares two ir.Module instances and produces a structured drift report. Typically used to compare a declared YAML definition against a runtime-exported module.

go
import "github.com/redelay/go-framework/core/modsync"

report := modsync.Compare(declared, actual)
if report.HasDrift() {
    fmt.Print(report.Summary())
    for _, d := range report.Diffs {
        fmt.Println(d.String())  // e.g. "[+] events: auth.mfa_enabled"
    }
}

Drift kinds:

KindSymbolMeaning
added+Present in actual, missing from declared
removed-Present in declared, missing from actual
changed~Present in both but different (e.g. field count)

Compared sections: name, version, description, entities, events, config, settings, CRUD, dependencies, provides, commands, queries, workflows, schedules, consumers.