Skip to content

Data Model Reference

Overview

This document consolidates all data structures used across noorm. It serves as a single reference for types, database schemas, file formats, and their relationships.

noorm separates data into three tiers:

TierStorageEncryptionVersioned
State.noorm/state.encAES-256-GCMGit-ignored
Settings.noorm/settings.ymlNoneCommitted
DatabaseTarget databaseN/ATracked in-db

State holds secrets and credentials. Settings holds team-shared rules. Database tables track execution history.

Entity Relationship Diagram


State (Encrypted)

State File

The encrypted state file at .noorm/state.enc contains all sensitive configuration.

FieldTypeDescription
versionstringnoorm version for migrations
identityCryptoIdentity?User's cryptographic identity
knownUsersMapKnown users discovered from databases
activeConfigstring?Currently selected config name
configsMapDatabase configurations by name
secretsMapConfig-scoped secrets (configName → key → value)
globalSecretsMapApp-level secrets shared across configs

Encrypted Payload

On-disk format for the state file.

FieldTypeDescription
algorithmstringAlways aes-256-gcm
ivstringInitialization vector (base64)
authTagstringAuthentication tag (base64)
ciphertextstringEncrypted state JSON (base64)

The encryption key derives from machine-specific identifiers or the user's cryptographic identity passphrase.


Configuration

Config

A database connection profile stored in encrypted state.

FieldTypeRequiredDescription
namestringYesUnique identifier (e.g., dev, staging, prod)
typeenumYeslocal or remote
isTestbooleanYesMarks database as disposable for testing
protectedbooleanYesRequires confirmation for dangerous operations
connectionConnectionConfigYesDatabase connection details
pathsPathConfigYesFile system paths for schema and changes
identitystringNoOverride identity for executed_by field

ConnectionConfig

Database connection parameters.

FieldTypeRequiredDescription
dialectenumYespostgres, mysql, sqlite, or mssql
hoststringNetworkHostname (required for non-SQLite)
portnumberNoPort number (defaults by dialect)
databasestringYesDatabase name
filenamestringSQLiteFile path for SQLite databases
userstringNoDatabase username
passwordstringNoDatabase password
sslboolean or objectNoSSL/TLS configuration
poolobjectNoConnection pool settings (min, max)

Default ports by dialect:

DialectDefault Port
postgres5432
mysql3306
mssql1433
sqliteN/A

PathConfig

File system paths for schema and changes.

FieldTypeDescription
schemastringPath to schema directory
changesstringPath to changes directory

ConfigSummary

Lightweight config view for listings. Omits sensitive connection details.

FieldTypeDescription
namestringConfig identifier
typeenumlocal or remote
isTestbooleanTest database flag
protectedbooleanProtection enabled
isActivebooleanCurrently selected config

Config Resolution Order

Configs merge from five sources in priority order:

CLI flags > Environment > Stored config > Stage defaults > Defaults

Higher priority sources override lower ones, enabling flexible overrides for CI/CD.


Settings

Settings File

The .noorm/settings.yml file configures project-wide behavior. Unlike state, this file is not encrypted and should be version controlled.

yaml
# .noorm/settings.yml
build:
    include:
        - tables/**/*.sql
        - views/**/*.sql
    exclude:
        - '**/*.test.sql'

paths:
    sql: db/sql
    changes: db/changes

stages:
    dev:
        description: Development database
        defaults:
            dialect: postgres
            isTest: true
    prod:
        description: Production database
        locked: true
        defaults:
            dialect: postgres
            protected: true
        secrets:
            - key: DB_PASSWORD
              type: password
              required: true

rules:
    - match:
          protected: true
      exclude:
          - '**/*.seed.sql'

strict:
    enabled: true
    stages:
        - dev
        - staging
        - prod

logging:
    enabled: true
    level: info
    file: .noorm/noorm.log
    maxSize: 10mb
    maxFiles: 5

BuildConfig

Controls which files are included in build operations.

FieldTypeDescription
includestring[]Glob patterns for included files (filter only)
excludestring[]Glob patterns for excluded files

Include acts as a filter, not an ordering mechanism. Files are executed in alphanumeric order—use numeric prefixes on directories and files to control the sequence. If not specified, all .sql files in the schema directory are included.

PathConfig (Settings)

Override default file locations.

