Commit graph

  • 86340caf9d fix(android): keep pairing code fully on-screen (was clipped at bottom) ScreenTinker 2026-06-08 19:46:30 -0500
  • 06c6c3214b fix(android): make pairing code fit/visible on all screen sizes ScreenTinker 2026-06-08 19:18:29 -0500
  • d41bd1f27d fix(android): verify OTA APK signature before install + disable backup (Critical) ScreenTinker 2026-06-08 19:06:23 -0500
  • ccaf83a698 fix(android): make pairing code fit/visible on all screen sizes ScreenTinker 2026-06-08 19:18:29 -0500
  • 401c4b00b5 fix(security): sanitize public widget render to close stored XSS ScreenTinker 2026-06-08 19:11:14 -0500
  • 9bad686667 fix(android): verify OTA APK signature before install + disable backup (Critical) ScreenTinker 2026-06-08 19:06:23 -0500
  • 50ad1f670b
    Merge pull request #28 from screentinker/fix/security-quick-wins screentinker 2026-06-08 19:04:14 -0500
  • ba3e2cc785 fix(security): patch quick-win findings from the codebase review ScreenTinker 2026-06-08 19:02:19 -0500
  • 66ef47239f fix(android): Android 14+ MediaProjection / foreground-service compliance (#5) ScreenTinker 2026-06-08 17:19:56 -0500
  • d6e85b1745
    Merge pull request #26 from screentinker/feat/global-default-branding-15 screentinker 2026-06-08 17:03:39 -0500
  • eb13f716d0 feat(branding): instance-level default white-label branding (#15) ScreenTinker 2026-06-08 16:55:22 -0500
  • 5433a97bc9
    Merge pull request #25 from screentinker/fix/single-workspace-settings-19 screentinker 2026-06-08 16:40:44 -0500
  • 3bf108d0fb fix(switcher): expose workspace settings for single-workspace users (#19) ScreenTinker 2026-06-08 16:39:42 -0500
  • c1f2f0a637
    Merge pull request #24 from screentinker/feat/searchable-org-switcher-16 screentinker 2026-06-08 16:32:45 -0500
  • 1f62ffbc3b feat(switcher): searchable/filterable org switcher (#16) ScreenTinker 2026-06-08 16:31:46 -0500
  • 0f84cac440
    Merge pull request #23 from screentinker/feat/admin-user-workspace-mgmt screentinker 2026-06-08 16:26:07 -0500
  • 2872b883c7 feat(admin): manage a user's workspace memberships (multi + per-workspace role) ScreenTinker 2026-06-08 16:24:52 -0500
  • 66c95bb331 fix(db): cascade tenant resources on workspace/org delete (#18 follow-up) ScreenTinker 2026-06-08 16:01:52 -0500
  • ec44cb785a
    Merge pull request #21 from screentinker/fix/delete-user-fk-cascade-18 screentinker 2026-06-08 10:52:50 -0500
  • 05f9c20ecf fix(admin): user deletion failed with FOREIGN KEY constraint (#18) ScreenTinker 2026-06-08 10:51:32 -0500
  • 7615eabdd5 feat(admin): Workspace column + inline move/assign on the Users page ScreenTinker 2026-06-08 10:21:41 -0500
  • 65691e26da chore(admin-sw): bump cache to v3 to evict stale clients ScreenTinker 2026-06-05 15:22:24 -0500
  • 400872f8ea feat(admin): Add User from the platform Users page (workspace picker) ScreenTinker 2026-06-05 14:40:31 -0500
  • 9aae64c47a
    Merge pull request #20 from screentinker/docs/surface-disable-registration screentinker 2026-06-08 10:30:13 -0500
  • 406f481a57 docs: surface DISABLE_REGISTRATION self-hosting flag (#11) ScreenTinker 2026-06-08 10:29:08 -0500
  • 212170eb88
    Merge pull request #17 from screentinker/feat/role-model-and-admin-users screentinker 2026-06-05 13:44:46 -0500
  • 5502a3eaa8 fix(roles): make platform_operator assignable + add deny/assign regression tests ScreenTinker 2026-06-05 12:44:39 -0500
  • 7674f6dc9f test(admin): node:test coverage for Add User + role gating ScreenTinker 2026-06-05 11:23:06 -0500
  • 54549420e7 feat(signup): optional org-on-create for self-service signups (#12) ScreenTinker 2026-06-05 11:16:27 -0500
  • 6e31770cee feat(admin): admin-provisioned user creation + first-login gate (#10) ScreenTinker 2026-06-05 11:03:56 -0500
  • 48902f6807 feat(roles): add cross-org platform_operator staff role (#13) ScreenTinker 2026-06-05 10:30:21 -0500
  • 797eab7c8d refactor(roles): normalize the platform-role model (#14) ScreenTinker 2026-06-05 09:58:46 -0500
  • 0fec335e75 docs: add Android player troubleshooting & recovery guide ScreenTinker 2026-06-03 19:58:09 -0500
  • 890ec5790f fix(proof-of-play): throttle play_logs writes to prevent runaway bloat ScreenTinker 2026-06-02 09:52:22 -0500
  • cbe00d6c85 feat(signup): T+3 activation nudge for users with zero paired screens ScreenTinker 2026-05-30 20:28:24 -0500
  • 6edc50203a feat: implement AI improvements AI Scout Agent 2026-05-31 00:43:12 +0300
  • 2f78fa1106 chore: track .env.example (un-ignore from .env.* rule) ScreenTinker 2026-05-30 16:16:52 -0500
  • c0b220836a fix(signup): make admin-notify recipient env-driven, not hardcoded ScreenTinker 2026-05-30 16:16:33 -0500
  • a0abdc01ed fix(signup): route admin signup notification to support@ not personal inbox ScreenTinker 2026-05-30 14:52:59 -0500
  • b67fbaa1b6 feat(signup): welcome email + admin signup notification (slice 1) ScreenTinker 2026-05-30 14:50:27 -0500
  • d7e3ae6076 security(widgets): tighten webpage widget inner sandbox ScreenTinker 2026-05-30 13:14:31 -0500
  • fe36c8c4b9 security(widgets): add sandbox="allow-scripts" to widget iframes ScreenTinker 2026-05-28 12:28:34 -0500
  • 159a36ed99 fix(workspaces): use APP_URL env var for invite-accept URL generation ScreenTinker 2026-05-17 15:26:07 -0500
  • caa9fd0f40 feat(workspaces): mutation UI for members (slice 2B) ScreenTinker 2026-05-17 14:45:34 -0500
  • 399af54839 feat(workspaces): accept-invite URL handler (slice 2C) + email URL path fix ScreenTinker 2026-05-16 13:50:23 -0500
  • 8db171d979 feat(workspaces): members page read-only view (slice 2A) ScreenTinker 2026-05-16 13:00:51 -0500
  • c4fbd2ba5c feat(workspaces): invite/accept-invite backend (slice 1+3) ScreenTinker 2026-05-16 12:19:59 -0500
  • d2a3bdfd15 fix(auth/me): broaden non-admin accessible_workspaces to include org_owner/org_admin paths ScreenTinker 2026-05-16 11:50:37 -0500
  • 3294525f4c fix(socket): prefer WebSocket transport for dashboard socket ScreenTinker 2026-05-16 11:15:18 -0500
  • 2725ea9152 docs(privacy): disclose error and diagnostic telemetry from players ScreenTinker 2026-05-15 15:31:21 -0500
  • 19f434d05a Add player debug overlay and server-side error telemetry sink ScreenTinker 2026-05-15 15:20:42 -0500
  • 12fe0e43eb fix(zones): frontend assignment-flow picker + missed devices.js zone_id projection ScreenTinker 2026-05-14 21:26:58 -0500
  • 73f41c3288 fix(zone-id): restore zone-aware playlist_items wiring (issue #3 follow-up) ScreenTinker 2026-05-14 19:20:44 -0500
  • cdd29d5e3b Merge pull request #6 from ChrisChrome: web player auto-connect ScreenTinker 2026-05-14 16:12:58 -0500
  • f6ef75549b Fix possible race condition in player auto-connect Christopher Cookman 2026-05-14 14:54:17 -0600
  • 98e742c612
    Merge branch 'screentinker:main' into main Christopher Cookman 2026-05-14 13:46:40 -0600
  • d5e4e4d927 Feat: Web player auto connect Add a simple 5 second countdown to the web player to get a code without interacting (for systems where interaction is a hassle, or impossible) Christopher Cookman 2026-05-14 13:46:19 -0600
  • 8439f2bf18 fix(landing): replace broken Custom pricing card with enterprise contact form ScreenTinker 2026-05-14 13:52:24 -0500
  • f5ca26ae2d fix(socket): offline debounce + truthful single-device command feedback ScreenTinker 2026-05-14 13:11:40 -0500
  • 742d8c4b09 feat(socket): delivery queue for offline-device emits ScreenTinker 2026-05-14 13:06:43 -0500
  • 3da49ec79c chore(config): env-configurable heartbeat timing ScreenTinker 2026-05-14 13:03:02 -0500
  • 1aee4f2d5b fix(socket): raise Engine.IO ping/pong + prefer WebSocket transport ScreenTinker 2026-05-14 13:02:34 -0500
  • c4ac81c7a6 chore(discord): update Discord invite link ScreenTinker 2026-05-14 12:26:20 -0500
  • 1e23335356 fix(player): graceful handling when displayed content is removed ScreenTinker 2026-05-14 12:17:40 -0500
  • 3dfec5d2f9 feat(config): DISABLE_HOMEPAGE env var to redirect / to the app ScreenTinker 2026-05-14 12:03:29 -0500
  • 4b2a5c51ea docs(readme): comprehensive review - multi-tenancy, current features, tech stack, deployment, contribution ScreenTinker 2026-05-12 18:57:41 -0500
  • f4d2a0330b chore(email): log successful sends for observability ScreenTinker 2026-05-12 18:34:19 -0500
  • dddc48440b docs(readme): document Microsoft Graph email setup + dev restrict + spam protections ScreenTinker 2026-05-12 18:34:08 -0500
  • c71c4016ca feat(email): Microsoft Graph send + alert spam protection + preferences UI ScreenTinker 2026-05-12 18:16:40 -0500
  • f115cb454f style(switcher): widen dropdown, tighten rows, prevent org-line wrap ScreenTinker 2026-05-12 14:04:56 -0500
  • ce332ead67 feat(switcher): per-workspace device count in dropdown rows ScreenTinker 2026-05-12 14:04:21 -0500
  • 42966da973 feat(teams): temporarily disable Teams API while feature is redesigned ScreenTinker 2026-05-12 13:30:55 -0500
  • 766f02ae5d docs(upload): correct misleading defParamCharset comment ScreenTinker 2026-05-12 11:57:54 -0500
  • d679ca8d14 fix(upload): re-decode multipart filename header from latin1 to utf8 in multer storage callback ScreenTinker 2026-05-12 11:55:55 -0500
  • b67775283b fix(server): NFC normalize user-facing filenames in safeFilename ScreenTinker 2026-05-12 11:51:34 -0500
  • 1e142d9644 fix(frontend): playlists.js thumbnail path uses API endpoint instead of legacy direct path ScreenTinker 2026-05-12 11:44:30 -0500
  • fc29843035 feat(socket): Phase 2.3 workspace-scoped dashboard socket rooms + per-command permission gates. Dashboard namespace was previously a flat broadcast - every connected dashboard received every device's status/screenshot/playback events platform-wide (foreign device names + IPs included). Inbound socket commands gated by a legacy admin/superadmin role check that was dead code post-Phase-1 rename. ScreenTinker 2026-05-12 11:34:24 -0500
  • 56da64d0cd feat(workspaces): rename via switcher dropdown - new PATCH /api/workspaces/:id route, per-row pencil affordance in switcher (visible only when caller can_admin), small rename modal with name + slug fields, validation (name <=80 chars, slug ^[a-z0-9]+(?:-[a-z0-9]+)*$ <=60 chars, blank slug -> NULL), 409 on per-org slug collision. Permission gating via new canAdminWorkspace(db, user, ws) helper in lib/permissions.js - reused-ready for future Phase 3 admin actions. /me query now joins organization_members to compute can_admin per accessible_workspaces entry. Drive-by fixes surfaced: (1) activityLogger method filter was missing PATCH, added; (2) routes that operate on a target workspace by URL param need to stamp req.workspaceId from the param so activityLogger captures the right tenant attribution - documented in the route. Smoke fixture: switcher-test@local.test is workspace_admin of Studio A and workspace_editor of Field Crew (no org_owner) so the can_admin true/false split is exercised in one login. ScreenTinker 2026-05-12 11:06:55 -0500
  • 0c91390e56 fix(frontend): workspace switcher (Phase 3 MVP) + SW network-first migration + platform_admin accessible_workspaces expansion + static render CSS cleanup. The switcher adds a sidebar dropdown for users who are members of multiple workspaces, renders as static text with a 'Workspace' label for single-workspace users, and muted 'No workspace' for zero. Uses existing /api/auth/me's accessible_workspaces and POST /api/auth/switch-workspace endpoints. Platform admin / superadmin users now see all workspaces in accessible_workspaces (closing the known regression from 88d91b1) via a LEFT JOIN that preserves workspace_role semantics (null = acting-as, role string = direct member). No cap on the list - deliberate for now, revisit at 50+ workspaces. SW fix bumps rd-admin-v1 -> rd-admin-v2 and switches fetch strategy from cache-first to network-first so the server's existing Cache-Control: no-cache + ETag headers actually get respected; preserves offline fallback. Static render CSS drops the bordered-box chrome that was making single-workspace users think the static text was clickable. Includes test fixture user switcher-test@local.test (credentials in fixture SQL header). Surfaced by semetra22 / Discord report about 'screens jumbled up' post-migration; root cause was the missing workspace switcher UI making devices in non-active workspaces appear missing. ScreenTinker 2026-05-12 10:55:09 -0500
  • bc445a0a7c fix(boot): auto-apply Phase 1 multi-tenancy migration on startup if not yet applied; refactor scripts/migrate-multitenancy.js to expose runMigration() with CLI wrapper preserved; pre-migration snapshot to db/remote_display.pre-migration-<timestamp>.db; belt-and-suspenders guards on migrateFolderWorkspaceIds + backfillActivityLogWorkspace so the inline backfills skip cleanly if workspaces table absent. Fixes startup crash on pre-multi-tenancy installs (semetra22 / Discord report) where 'npm start' after pulling latest hit migrateFolderWorkspaceIds and crashed with 'no such table: workspaces'. Self-hosters now get an automatic upgrade path without needing to run 'node scripts/migrate-multitenancy.js' manually. ScreenTinker 2026-05-12 08:22:47 -0500
  • 92e26aafcb fix(server): mount activityLogger middleware before workspace routes so POST/PUT/DELETE actually get logged - pre-existing bug, the middleware was a no-op for every API route because route mounts came first in server.js (L305 routes vs L368 middleware). Zero double-log risk: the one inline logActivity caller at routes/auth.js:452 is on /api/auth which mounts before the new middleware position. activity_log row growth will pick up significantly going forward (pruneActivityLog 90-day retention already handles the bound). Surfaced by Phase 2.2 migration discipline. ScreenTinker 2026-05-11 23:17:28 -0500
  • 88d91b10af activity_log: stop the bleeding - writer-leak fix on 3 sites (activityLogger middleware, alert service, login route) + one-time backfill of 548 NULL-workspace rows via device.workspace_id or workspace_members lookup; activity.js route migration deferred to its own slice tomorrow. ScreenTinker 2026-05-11 23:14:06 -0500
  • f88805f36d fix(schedule): add delete button to schedule edit modal so schedules can be removed from the UI (DELETE /api/schedules/:id already existed) ScreenTinker 2026-05-11 23:05:03 -0500
  • 0b9aa56e75 Phase 2.2m: schedules.js scoped to workspace_id; schedule.workspace_id inherited from target (device/group); fixes 6 pre-existing cross-tenant leaks (POST content/widget/layout/playlist accepted with no check, PUT verifyOwnership rewrite across all 6 polymorphic targets) ScreenTinker 2026-05-11 23:03:54 -0500
  • a77ab365dd fix(dashboard): selection bar surfaces 'pick 1 more' hint when 1 display selected so the disabled Create Video Wall button isn't silently unresponsive ScreenTinker 2026-05-11 22:56:15 -0500
  • b6c90d3421 Phase 2.2l: video-walls.js scoped to workspace_id; fixes 4 pre-existing cross-tenant leaks (POST playlist_id, PUT playlist/content/leader_device, PUT /devices, PUT /content); drops dead admin/team_members code paths left over from Phase 2.1 role rename; team_id column noted for future cleanup ScreenTinker 2026-05-11 22:56:08 -0500
  • 52e68ac490 fix(playlists): POST /publish returns items with pi.id so post-publish delete works without refresh; future refactor candidate to share SELECT shape with GET /:id ScreenTinker 2026-05-11 22:28:59 -0500
  • 833e84578e Phase 2.2k: playlists.js scoped to workspace_id; fixes 3 pre-existing cross-tenant leaks (content add, widget add with NO existing check, device assign); content.js snapshot-scrub bundle; status.js export endpoint deferred to dedicated slice ScreenTinker 2026-05-11 22:22:18 -0500
  • 90fe6e0f9a Phase 2.2j: assignments.js scoped to workspace_id via playlist.workspace_id; fixes 3 pre-existing cross-tenant leaks (content add, widget add with NO existing check, copy-to cross-workspace); ensureDevicePlaylist loop-closer; status.js playlist INSERT bundle ScreenTinker 2026-05-11 22:12:13 -0500
  • e17538b186 Phase 2.2i: device-groups.js scoped to workspace_id; fixes 3 pre-existing cross-tenant leaks (group device add, bulk content assign, bulk playlist assign); pre-emptive workspace_id stamp on ensureDevicePlaylist helper ScreenTinker 2026-05-11 21:58:13 -0500
  • c7f9d014ca Phase 2.2h: layouts.js scoped to workspace_id; templates via is_template path; fixes pre-existing PUT /device/:deviceId cross-tenant layout-assignment leak ScreenTinker 2026-05-11 21:45:28 -0500
  • f17d757ba0 Phase 2.2g: reports.js scoped to workspace_id; fixes pre-existing /export and /uptime cross-tenant leaks ScreenTinker 2026-05-11 21:36:54 -0500
  • 0d642e4d80 Phase 2.2f: white-label.js scoped to workspace_id; requireWorkspaceAdmin gate; status.js bundle ScreenTinker 2026-05-11 21:30:22 -0500
  • 806c931e43 Phase 2.2e: kiosk.js scoped to workspace_id; import kiosk INSERT bundled ScreenTinker 2026-05-11 21:20:18 -0500
  • efce13e05d Phase 2.2d: widgets.js scoped to workspace_id; import + widget-reference defense bundled ScreenTinker 2026-05-11 21:13:51 -0500
  • a4610e8d0d Phase 2.2c: content_folders gets workspace_id (schema + backfill); folders.js scoped; content.js folder-move strict same-workspace ScreenTinker 2026-05-11 21:04:03 -0500
  • a5dbc5d665 Phase 2.2b: content.js + status.js import scoped to workspace_id; uploads stamp workspace_id ScreenTinker 2026-05-11 20:50:25 -0500
  • afd2a10df2 Phase 2.2a: devices.js scoped to workspace_id; pair flow stamps workspace_id on claim ScreenTinker 2026-05-11 20:33:58 -0500
  • ac3eb74122 i18n: register Italian locale in language registry (followup to PR #2) ScreenTinker 2026-05-11 20:05:09 -0500
  • 2954fd1a84 Phase 2.1: tenancy middleware, permission helpers, JWT workspace context, frontend + backend role-rename compat ScreenTinker 2026-05-11 20:02:00 -0500