NubleStation

The platform schema holds all NubleStation infrastructure tables. These are shared across tenants and managed exclusively by the platform — app developers never access them directly.

Entity Relationship Diagram

ORGANIZATIONS
  │ id, name, domain, created_at

  ├──< USERS (org_id)
  │      id, email, password_hash, role, created_at

  ├──< APPS (org_id)
  │      id, name, slug, created_at
  │      │
  │      ├──< API_KEYS (app_id)
  │      │      id, key_id, secret_hash, revoked_at, created_at
  │      │
  │      ├──< USER_APP_ACCESS (app_id)
  │      │      id, user_id, role, created_at
  │      │
  │      ├──< APP_TABLES (app_id)
  │      │      id, table_name, created_at
  │      │
  │      ├──< DEPLOYMENTS (app_id)
  │      │      id, version, status, deployed_at, created_at
  │      │
  │      └──< MIGRATIONS (app_id)
  │             id, version, checksum, applied_at, created_at

  ├──< AUDIT_LOG (org_id, app_id, user_id)
  │      id, action, metadata (jsonb), created_at

  └── SCHEMA_VERSION (standalone)
         id, version, checksum, applied_at, created_at

Table reference

organizations

One row per NubleStation install. Holds the clinic’s identity.

ColumnTypeNotes
iduuidPrimary key
nametextHuman name, e.g. “Clinic Sidi Youssef”
domaintextSubdomain root, e.g. “clinic” → *.clinic.local
created_attimestamptzInstall timestamp

users

Every human who can log in. One identity, many app accesses.

ColumnTypeNotes
iduuidPrimary key
org_iduuidFK → organizations
emailtextUnique, used for login
password_hashtextArgon2id hash
roletextPlatform role: admin, developer, user
created_attimestamptz

apps

Each app the admin creates. Determines a subdomain, a tenant scope, and credentials.

ColumnTypeNotes
iduuidPrimary key — used as app_id / tenant discriminator
org_iduuidFK → organizations
nametextDisplay name
slugtextUnique — used as subdomain (taskstasks.clinic.local)
created_attimestamptz

api_keys

Developer credentials for SDK and CLI authentication.

ColumnTypeNotes
iduuidPrimary key (used as Phase 1 user_id placeholder)
app_iduuidFK → apps
key_idtextIndexed, plaintext — used for O(1) gateway lookup
secret_hashtextArgon2id of the secret — never the plaintext
labeltextOptional human label
revoked_attimestamptzSet to revoke; null = active
expires_attimestamptzOptional expiry; null = never
created_attimestamptz

Key format: nbl_<key_id>.<secret>. The gateway splits on ., looks up key_id, verifies secret with Argon2.

user_app_access

Authorization matrix: which user can use which app, and with what role.

ColumnTypeNotes
iduuidPrimary key
user_iduuidFK → users
app_iduuidFK → apps
roletextApp-defined role (e.g., doctor, nurse, admin)
created_attimestamptz

A user not present in this table for an app cannot access that app’s data through tenant_data.users view.

app_tables

Registry of which custom table names belong to which app. The REST router uses this — never information_schema.

ColumnTypeNotes
iduuidPrimary key
app_iduuidFK → apps
table_nametextPhysical table name in tenant_data schema
created_attimestamptz

Table names are org-wide unique. The first app to claim tasks defines its columns. A second app with an incompatible tasks schema is rejected.

deployments

Frontend version history per app.

ColumnTypeNotes
iduuidPrimary key
app_iduuidFK → apps
versiontextSemver or git SHA
statustextdeployed, rolled_back
deployed_attimestamptz
created_attimestamptz

migrations

Applied developer SQL migration log per app.

ColumnTypeNotes
iduuidPrimary key
app_iduuidFK → apps
versiontextFilename, e.g. 001_create_tasks.sql
checksumtextSHA-256 of file content — editing an applied migration is refused
applied_attimestamptz
created_attimestamptz

schema_version

Tracks NubleStation’s own platform-schema migrations. Separate from migrations (which tracks developer migrations).

ColumnTypeNotes
iduuidPrimary key
versiontextPlatform schema version (e.g., 0.3.0)
checksumtextSHA-256 of the migration SQL
applied_attimestamptz
created_attimestamptz

Applied at DB service boot, before the service accepts traffic. If this migration fails, the container exits non-zero rather than serving on a half-migrated schema.

audit_log

Append-only compliance trail for sensitive actions.

ColumnTypeNotes
iduuidPrimary key
org_iduuidFK → organizations
app_iduuidFK → apps (nullable for org-level actions)
user_iduuidFK → users (nullable for system actions)
actiontexte.g., user.login, api_key.revoke, query.named
metadatajsonbAction-specific details
created_attimestamptz

No UPDATE or DELETE is permitted on this table. It is written by platform middleware, never by app code.