FieldTypeDefaultDescription
schemastringschemaPath to schema files
changesstringchangesPath to change directories

Stage

A stage is a config template that provides defaults and enforces constraints.

FieldTypeDescription
descriptionstring?Human-readable description
lockedboolean?When true, linked configs cannot be deleted
defaultsStageDefaults?Default values for new configs
secretsStageSecret[]Required secrets for completeness

StageDefaults

Initial values when creating a config from a stage.

FieldTypeDescription
dialectenum?Default database dialect
hoststring?Default hostname
portnumber?Default port
databasestring?Default database name
userstring?Default username
passwordstring?Default password
sslboolean?Default SSL setting
isTestboolean?Default test flag
protectedboolean?Default protection (cannot be overridden if true)

StageSecret

Defines a required secret for configs linked to a stage.

FieldTypeDefaultDescription
keystringRequiredSecret identifier
typeenumstringstring, password, api_key, or connection_string
descriptionstring?Human-readable description
requiredbooleantrueWhether the secret must be set for completeness

Rule

Conditional file inclusion/exclusion based on config properties.

FieldTypeDescription
matchRuleMatchConditions that trigger this rule
includestring[]?Additional glob patterns to include
excludestring[]?Additional glob patterns to exclude

RuleMatch

Conditions for rule evaluation.

FieldTypeDescription
namestring?Match config by name
protectedboolean?Match by protection status
isTestboolean?Match by test flag
typeenum?Match by local or remote

All specified conditions must match for the rule to apply.

StrictConfig

Enforce stage usage.

FieldTypeDescription
enabledboolean?Enable strict mode
stagesstring[]?Required stages (configs must link to one)

LoggingConfig

File logging configuration.

FieldTypeDefaultDescription
enabledbooleantrueEnable file logging
levelenuminfosilent, error, warn, info, or verbose
filestring.noorm/noorm.logLog file path
maxSizestring10mbMaximum file size before rotation
maxFilesnumber5Maximum rotated files to keep

Identity

Identity (Audit)

Simple identity used for tracking who executed database operations.

FieldTypeDescription
namestringDisplay name
emailstring?Email address
sourceenumHow identity was resolved

Identity sources (in resolution order):

PrioritySourceDescription
1configOverride specified in config (for bots/services)
2stateFrom encrypted state file (crypto identity)
3envNOORM_IDENTITY env var (CI pipelines)
4gitFrom git user.name and user.email
5systemFrom OS username

The resolver tries each source until it finds a valid identity.

CryptoIdentity

Full cryptographic identity for secure config sharing. Stored in encrypted state.

FieldTypeDescription
identityHashstringSHA-256 of canonical identity string
namestringDisplay name
emailstringEmail address
publicKeystringX25519 public key (hex)
machinestringMachine hostname
osstringOS platform and version
createdAtstringISO 8601 timestamp

Identity hash calculation:

SHA256(email + '\0' + name + '\0' + machine + '\0' + os)

The same user on different machines has different identities with different keypairs.

KnownUser

Cached identity discovered from database sync. Enables secure config sharing with team members.

FieldTypeDescription
identityHashstringSHA-256 of canonical identity string
emailstringUser email
namestringDisplay name
publicKeystringX25519 public key (hex)
machinestringMachine hostname
osstringOS platform and version
lastSeenstringISO 8601 timestamp of last activity
sourcestringConfig name where discovered

Key Files

Cryptographic keys are stored outside the project directory.

~/.noorm/
├── identity.key        # X25519 private key (hex, mode 600)
└── identity.pub        # X25519 public key (hex, mode 644)

The private key never leaves the user's machine. The public key is shared via database identity tables.


Encrypted Sharing

SharedConfigPayload

Format for encrypted config export files (*.noorm.enc).

FieldTypeDescription
versionnumberPayload format version
senderstringSender's email
recipientstringRecipient's email
ephemeralPubKeystringEphemeral X25519 public key (hex)
ivstringInitialization vector (hex)
authTagstringAuthentication tag (hex)
ciphertextstringEncrypted config (hex)

ExportedConfig

The decrypted contents of a shared config.

FieldTypeDescription
namestringConfig name
dialectstringDatabase dialect
connectionobjectHost, port, database, ssl, pool (no user/password)
pathsobjectSchema and change directories
isTestbooleanTest database flag
protectedbooleanProtection status
secretsMapConfig-scoped secrets

