Remove recordings feature, replay sessions directly, bump to 0.6.0
CI / Build and push image (push) Successful in 1m41s
CI / Static checks (push) Successful in 2m12s

Recordings were just a thin named pointer over an already-captured
session's events, so the whole separate feature (recordings table, API
routes, pages, UI) is gone: any completed session can now be named and
replayed directly. Replaying no longer creates a session or duplicates
events of its own - it just bumps the source session's playCount/lastPlayedAt.

Also renames play_sessions/playSession(s) to sessions/session(s) throughout
the schema, queries, API routes, and UI for consistency, and updates the
README to match the new flow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 21:38:51 +02:00
co-authored by Claude Sonnet 5
parent 2a3c4ff1f2
commit 401b9b5033
46 changed files with 1710 additions and 1018 deletions
+347
View File
@@ -0,0 +1,347 @@
{
"version": "6",
"dialect": "sqlite",
"id": "dd3f46c7-f6a2-428b-b751-982018e83803",
"prevId": "cb592704-f845-4761-b5cc-53ec7cb5d179",
"tables": {
"devices": {
"name": "devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ble_name": {
"name": "ble_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"device_class": {
"name": "device_class",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"capabilities": {
"name": "capabilities",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"last_connected_at": {
"name": "last_connected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"play_sessions": {
"name": "play_sessions",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'active'"
},
"started_at": {
"name": "started_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ended_at": {
"name": "ended_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_devices": {
"name": "session_devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"play_session_id": {
"name": "play_session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"device_id": {
"name": "device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"slot_label": {
"name": "slot_label",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"connected_at": {
"name": "connected_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"disconnected_at": {
"name": "disconnected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"session_devices_play_session_id_idx": {
"name": "session_devices_play_session_id_idx",
"columns": [
"play_session_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_devices_play_session_id_play_sessions_id_fk": {
"name": "session_devices_play_session_id_play_sessions_id_fk",
"tableFrom": "session_devices",
"tableTo": "play_sessions",
"columnsFrom": [
"play_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"session_devices_device_id_devices_id_fk": {
"name": "session_devices_device_id_devices_id_fk",
"tableFrom": "session_devices",
"tableTo": "devices",
"columnsFrom": [
"device_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_events": {
"name": "session_events",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"play_session_id": {
"name": "play_session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"session_device_id": {
"name": "session_device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ts_ms": {
"name": "ts_ms",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"command_type": {
"name": "command_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feature_index": {
"name": "feature_index",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"raw_payload": {
"name": "raw_payload",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"session_events_session_ts_idx": {
"name": "session_events_session_ts_idx",
"columns": [
"play_session_id",
"ts_ms"
],
"isUnique": false
},
"session_events_session_device_idx": {
"name": "session_events_session_device_idx",
"columns": [
"session_device_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_events_play_session_id_play_sessions_id_fk": {
"name": "session_events_play_session_id_play_sessions_id_fk",
"tableFrom": "session_events",
"tableTo": "play_sessions",
"columnsFrom": [
"play_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"session_events_session_device_id_session_devices_id_fk": {
"name": "session_events_session_device_id_session_devices_id_fk",
"tableFrom": "session_events",
"tableTo": "session_devices",
"columnsFrom": [
"session_device_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
+390
View File
@@ -0,0 +1,390 @@
{
"version": "6",
"dialect": "sqlite",
"id": "d2afbfe4-99cd-4898-956d-2097b26dda60",
"prevId": "dd3f46c7-f6a2-428b-b751-982018e83803",
"tables": {
"devices": {
"name": "devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ble_name": {
"name": "ble_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"device_class": {
"name": "device_class",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"capabilities": {
"name": "capabilities",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"last_connected_at": {
"name": "last_connected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"play_sessions": {
"name": "play_sessions",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"replayed_session_id": {
"name": "replayed_session_id",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'active'"
},
"started_at": {
"name": "started_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ended_at": {
"name": "ended_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"play_count": {
"name": "play_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"last_played_at": {
"name": "last_played_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"play_sessions_replayed_session_id_play_sessions_id_fk": {
"name": "play_sessions_replayed_session_id_play_sessions_id_fk",
"tableFrom": "play_sessions",
"tableTo": "play_sessions",
"columnsFrom": [
"replayed_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_devices": {
"name": "session_devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"play_session_id": {
"name": "play_session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"device_id": {
"name": "device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"slot_label": {
"name": "slot_label",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"connected_at": {
"name": "connected_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"disconnected_at": {
"name": "disconnected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"session_devices_play_session_id_idx": {
"name": "session_devices_play_session_id_idx",
"columns": [
"play_session_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_devices_play_session_id_play_sessions_id_fk": {
"name": "session_devices_play_session_id_play_sessions_id_fk",
"tableFrom": "session_devices",
"tableTo": "play_sessions",
"columnsFrom": [
"play_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"session_devices_device_id_devices_id_fk": {
"name": "session_devices_device_id_devices_id_fk",
"tableFrom": "session_devices",
"tableTo": "devices",
"columnsFrom": [
"device_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_events": {
"name": "session_events",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"play_session_id": {
"name": "play_session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"session_device_id": {
"name": "session_device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ts_ms": {
"name": "ts_ms",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"command_type": {
"name": "command_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feature_index": {
"name": "feature_index",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"raw_payload": {
"name": "raw_payload",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"session_events_session_ts_idx": {
"name": "session_events_session_ts_idx",
"columns": [
"play_session_id",
"ts_ms"
],
"isUnique": false
},
"session_events_session_device_idx": {
"name": "session_events_session_device_idx",
"columns": [
"session_device_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_events_play_session_id_play_sessions_id_fk": {
"name": "session_events_play_session_id_play_sessions_id_fk",
"tableFrom": "session_events",
"tableTo": "play_sessions",
"columnsFrom": [
"play_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"session_events_session_device_id_session_devices_id_fk": {
"name": "session_events_session_device_id_session_devices_id_fk",
"tableFrom": "session_events",
"tableTo": "session_devices",
"columnsFrom": [
"session_device_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
+390
View File
@@ -0,0 +1,390 @@
{
"version": "6",
"dialect": "sqlite",
"id": "3d3770ee-d054-4dc7-9ff2-c033e8d000a1",
"prevId": "d2afbfe4-99cd-4898-956d-2097b26dda60",
"tables": {
"devices": {
"name": "devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ble_name": {
"name": "ble_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"device_class": {
"name": "device_class",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"capabilities": {
"name": "capabilities",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"last_connected_at": {
"name": "last_connected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_devices": {
"name": "session_devices",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"device_id": {
"name": "device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"slot_label": {
"name": "slot_label",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"connected_at": {
"name": "connected_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"disconnected_at": {
"name": "disconnected_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"session_id": {
"name": "session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"session_devices_session_id_idx": {
"name": "session_devices_session_id_idx",
"columns": [
"session_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_devices_device_id_devices_id_fk": {
"name": "session_devices_device_id_devices_id_fk",
"tableFrom": "session_devices",
"tableTo": "devices",
"columnsFrom": [
"device_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "no action"
},
"session_devices_session_id_sessions_id_fk": {
"name": "session_devices_session_id_sessions_id_fk",
"tableFrom": "session_devices",
"tableTo": "sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session_events": {
"name": "session_events",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"session_device_id": {
"name": "session_device_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ts_ms": {
"name": "ts_ms",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"command_type": {
"name": "command_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feature_index": {
"name": "feature_index",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"raw_payload": {
"name": "raw_payload",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"session_id": {
"name": "session_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"session_events_session_ts_idx": {
"name": "session_events_session_ts_idx",
"columns": [
"session_id",
"ts_ms"
],
"isUnique": false
},
"session_events_session_device_idx": {
"name": "session_events_session_device_idx",
"columns": [
"session_device_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_events_session_device_id_session_devices_id_fk": {
"name": "session_events_session_device_id_session_devices_id_fk",
"tableFrom": "session_events",
"tableTo": "session_devices",
"columnsFrom": [
"session_device_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"session_events_session_id_sessions_id_fk": {
"name": "session_events_session_id_sessions_id_fk",
"tableFrom": "session_events",
"tableTo": "sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"sessions": {
"name": "sessions",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"replayed_session_id": {
"name": "replayed_session_id",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'active'"
},
"started_at": {
"name": "started_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ended_at": {
"name": "ended_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"duration_ms": {
"name": "duration_ms",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"play_count": {
"name": "play_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"last_played_at": {
"name": "last_played_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_replayed_session_id_sessions_id_fk": {
"name": "sessions_replayed_session_id_sessions_id_fk",
"tableFrom": "sessions",
"tableTo": "sessions",
"columnsFrom": [
"replayed_session_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
+21
View File
@@ -8,6 +8,27 @@
"when": 1787617808883,
"tag": "0000_bouncy_anita_blake",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1787856296915,
"tag": "0001_drop_recordings",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1787856317550,
"tag": "0002_add_session_replay_fields",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1787950004000,
"tag": "0003_rename_sessions",
"breakpoints": true
}
]
}