# Wallboard Platform Core Concepts

Enterprise digital signage CMS for managing screens at scale.

## Entity Hierarchy

```
Customer (tenant)
├── DeviceGroups (folders) → Devices
├── FileFolders → Files (media)
├── ContentGroups (folders) → Content/Slides/Playlists
├── Campaigns → MessageGroups → Messages
│   ├── level=WIDGET: Channels (content orchestration)
│   └── level=TOP: Schedules (content override)
├── DataSources
├── Teams → Users (many-to-many)
├── Tags
├── QuickFilters
├── Actions (webhooks)
├── AlertRules
├── Advertisers
├── LicenseOrders
├── UserInterfaceProfiles
├── Logs (audit trail)
├── DeviceMetrics (monitoring)
└── ProofOfPlay (playback logs)
```

## Folders

Three folder types: `deviceGroup`, `fileFolder`, `contentGroup`

**Root folders**: One per type per tenant (`parentId == null`). Cannot be renamed.

## Teams & Access Control

- **Many-to-many**: Users ↔ multiple teams, resources ↔ multiple teams
- Team membership determines resource access
- Roles: Administrator, Technical Manager, Content Manager, Content Editor, View Only

**Visibility rules**:
- OWNER role: sees ALL resources, cannot be assigned to teams
- Resources without team: global setting per customer (visible to all OR visible to none)

## Content Delivery

### 1. Direct Assignment
Content/Playlist → Device. Simple, one base content at a time.

### 2. Channel System
Multi-content orchestration with balancing. **Channels play through Channel Widgets** embedded in Content/Slides - not directly on devices.

```
Content (with Channel Widget)
└── Main Channel (Campaign, level=WIDGET)
    ├── Sub-Channel Groups (MessageGroup) ← mandatory wrapper
    │   └── Sub-Channels (Message) → Content
    └── saturation (weight) for playback balancing
```

**Constraint**: Channels can only contain ONE content type (no mixing media+slides).

**Device Selection** uses `deviceSelectionMode`:
- **STATIC**: Manual only
- **DYNAMIC**: Manual + tags + folders (AND/OR logic)
- **QUICK_FILTER**: WBQL query

**Content Selection** methods can be combined:
- Manual item selection
- Tag-based (auto-include matching)
- Folder-based (auto-include from folders)
- Team filtering
- Quick Filter (WBQL)

**Tag-based targeting**: Device tags filter which devices receive the channel; content tags auto-include matching content. Can combine (e.g., retail content → lobby devices).

**Hierarchical Delegation**: Main channels (corporate) → sub-channel groups (regional) → sub-channels (local).

### 3. Schedule Override
Temporary content replacement using Campaign with `level=TOP`.

## Scheduling System

### Scheduling Types

| Type | Scope | Per-Item? |
|------|-------|-----------|
| Playlist page scheduling | Pages in playlist (simpleLoop) | YES |
| Content page scheduling | Pages in multi-page content | YES |
| Schedule override | Device content replacement | NO |
| Channel/sub-channel scheduling | Channel level | NO |

### AND Logic
All schedules use AND: parent + child must both be active.

### Content Priority on Device
1. **Emergency** (highest) - triggered via UI, CAP alerts, API
2. **Active Schedule** - Campaign with level=TOP
3. **Base Content** - directly assigned

When multiple schedules overlap: higher priority wins (tie-breaker: first created). API field: `weight`.

## File Validity

`validFrom`/`validTo` timestamps cause files to be **skipped outside validity window** in: playlists, channels (ASSETS_STATIC/DYNAMIC), folder-connected galleries. Direct widget references unaffected.

## Device System

**Registration**: 4-digit code, serial number, or pre-registration

**Preview**: `previewUrl` (current screenshot), `previewStore` (historical)

**Commands** (batch operations via criteria):
- **Content**: assign, detach, refresh
- **Display**: on/off, brightness, volume, rotation
- **Power**: restart, scheduled reboot, working hours
- **Cache**: cache files/content, clear cache
- **Config**: timezone, location, sensor config, advanced config, lock (kiosk)
- **Updates**: update app, set version limit, update rule
- **Debug**: request logs, show console/name/device info, recovery mode

## Data Binding

Widgets bind to DataSource fields for dynamic content.

**EDIT permission** (Internal datasources only): Team-based permission that allows editing data directly on any screen displaying it, without needing content access. Enables domain experts (e.g. pricing manager) to update data from any device showing it.

## Internal Datasource Data

Internal datasources (`sourceType: INTERNAL`) store user-managed JSON data, writable via API or UI. External/system datasources pull data automatically and are read-only. Data structure depends on `structureType` (table, key-value, custom, etc.) and is consumed by widgets via data binding.

## Data Model Architecture

Two fundamentally different storage models:

**JSON Document Storage** (Content, Slide, Playlist, Datasource data):
- Entire entity stored as one large JSON blob
- Must read/write the complete object - no partial updates
- Pages, items, widgets, animations all nested within
- API: GET returns full JSON, PUT replaces entire structure

**Normalized Database** (Channels, Schedules, Messages, Devices, etc.):
- Standard relational tables with foreign keys
- Individual fields and relationships can be modified independently
- Nested entities (MessageGroup → Message) are separate API resources
- API: PATCH updates specific fields only

## Actions (Integrations)

Pre-configured actions (~80 types) for external system integration. API-key-authenticated webhook calls supply an `eventId` → Wallboard executes the matching action. Targets: Device, Datasource, Campaign, Folder. Webhook key secrets are UI-only for AI workflows.