Note: user and password are intentionally omitted. Recipients provide their own credentials on import.


Database Tables

noorm creates five tracking tables in the target database. All table names are prefixed with __noorm_ to avoid conflicts.

__noorm_version__

Tracks noorm CLI version for internal schema migrations.

ColumnTypeConstraintsDescription
idserialPKPrimary key
cli_versionvarchar(50)NOT NULLnoorm version (semver)
noorm_versionintegerNOT NULLTracking table schema version
state_versionintegerNOT NULLState file format version
settings_versionintegerNOT NULLSettings file format version
installed_attimestampNOT NULL, DEFAULT NOW()First installation
upgraded_attimestampNOT NULL, DEFAULT NOW()Last upgrade

This table tracks noorm's internal schema, not the user's database schema.

__noorm_change__

Tracks all operation batches—changes, builds, and ad-hoc runs.

ColumnTypeConstraintsDescription
idserialPKPrimary key
namevarchar(255)NOT NULLOperation identifier
change_typevarchar(50)NOT NULLbuild, run, or change
directionvarchar(50)NOT NULLchange or revert
checksumvarchar(64)NOT NULLSHA-256 of sorted file checksums
executed_attimestampNOT NULL, DEFAULT NOW()When executed
executed_byvarchar(255)NOT NULLIdentity string
config_namevarchar(255)NOT NULLWhich config was used
cli_versionvarchar(50)NOT NULLnoorm version
statusvarchar(50)NOT NULLpending, success, failed, reverted
error_messagetextNOT NULLError details (empty = no error)
duration_msintegerNOT NULLExecution time (0 = never ran)

Name formats by change type:

Change TypeFormatExample
changeFolder name2024-01-15_add-users
buildbuild:{timestamp}build:2024-01-15T10:30:00
runrun:{timestamp}run:2024-01-15T10:30:00

__noorm_executions__

Tracks individual file executions within an operation.

ColumnTypeConstraintsDescription
idserialPKPrimary key
change_idintegerFK, NOT NULLParent operation
filepathvarchar(500)NOT NULLExecuted file path
file_typevarchar(10)NOT NULLsql or txt
checksumvarchar(64)NOT NULLSHA-256 of file contents
cli_versionvarchar(50)NOT NULLnoorm version
statusvarchar(50)NOT NULLpending, success, failed, skipped
error_messagetextNOT NULLError details (empty = no error)
skip_reasonvarchar(100)NOT NULLWhy skipped (empty = not skipped)
duration_msintegerNOT NULLExecution time (0 = never ran)

__noorm_lock__

Prevents concurrent operations on the same database.

ColumnTypeConstraintsDescription
idserialPKPrimary key
config_namevarchar(255)UNIQUE, NOT NULLLock scope
locked_byvarchar(255)NOT NULLIdentity of holder
locked_attimestampNOT NULL, DEFAULT NOW()When acquired
expires_attimestampNOT NULLAuto-expiry time
reasonvarchar(255)NOT NULLLock reason (empty = none)

Locks automatically expire to prevent deadlocks from crashed processes.

__noorm_identities__

Stores user identities for team discovery.

ColumnTypeConstraintsDescription
idserialPKPrimary key
identity_hashvarchar(64)UNIQUE, NOT NULLSHA-256 of identity
emailvarchar(255)NOT NULLUser email
namevarchar(255)NOT NULLDisplay name
machinevarchar(255)NOT NULLMachine hostname
osvarchar(255)NOT NULLOS platform and version
public_keytextNOT NULLX25519 public key (hex)
registered_attimestampNOT NULL, DEFAULT NOW()First registration
last_seen_attimestampNOT NULL, DEFAULT NOW()Last activity

Auto-populated on first database connection when cryptographic identity is configured.


File System Structures

Change Directory

Changes live on disk as directories with a specific structure.

changes/
└── 2024-01-15_add-email-verification/
    ├── change/
    │   ├── 001_add-column.sql
    │   ├── 002_update-data.sql
    │   └── 003_files.txt
    ├── revert/
    │   ├── 001_drop-column.sql
    │   └── 002_restore-data.sql
    └── changelog.md

Change (Parsed)

When read from disk, changes are parsed into:

