the SESAME reference implementation · open source · written in Rust

rust-pois

A complete POIS / ESAM server you can actually run.

A lightweight, self-contained Rust server for Program Opportunity Information Service (POIS) and ESAM workflows: a REST/JSON API, a web UI, and SQLite persistence for channels, rules, and ESAM event logs. It is also where SESAME lives in practice, the working implementation the protocol and its conformance vectors were extracted from.

Run it in minutes $git clone https://github.com/bokelleher/rust-poiscopy
REST/JSON API + web UI SCTE-35 build · decode · validate SESAME security built in SQLite, zero external services
The console

Channels, rules, and signals in one place.

Define channels, attach priority-ordered conditioning rules, and watch ESAM signals resolve against them in real time. The whole control surface ships in the binary, served from the server itself.

What it does

A full POIS, not a stub.

Everything needed to receive ESAM, decide policy, and prove what happened, in one binary you control.

Channels & rules engine

Per-channel, priority-ordered rules with match conditions and conditioning actions. A default channel and a noop rule are seeded on first start, so the box is useful out of the box.

Event Monitor

Live ESAM event logging and monitoring. Every signal that arrives is recorded with the rule it matched and the action taken, so the decision history is auditable.

SCTE-35 tools

Build, decode, and validate SCTE-35 in the browser. The decoder accepts base64, hex, or binary input and breaks the message down field by field.

SESAME security built in

All three SESAME tiers wired straight through the ESAM path, verifying inbound requests and signing outbound responses. See the protocol →

Projects & templates

Save a rule as a template and group rules into projects, so a working policy on one channel can be reused and rolled out across feeds instead of rebuilt by hand.

Groups & users (RBAC)

User accounts, groups, and role-based access over a bearer-authenticated management API, so operators and integrations get only the scope they need.

SQLite persistence

Channels, rules, and events persist in a single SQLite file. Schema migrations run automatically on first start. No database server to stand up.

Deploy anywhere

One-shot install on Ubuntu 24.04 (builds from source, sets up a systemd unit). Optional TLS via POIS_TLS_CERT / POIS_TLS_KEY. Zero dependencies beyond SQLite and Rust.

REST/JSON API

Everything in the UI is an API call. Manage channels, rules, projects, and users programmatically, or drive the ESAM endpoint directly from an encoder, packager, or SAS.

The rules engine

Match the signal, decide the action.

Each channel holds an ordered list of rules. A signal is evaluated in priority order; the first match wins. Rules match on UPID, time window, or SCTE-35 segmentation type, and resolve to a conditioning action with explicit parameters. These four ship as a demonstration policy on RegionalAffiliate.

Region-tagged UPID replace priority 10
Match
UPID matches *AFE1*
Action
Built splice_insert ad-out, 15s
Prime-time window replace priority 20
Match
UTC time between 18:00 and 23:00 (utcBetween)
Action
Built splice_insert ad-out, 45s
Catch-all pass-through noop priority 100
Match
Matches every signal (catch-all)
Action
Original signal passed through unchanged
Regional blackout (program start) blackout disabled priority 110
Match
Segmentation type 0x10 (Program Start)
Action
Delivery restrictions: web restricted, regional-blackout on, archive allowed

Every rule is inspectable. Each card exposes the exact JSON it evaluates and emits, so a policy decision is never a black box: you can see the match it fired on and the SCTE-35 it produced.

Built-in tooling

SCTE-35, decoded in the box.

The same server that conditions your signals also carries a full SCTE-35 workbench, so you can build a cue to test a rule, paste a capture to see what an encoder actually sent, or validate a message before it ships.

Build

Compose splice_insert and time_signal messages from fields and emit the encoded form, the same construction the rules engine uses for ad-outs.

Decode

Paste base64, hex, or raw binary and get a field-by-field breakdown: splice command, segmentation descriptors, UPIDs, and durations.

Validate

Check a message for structural correctness before it reaches air, so malformed cues are caught at authoring time rather than in the field.

Reference implementation

The POIS that proves the protocol.

SESAME was extracted byte-for-byte from rust-pois, and the published conformance vectors are generated from it. Turning security on is a matter of configuration, not a rebuild.

  • Bidirectional out of the box. rust-pois verifies inbound ESAM requests and signs its own POIS responses, the decision being the thing most worth protecting.
  • Per-channel minimum tier. Raise the security floor on one feed at a time; Tier-0 peers keep working untouched while you migrate.
  • The source of truth for conformance. The golden vectors the multi-language SDK validates against are generated from this server, so spec and code cannot drift.

Turn it on

Leave the SESAME variables unset and rust-pois is a clean Tier-0 POIS. Set a key directory and it verifies and signs.

# enable SESAME by providing keys
POIS_SESAME_KEYS={...}
POIS_SESAME_MIN_TIER=1
POIS_SESAME_RESPONSE_KEYID=pois-primary
Quick start

From clone to console in three commands.

The installer pulls Rust, builds the binary from source, and registers a systemd service. Allow a couple of minutes for the first build.

install on Ubuntu 24.04
$ git clone https://github.com/bokelleher/rust-pois.git
$ cd rust-pois
$ sudo ./install.sh      # prompts for service user + port

# check it is running, then open the UI
$ sudo systemctl status pois
$ curl http://localhost:8080/healthz
# visit http://<server-ip>:8080/

Prefer a throwaway dev instance? make run-dev starts a server on localhost:18080 against a separate database. Configuration is environment-driven: POIS_PORT, POIS_DB, POIS_TLS_CERT / POIS_TLS_KEY, and the POIS_SESAME_* family.

On the roadmap (planned, not yet shipped):

SMPTE timecode rendering SCTE-35 → SCTE-104 conversion human-readable UPIDs in the monitor logged SESAME rejections distributed (Redis) replay cache
Open source · MIT

Run a real POIS.
See SESAME in motion.

Clone it, install it, and condition your first signal. The protocol it implements is documented and open too.