Proprietary — Uued Viljapuuaiad OÜ / Code Zero Group — All Rights Reserved
Nexus — Engineering
v1.0.0 2026-03-25 DB: admin/admin.db (SQLite)

Data Model

Current schema (admin/admin.db), target schema additions (audit trail, RBAC keys), PFP rule JSON schema, ingestion YAML schema, and DeltaPrism migration path. PostgreSQL is the medium-term production target.

2 Current Tables 2 Target Tables DeltaPrism: Future
01 Current Schema

Database: admin/admin.db (SQLite). Shared by FastAPI engine and Flask admin panel via filesystem. Both services use plain sqlite3 or SQLAlchemy respectively — no ORM dependency in the engine.

TableRowsPurpose
_tbl_calcrule_profiles4Versioned domain-scoped rule containers
_tbl_calcrule_rules1,213+Individual calculation rules (229 TCO + 535 PFP formula + 430 PFP table + 19+ EDR)
_tbl_nexus_platform_userslivePlatform users registered via Google OAuth 2.0 — role-based access control
02 _tbl_calcrule_profiles

Stores calculation profiles. Each profile is a versioned, domain-scoped container for rules. At most one profile can be active per domain.

CREATE TABLE _tbl_calcrule_profiles (



    id                  INTEGER PRIMARY KEY AUTOINCREMENT,



    slug                TEXT UNIQUE NOT NULL,



        -- 'tco-dc-cooling', 'pfp-clearance-hdb', 'edr-entity-validation'



    name                TEXT NOT NULL,



        -- 'TCO Calculator — Data Centre Cooling'



    description         TEXT,



    technology_variants TEXT DEFAULT '[]',



        -- JSON array: '["traditional","rdhx","dlc","grc"]'



    domain              TEXT NOT NULL DEFAULT 'tco',



        -- Bounded context: 'tco' | 'edr' | 'pfp' | 'pfp_table'



    is_active           INTEGER NOT NULL DEFAULT 0,



        -- 1 = active within domain. At most one active per domain.



    version             TEXT DEFAULT '1.0.0',



    created_at          DATETIME DEFAULT CURRENT_TIMESTAMP,



    updated_at          DATETIME DEFAULT CURRENT_TIMESTAMP



);

Current rows:

idslugdomainrulesis_active
1tco-dc-coolingtco2291
2pfp-clearance-hdbpfp5351
3pfp-tablepfp_table4301
4edr-entity-validationedr19+1
03 _tbl_calcrule_rules

Stores individual calculation rules. Each rule belongs to exactly one profile. Rules are executed in descending priority order within a pipeline run.

CREATE TABLE _tbl_calcrule_rules (



    id             INTEGER PRIMARY KEY AUTOINCREMENT,



    profile_id     INTEGER NOT NULL REFERENCES _tbl_calcrule_profiles(id) ON DELETE CASCADE,



    rule_id        TEXT NOT NULL,



        -- Logical ID: 'pfp_hdb_clr_002', 'infra_001_servers_per_rack'



    name           TEXT NOT NULL,



    formula        TEXT NOT NULL,



        -- Python expression evaluated in sandboxed namespace



    output         TEXT,



        -- Dot-path output field: 'result.clearance_mm', 'capex.racks_capex'



    rule_type      TEXT,



        -- 'pfp_clearance' | 'pfp_selection' | 'pfp_sza'



        -- 'infrastructure' | 'capex' | 'opex' | 'tco' | 'scoring' | 'edr_validation'



    technology     TEXT,



        -- NULL = all; 'traditional' | 'rdhx' | 'dlc' | 'grc' | 'hdb' | 'fs'



    priority       INTEGER DEFAULT 0,



        -- Execution order: higher runs first



    enabled        INTEGER NOT NULL DEFAULT 1,



    skip_if_set    INTEGER NOT NULL DEFAULT 0,



        -- If 1: skip when output field already has a non-None value



    excel_source   TEXT,



    excel_baseline REAL,



    description    TEXT,



    created_at     DATETIME DEFAULT CURRENT_TIMESTAMP,



    updated_at     DATETIME DEFAULT CURRENT_TIMESTAMP,



    UNIQUE (profile_id, rule_id)



);
04 Target Schema Additions Not Yet Built