FieldTypeDescription
namestringFolder name (e.g., 2024-01-15_add-email-verification)
pathstringAbsolute path to directory
dateDate?Parsed from name prefix (YYYY-MM-DD)
descriptionstringHuman-readable, derived from name
changeFilesChangeFile[]Files in change/ subdirectory
revertFilesChangeFile[]Files in revert/ subdirectory
hasChangelogbooleanWhether changelog.md exists

ChangeFile

Individual file within a change.

FieldTypeDescription
filenamestringFile name (e.g., 001_alter-users.sql)
pathstringAbsolute path
typeenumsql or txt
resolvedPathsstring[]?For .txt files, paths to referenced files
statusenum?Runtime status after execution
skipReasonstring?Why file was skipped

File types:

TypeExtensionPurpose
sql.sql, .sql.tmplDirect SQL execution (with optional templating)
txt.txtManifest file listing paths to execute

Change Naming

Change folder names follow a convention:

{date}_{description}
ComponentFormatExample
dateYYYY-MM-DD2024-01-15
descriptionkebab-caseadd-email-verification

The date prefix ensures chronological ordering. The description provides context.


Runtime Types

Operation Status

Used in __noorm_change__ and change results.

StatusMeaning
pendingNot yet executed
successCompleted successfully
failedExecution failed
revertedWas applied, then rolled back

Execution Status

Used in __noorm_executions__ and file results.

StatusMeaning
pendingNot yet executed
successCompleted successfully
failedExecution failed
skippedSkipped (see skip reason)

Skip Reasons

ReasonMeaning
unchangedFile checksum matches previous run
already-runFile was already executed successfully
change failedParent change failed

Lock

Active lock state returned by lock operations.

FieldTypeDescription
lockedBystringIdentity of holder
lockedAtDateWhen acquired
expiresAtDateAuto-expiry time
reasonstring?Why lock was acquired

Lock Options

Options for lock acquisition.

FieldTypeDefaultDescription
timeoutnumber300,000 (5 min)Lock duration in ms
waitbooleanfalseBlock until available
waitTimeoutnumber30,000 (30 sec)Maximum wait time in ms
pollIntervalnumber1,000 (1 sec)Check interval in ms
reasonstring?Lock reason

Run Options

Options for file execution.

FieldTypeDefaultDescription
forcebooleanfalseRe-run even if unchanged
concurrencynumber1Parallel file execution
abortOnErrorbooleantrueStop on first failure
dryRunbooleanfalseRender to temp without executing
previewbooleanfalseOutput SQL without executing
outputstring?Write rendered SQL to file

Note: Concurrency defaults to 1 (sequential) because DDL operations often cannot run in parallel.


Template Context

Template Context Object ($)

Available in .sql.tmpl templates via Eta.

PropertyTypeDescription
$.<filename>anyAuto-loaded data from co-located files
$.configobjectActive config values
$.secretsMapConfig-scoped secrets
$.globalSecretsMapApp-level secrets
$.envMapEnvironment variables

Built-in Helpers

HelperSignatureDescription
$.include(path)string → Promise<string>Include another SQL file
$.escape(value)string → stringSQL-escape a string
$.quote(value)any → stringEscape and quote a value
$.json(value)any → stringJSON stringify
$.now()() → stringCurrent ISO timestamp
$.uuid()() → stringGenerate UUID v4

Data File Auto-Loading

Files co-located with templates are automatically loaded.

ExtensionLoaderResult
.json, .json5JSON parserObject
.yaml, .ymlYAML parserObject
.csvCSV parserArray of objects
.js, .mjs, .tsDynamic importDefault export
.sqlFile readString

Data files are available on $ by filename without extension:

sql/
├── users.sql.tmpl      # Template
├── users.json          # Available as $.users
└── seed-data.csv       # Available as $.seedData

Version Management

Version Layers

noorm tracks versions across three layers:

LayerStoragePurpose
schemaDatabase tableTracking table structure
stateState fileEncrypted state format
settingsSettings fileSettings YAML format

Each layer has independent migrations that run automatically when version mismatches are detected.

Current Versions

LayerCurrent Version
schema1
state1
settings1

Lifecycle States

Application States

StateMeaning
idleNot started
startingInitialization in progress
runningNormal operation
shutting_downGraceful shutdown in progress
stoppedClean shutdown complete
failedError during startup or shutdown

