12 KiB
Database Schema
This app creates and maintains its schema at startup through src/db/index.js.
The sections below summarize the current tables and their purpose.
Tables generally use a numeric auto-increment id primary key. The relationship table d_announcement_screens intentionally uses the composite (announcement_id, screen_id) primary key instead. Natural and relationship keys remain as unique constraints where needed. Timestamps are stored as created_at and modified_at when a table supports auditing.
Admin
a_users- admin user accounts and password hashes.a_roles- named role definitions.a_permissions- permission catalog seeded from the application constants.a_role_permissions- many-to-many mapping between roles and permissions.a_user_roles- many-to-many mapping between users and roles.a_sessions- persisted admin session tokens.
a_users
id,name,username,password_hash,password_salt,password_iterations,must_change_password,account_locked,created_at,created_by,modified_at,modified_byusernameis unique.
a_roles
id,role_key,name,description,created_at,created_by,modified_at,modified_byrole_keyis unique.nameis unique.
a_permissions
id,permission_key,name,section_name,description,created_at,modified_atpermission_keyis unique.
a_role_permissions
id,role_id,permission_id,created_at,modified_at- Foreign keys:
-
role_id->a_roles.id-permission_id->a_permissions.id - Unique key:
(role_id, permission_id)
a_user_roles
id,user_id,role_id,created_at,modified_at- Foreign keys:
-
user_id->a_users.id-role_id->a_roles.id - Unique key:
(user_id, role_id)
a_sessions
id,session_hash,user_id,ip_address,user_agent,expires_at,created_at,created_by,last_used_at,modified_bysession_hashis unique.- Foreign key:
-
user_id->a_users.id
Content
c_canvas_sizes- reusable canvas presets for templates.c_playlists- playlist definitions, playback options, and canvas assignment.c_templates- slide templates with canvas and background settings.c_template_regions- template region layout and metadata.c_slides- slide records with template binding, JSON content, and thumbnail path.c_playlist_slides- ordered playlist items and timing.c_playlist_slide_schedule_rules- rule rows attached to playlist slides.
c_canvas_sizes
id,name,width,height,created_at,created_by,modified_at,modified_by(width, height)is unique.
c_playlists
id,name,fade_between_slides,skip_unavailable_rtmp,canvas_id,created_at,created_by,modified_at,modified_by- Foreign key:
-
canvas_id->c_canvas_sizes.idwithON DELETE SET NULL
c_templates
id,name,canvas_size_id,background_image_path,background_color,background_gradient,created_at,created_by,modified_at,modified_bybackground_gradientstores normalized linear gradient settings as JSON text, including angle and colour stops.- Foreign key:
-
canvas_size_id->c_canvas_sizes.idwithON DELETE SET NULL
c_template_regions
id,template_id,region_key,region_type,label,font_family,lock_ratio,animation_json,x,y,width,height,z_index,created_at,created_by,modified_at,modified_by- Foreign key:
-
template_id->c_templates.idwithON DELETE CASCADE
c_slides
id,title,template_id,content_json,thumbnail_path,created_at,created_by,modified_at,modified_by- Foreign key:
-
template_id->c_templates.idwithON DELETE SET NULL
c_playlist_slides
id,playlist_id,slide_id,position,duration_seconds,use_video_duration,disable_audio,created_at,created_by,modified_at,modified_by- Foreign keys:
-
playlist_id->c_playlists.idwithON DELETE CASCADE-slide_id->c_slides.idwithON DELETE CASCADE
c_playlist_slide_schedule_rules
-
id,playlist_slide_id,position,start_datetime,end_datetime,start_time,end_time,schedule_days_json,created_at,created_by,modified_at,modified_by -
Foreign key: -
playlist_slide_id->c_playlist_slides.idwithON DELETE CASCADE -
Index: -
(playlist_slide_id, position) -
Each playlist slide can have zero or more schedule rules.
-
Rules are evaluated with OR across rows and with AND across the fields inside a single rule.
Devices
d_players- player registry and connection metadata.d_screens- screen records and playlist assignment.d_onboarding_devices- device-to-screen bindings and onboarded client names.
d_players
id,identifier,public_base_url,internal_base_url,last_seen_at,created_at,modified_atidis the primary key.identifieris unique and is the stable player identity used by the app.
d_screens
-
id,name,slug,playlist_id,created_at,created_by,modified_at,modified_by -
slugis unique. -
Foreign keys: -
playlist_id->c_playlists.idwithON DELETE SET NULL -
Screens are no longer tied to a player foreign key directly; player registration and live connection metadata are tracked separately in
d_players.
d_onboarding_devices
id,device_id,client_name,screen_id,created_at,created_by,modified_at,modified_bydevice_idis unique.- Foreign key:
-
screen_id->d_screens.idwithON DELETE SET NULL
Onboarding
- The onboarding flow uses
d_onboarding_devicesto bind a device to a screen and persist the client name.
Announcements
d_announcements- announcement content and display metadata.d_announcement_screens- announcement-to-screen assignments.
d_announcements
id,message,short_label,announcement_type,color_key,icon_key,duration_seconds,expires_at,created_at,created_by,modified_at,modified_byannouncement_typedefaults tolower-third.
d_announcement_screens
announcement_id,screen_id,created_at,created_by,modified_at,modified_by- Foreign keys:
-
announcement_id->d_announcements.idwithON DELETE CASCADE-screen_id->d_screens.idwithON DELETE CASCADE - Unique key:
(announcement_id, screen_id)
Integrations
i_rss_feeds- RSS feed definitions and refresh cadence.i_rss_feed_items- cached RSS feed items.i_api_sources- API source definitions and last response snapshot.i_timetable_groups- grouped timetable definitions used by the timetable region.i_timetable_entries- dated entries that belong to a timetable group.
i_rss_feeds
id,name,feed_url,update_interval_value,update_interval_unit,item_limit,enabled,last_pulled_at,created_at,created_by,modified_at,modified_by
i_rss_feed_items
id,rss_feed_id,position,item_json,created_at,created_by,modified_at,modified_by- Foreign key:
-
rss_feed_id->i_rss_feeds.idwithON DELETE CASCADE - Unique key:
-
(rss_feed_id, position)
i_api_sources
id,name,api_url,auth_method,auth_username,auth_password,auth_bearer_token,auth_header_name,auth_header_value,items_path,update_interval_value,update_interval_unit,enabled,last_pulled_at,last_pull_error,last_response_status,last_response_content_type,last_response_json,created_at,created_by,modified_at,modified_by
i_weather_locations
id,name,location_label,latitude,longitude,timezone,provider,temperature_unit,wind_unit,precipitation_unit,update_interval_value,update_interval_unit,enabled,last_pulled_at,last_pull_error,last_response_json,created_at,created_by,modified_at,modified_by- Stores configured weather locations and the most recent provider response used for forecast previews and weather regions.
i_timetable_groups
id,name,short_description,timezone,created_at,created_by,modified_at,modified_bytimezonedefaults toEurope/London.
i_timetable_entries
id,schedule_group_id,title,short_description,start_datetime,end_datetime,created_at,created_by,modified_at,modified_by- Foreign key:
-
schedule_group_id->i_timetable_groups.idwithON DELETE CASCADE - Index:
-
(schedule_group_id, start_datetime)
Operations
o_background_tasks- queue and history for background jobs.o_app_state- generic app state and version markers stored as key/value pairs.o_app_settings- administrator-configurable application settings stored by key.o_audit_events- retained audit events for administrator activity and system changes.
o_background_tasks
id,task_key,task_type,title,category,status,payload_json,metadata_json,attempts,created_at,created_by,started_at,finished_at,error_message- Indexed by
status,task_key, andtask_type.
o_app_state
id,state_key,state_value,created_at,modified_atstate_keyis unique.schema_versionis stored here so startup can detect the previously recorded schema version before deciding whether migrations need to run.
o_app_settings
id,setting_key,setting_value,created_at,created_by,modified_at,modified_bysetting_keyis unique.- Values are stored as JSON and validated against the application setting definitions in
src/data/app-settings.js.
o_audit_events
id,occurred_at,category,event_type,actor_user_id,target_type,target_id,target_label,ip_address,user_agent,details_json- Indexed by occurrence time, category and event type, actor, and target.
Notes
- The schema is initialized with
CREATE TABLE IF NOT EXISTS, so new installs can start from an empty database. src/db/bootstrap.jsseeds the canvas size defaults, default permissions, and the default administrator role.src/db/migrations.jsrecords the current schema version ino_app_stateduring startup so later launches can tell whether an update is happening.
erDiagram
A_USERS {
}
A_ROLES {
}
A_PERMISSIONS {
}
A_ROLE_PERMISSIONS {
}
A_USER_ROLES {
}
A_SESSIONS {
}
C_CANVAS_SIZES {
}
C_PLAYLISTS {
}
C_TEMPLATES {
}
C_TEMPLATE_REGIONS {
}
C_SLIDES {
}
C_PLAYLIST_SLIDES {
}
C_PLAYLIST_SLIDE_SCHEDULE_RULES {
}
D_PLAYERS {
}
D_SCREENS {
}
D_ONBOARDING_DEVICES {
}
D_ANNOUNCEMENTS {
}
D_ANNOUNCEMENT_SCREENS {
}
I_RSS_FEEDS {
}
I_RSS_FEED_ITEMS {
}
I_API_SOURCES {
}
I_TIMETABLE_GROUPS {
}
I_TIMETABLE_ENTRIES {
}
O_APP_STATE {
}
O_APP_SETTINGS {
}
O_BACKGROUND_TASKS {
}
O_AUDIT_EVENTS {
}
A_USERS ||--o{ A_USER_ROLES : has
A_ROLES ||--o{ A_USER_ROLES : assigned_to
A_ROLES ||--o{ A_ROLE_PERMISSIONS : has
A_PERMISSIONS ||--o{ A_ROLE_PERMISSIONS : granted_to
A_USERS ||--o{ A_SESSIONS : owns
A_USERS ||--o{ O_AUDIT_EVENTS : acts
C_CANVAS_SIZES ||--o{ C_TEMPLATES : used_by
C_CANVAS_SIZES ||--o{ C_PLAYLISTS : used_by
C_TEMPLATES ||--o{ C_TEMPLATE_REGIONS : contains
C_TEMPLATES ||--o{ C_SLIDES : used_by
C_PLAYLISTS ||--o{ C_PLAYLIST_SLIDES : contains
C_SLIDES ||--o{ C_PLAYLIST_SLIDES : included_in
C_PLAYLIST_SLIDES ||--o{ C_PLAYLIST_SLIDE_SCHEDULE_RULES : has_rules
C_PLAYLISTS ||--o{ D_SCREENS : uses
D_SCREENS ||--o{ D_ONBOARDING_DEVICES : binds
D_ANNOUNCEMENTS ||--o{ D_ANNOUNCEMENT_SCREENS : targets
D_SCREENS ||--o{ D_ANNOUNCEMENT_SCREENS : receives
I_RSS_FEEDS ||--o{ I_RSS_FEED_ITEMS : caches
I_TIMETABLE_GROUPS ||--o{ I_TIMETABLE_ENTRIES : contains