_tbl_calcrule_rule_audit — GAP-05

Audit trail for rule mutations. Write one row per changed field in every PATCH handler before applying the update. Enables GET /rules/{id}/history.

CREATE TABLE _tbl_calcrule_rule_audit (



    id          INTEGER PRIMARY KEY AUTOINCREMENT,



    rule_id     TEXT    NOT NULL,



        -- Logical rule_id (not FK — preserves history after delete)



    profile_id  INTEGER,



    changed_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,



    changed_by  TEXT,



        -- API key prefix (first 8 chars) or 'admin-panel'



    operation   TEXT NOT NULL,



        -- 'CREATE' | 'PATCH' | 'DELETE'



    field       TEXT,



        -- Field name changed (NULL for CREATE/DELETE)



    old_value   TEXT,



        -- JSON-serialised previous value



    new_value   TEXT



        -- JSON-serialised new value



);



CREATE INDEX idx_audit_rule_id   ON _tbl_calcrule_rule_audit(rule_id);



CREATE INDEX idx_audit_changed_at ON _tbl_calcrule_rule_audit(changed_at);

_tbl_api_keys — GAP-02

RBAC key store. Keys stored as SHA-256 hashes. Per-key scopes and expiry. Replace env-var comparison in require_api_key with hash lookup against this table.

CREATE TABLE _tbl_api_keys (



    id          INTEGER PRIMARY KEY AUTOINCREMENT,



    key_hash    TEXT UNIQUE NOT NULL,



        -- SHA-256 of the raw key — never store plaintext



    client_id   TEXT NOT NULL,



        -- 'pyrometrix-revit', 'admin', 'ci-pipeline'



    scopes      TEXT NOT NULL DEFAULT '["compute"]',



        -- JSON array: ["compute"] | ["compute","rules:read"] | ["admin"]



    expires_at  DATETIME,



        -- NULL = never expires (dev/internal only)



    created_at  DATETIME DEFAULT CURRENT_TIMESTAMP,



    last_used   DATETIME,



    enabled     INTEGER NOT NULL DEFAULT 1



);
05 PFP Rule JSON Schema