Shutdown Phases

Shutdown proceeds through ordered phases:

PhaseOrderPurpose
stopping1Stop accepting new operations
completing2Wait for in-flight operations
releasing3Release database locks
flushing4Flush logger buffers
exiting5Final cleanup

Default Timeouts

PhaseDefault
Operations30 seconds
Locks5 seconds
Connections10 seconds
Logger10 seconds

Database Exploration

The explore module provides schema introspection across dialects.

ExploreCategory

Object types that can be explored:

CategoryDescription
tablesDatabase tables
viewsViews and materialized views
proceduresStored procedures
functionsUser-defined functions
typesCustom types, enums, domains
indexesTable indexes
foreignKeysForeign key constraints
triggersTable triggers
locksActive database locks
connectionsActive sessions

ExploreOverview

Count of objects in each category, returned by getOverview().

FieldTypeDescription
tablesnumberTable count
viewsnumberView count
proceduresnumberStored procedure count
functionsnumberFunction count
typesnumberCustom type count
indexesnumberIndex count
foreignKeysnumberForeign key count
triggersnumberTrigger count
locksnumberActive lock count
connectionsnumberActive connection count

Summary Types

Brief metadata for list views.

TableSummary:

FieldTypeDescription
namestringTable name
schemastring?Schema/database name
columnCountnumberNumber of columns
rowCountEstimatenumber?Estimated row count

ViewSummary:

FieldTypeDescription
namestringView name
schemastring?Schema/database name
columnCountnumberNumber of columns
isUpdatablebooleanWhether view is updatable

IndexSummary:

FieldTypeDescription
namestringIndex name
tableNamestringParent table
columnsstring[]Indexed columns
isUniquebooleanUnique constraint
isPrimarybooleanPrimary key index

ForeignKeySummary:

FieldTypeDescription
namestringConstraint name
tableNamestringSource table
columnsstring[]Source columns
referencedTablestringTarget table
referencedColumnsstring[]Target columns
onDeletestring?Delete action
onUpdatestring?Update action

Detail Types

Full metadata for detail views.

ColumnDetail:

FieldTypeDescription
namestringColumn name
dataTypestringSQL data type
isNullablebooleanAllows NULL
defaultValuestring?Default expression
isPrimaryKeybooleanPart of primary key
ordinalPositionnumberColumn order

TableDetail:

FieldTypeDescription
namestringTable name
schemastring?Schema name
columnsColumnDetail[]All columns
indexesIndexSummary[]Associated indexes
foreignKeysForeignKeySummary[]Outgoing foreign keys
rowCountEstimatenumber?Estimated rows

SQL Terminal

The sql-terminal module provides ad-hoc SQL execution with history tracking.

SqlHistoryEntry

A single query execution record.

FieldTypeDescription
idstringUUID v4 identifier
querystringSQL query executed
executedAtDateExecution timestamp
durationMsnumberExecution duration in ms
successbooleanWhether execution succeeded
errorMessagestring?Error details if failed
rowCountnumber?Rows returned or affected
resultsFilestring?Path to gzipped results

SqlExecutionResult

Full result from query execution.

FieldTypeDescription
successbooleanExecution status
errorMessagestring?Error if failed
columnsstring[]?Column names from result set
rowsobject[]?Row data as key-value objects
rowsAffectednumber?Rows affected (INSERT/UPDATE/DELETE)
durationMsnumberExecution time in ms

SqlHistoryFile

Persistent history stored at .noorm/sql-history/{configName}.json.

FieldTypeDescription
versionstringSchema version
entriesSqlHistoryEntry[]History entries (newest first)

ClearResult

Result of clearing history.

FieldTypeDescription
entriesRemovednumberHistory entries deleted
filesRemovednumberResult files deleted

Summary

noorm's data model spans three tiers with clear separation of concerns:

  1. Encrypted State - Secrets, credentials, configs (.noorm/state.enc)
  2. Settings - Team rules, stages, build config (.noorm/settings.yml)
  3. Database Tables - Execution history, locks, identities (__noorm_*)

The change file system provides versioned changes, while runtime types enable flexible execution modes (dry run, preview, force).

All types follow consistent patterns:

  • Clear status enums for operation tracking
  • Duration timing on all executions
  • Error messages alongside status
  • Checksum-based change detection