Format used in nexus/rules/pfp/*.json. These files are import-format only — the DB is the runtime source of truth after seeding.

{



  "id":          "pfp_hdb_clr_002",



  "name":        "HDB EI60 Clearance — Double Drywall",



  "type":        "pfp_clearance",



  "technology":  "pfp",



  "priority":    6998,



  "formula":     "result.clearance_mm = 25 if (...) else None",



  "output":      "result.clearance_mm",



  "skip_if_set": true,



  "enabled":     true,



  "description": "Clearance for EI60 rated HDB penetration through DBL DW",



  "ruleset":     "HDB"



}
FieldRequiredDescription
idYesLogical rule ID, unique within profile
nameYesHuman-readable name
typeYesRule type: pfp_clearance, pfp_selection, pfp_sza
priorityYesExecution order (higher = first)
formulaYesPython expression evaluated in sandboxed namespace
outputYesDot-path output field target
skip_if_setNoIf true: skip when output field already has a non-None value
technologyNoScope limiter: hdb or fs
rulesetNoSource ruleset label: HDB or FS
06 PFP Table Pipeline Row Schema

Lookup-table format used in nexus/rules/pfp/table_*.json. Row matching uses hierarchical specificity: cat_acat_gcat_cposition. More specific matches win over general matches.

{



  "id":           "tbl_hdb_001",



  "type":         "pfp_table_row",



  "s1": { "cat_a": "Pipe", "cat_g": "Steel", "cat_c": null },



  "s2": { "cat_a": "Wall", "cat_g": "Concrete", "cat_c": null },



  "fire_rating":  "EI60",



  "position":     null,



  "clearance_mm": 25,



  "top_mm":       25,



  "side_mm":      25,



  "bottom_mm":    25



}
07 Ingestion Config YAML Schema

Files in nexus/config/datasources/*.yaml drive IngestionPipeline. The type field selects the DataSource connector backend.

name:        edr-uatdb



description: "EDR v6 UAT2 SQLite database"



pipeline:    edr







source:



  type: sqlite           # sqlite | csv | json | excel | access | postgres | odbc | rest



  path: "/path/to/db"







extractors:



  - id: equipment



    table: FACT_100_Equip_UAT2



    entity_class: Equipment



    limit: 2000



    field_map:



      Equipment_Tag: entity.tag



      Description:   entity.description



    value_filters:



      Status: ["Active", "Commissioned"]



    class_rules:



      - field: entity.tag



        pattern: "^EL[-_]"



        entity_class: Electrical

Supported connector types: sqlite, csv, json, excel, access (.accdb via pyodbc), postgres, odbc, rest

08 DeltaPrism Migration Path (Future)

Target architecture: rules stored as graph nodes in DeltaPrism property graph database. Enables dependency analysis, version history as edges, and conflict detection between rules.

Node: Rule



  Properties: id, name, formula, priority, output, type, technology, skip_if_set



  Edges:



    BELONGS_TO     → Profile node



    DEPENDS_ON     → Rule node  (formula references output of another rule)



    SUPERSEDES     → Rule node  (version history)



    CONFLICTS_WITH → Rule node  (same output, overlapping conditions)







Node: Profile



  Properties: slug, name, domain, version, is_active



  Edges: HAS_RULE → Rule







Node: Domain



  Properties: key (tco | edr | pfp), description



  Edges: HAS_PROFILE → Profile

Integration: profile_store.py gains a NEXUS_RULE_STORE=deltaprism backend switch. The existing connector layer (datasource.py) can reach DeltaPrism via ODBC or REST. No changes to the rule execution engine or API surface required.

_tbl_nexus_platform_users — NexusPlatformUser

Platform-level user registry. Every user who completes Google OAuth for the first time gets a row. Org-level access is governed separately by org_user. Role nexus_admin grants access to all nav groups and platform management. Added 2026-05-11, deployed as engine task def nexus-prod-engine:10. Login is broken in production (ISSUE-073 — see _STATE_STORE root cause). All auth/user management endpoints implemented in Wormwood routes_auth.py.

CREATE TABLE _tbl_nexus_platform_users (

    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    google_sub      TEXT NOT NULL UNIQUE,   -- Google subject identifier (immutable)
    email           TEXT NOT NULL UNIQUE,   -- verified Google email address
    display_name    TEXT,                   -- full name from Google profile
    picture_url     TEXT,                   -- Google profile photo URL (max 512 chars)
    nexus_role      TEXT NOT NULL DEFAULT 'nexus_user',
                                            -- 'nexus_user' | 'nexus_admin'
    is_active       INTEGER NOT NULL DEFAULT 1,
                                            -- 0 = account deactivated (login blocked)
    role_updated_at DATETIME,               -- timestamp of last role change (UTC)
    role_updated_by TEXT,                   -- email of admin who last changed the role
    created_at      DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_login_at   DATETIME                -- updated on every successful login
);

CREATE UNIQUE INDEX uq_npu_google_sub ON _tbl_nexus_platform_users (google_sub);
CREATE UNIQUE INDEX uq_npu_email      ON _tbl_nexus_platform_users (email);
ColumnTypeConstraintsDescription
idINTEGERPK, AUTOINCREMENTInternal surrogate key. Used as sub in Nexus JWT.
google_subTEXT(128)UNIQUE, NOT NULL, indexedGoogle’s stable user identifier from id_token.sub. Never changes even if email changes.
emailTEXT(255)UNIQUE, NOT NULL, indexedVerified Google email. Used to match legacy rows on first OAuth login.
display_nameTEXT(200)NULLFull name from Google profile. Updated on login if Google picture_url changes.
picture_urlTEXT(512)NULLGoogle profile photo CDN URL. Refreshed on every login if changed.
nexus_roleTEXT(30)NOT NULL, default nexus_userPlatform RBAC role. Values: nexus_user (default), nexus_admin. Overridden by NEXUS_ADMIN_EMAILS on every login.
is_activeINTEGER (bool)NOT NULL, default 1Account activation flag. 0 = deactivated; login blocked at OAuth callback with HTTP 403 / code account_deactivated. Set by admin via PATCH /auth/users/{id}/active. Data is retained when deactivated (no DELETE). Requires migration: ALTER TABLE ... ADD COLUMN is_active INTEGER NOT NULL DEFAULT 1.
role_updated_atDATETIMENULLTimestamp (UTC) of the last nexus_role change. Set by PATCH /auth/users/{id}/role. NULL on initial registration.
role_updated_byTEXT(255)NULLEmail of the nexus_admin who last changed this user’s role. Stored from the JWT email claim of the requesting admin. Provides audit trail without a separate audit log table.
created_atDATETIMEDEFAULT CURRENT_TIMESTAMPFirst registration timestamp (UTC).
last_login_atDATETIMENULLUpdated on every successful GET /auth/callback completion.

Upsert logic (routes_auth.py)

1. Query by google_sub
2. If not found: query by email (legacy row migration)
   2a. If found: set google_sub on existing row
   2b. If not found: INSERT new row with nexus_role='nexus_user'
3. If email in NEXUS_ADMIN_EMAILS: SET nexus_role='nexus_admin'
4. UPDATE last_login_at = NOW(UTC)
5. UPDATE picture_url if changed
6. COMMIT

JWT payload emitted after upsert

{
  "sub":   <user.id>,          // integer
  "email": <user.email>,
  "name":  <user.display_name>,
  "role":  <user.nexus_role>,   // 'nexus_user' | 'nexus_admin'
  "iat":   <unix timestamp>,
  "exp":   <iat + 28800>        // 8-hour validity
}

API endpoints (routes_auth.py)

MethodPathAuthResponse
GET/auth/googleNone302 → Google consent screen
GET/auth/callbackNone (OAuth)302 → SPA #token= or #auth_error=
GET/auth/meBearer JWT{id, email, display_name, picture_url, nexus_role, created_at, last_login_at}
PATCH/auth/meBearer JWTUpdated user dict
GET/auth/usersBearer JWT (nexus_admin)Array of all NexusPlatformUser records (REQ-AUTH-005 — IMPLEMENTED, ISSUE-073 pending)
PATCH/auth/users/{id}/roleBearer JWT (nexus_admin)Updated user; 409 if self-demotion (REQ-AUTH-005 — IMPLEMENTED, ISSUE-073 pending)
PATCH/auth/users/{id}/activeBearer JWT (nexus_admin)Updated user; 409 if self-deactivation (REQ-AUTH-005 — IMPLEMENTED, ISSUE-073 pending)

Migration (executed) — is_active + role audit columns

Columns is_active, role_updated_at, role_updated_by are defined in admin/models.py and were added to the production database as part of engine:10 deployment (ISSUE-073). SQLAlchemy create_all() does NOT add columns to existing tables — explicit ALTER TABLE migration was required.

-- migrate_m_nexus_06.py (executed — engine:10)
ALTER TABLE _tbl_nexus_platform_users ADD COLUMN is_active INTEGER NOT NULL DEFAULT 1;
ALTER TABLE _tbl_nexus_platform_users ADD COLUMN role_updated_at DATETIME;
ALTER TABLE _tbl_nexus_platform_users ADD COLUMN role_updated_by TEXT;