Skip to content

Latest commit

 

History

282 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tasker

v1.15.4 — A self-hosted, anonymous workload-logging PWA for NHS and healthcare teams. Built with TypeScript, Express 5, SQLite, and vanilla JS.


Features

  • Anonymous by design — usernames are auto-generated memorable word pairs. No real names, emails, or patient data stored.
  • PWA — installable on mobile, works offline for cached assets.
  • Task tracking — duty vs personal tasks, categories, subcategories, outcomes, interruption handling.
  • Faster Log Task start flow — up to 9 frequency-ranked quick-pick buttons for Task From/Task Type with the most recent option pinned first using a green border, plus dark-blue highlighting only after selection, and 3 one-tap date-start actions (Previous Task date, Yesterday, Selected Date).
  • Task flags — admin-managed list of structured task annotations (e.g. "Sent to wrong user", "Priority too high"). Users select any that apply; free-text notes removed for data protection. Users can suggest new flags via email.
  • Analytics — session and 30-day history with Chart.js charts, filtering, flag distribution chart, linear regression trendlines, and XLSX analytics report download.
  • Excel export — users can download their raw task data as .xlsx (includes Flags column), or download a full analytics report as .xlsx with one data sheet per chart.
  • User groups — administrators create groups that define which dropdown options users see.
  • Personal option customisation — users can tick/untick individual options to build their own personalised dropdown lists.
  • SMTP email suggestions — dropdown and flag suggestions are emailed to the administrator instead of being stored on the server, improving data security. Configure via admin panel or environment variables.
  • Notices — administrators can post notices that appear on every user's home screen.
  • User messages — administrators can send messages to individual users or broadcast to all users; messages appear on the user's home screen and are dismissable.
  • Integrated combobox dropdowns — all task dropdowns are searchable comboboxes.
  • Admin panel — user management, DB backup/restore, dropdown configuration, SMTP settings, notices management, task flag options, registration settings, group management, pending proposals. Desktop-optimised layout.
  • Configurable registration — administrator controls three levels for self-registration and user invitations.
  • 30-day data retention — task data is automatically deleted after 30 days.
  • Health-check endpointGET /readyz returns a JSON status response for uptime/heartbeat monitoring.
  • Landing, SEO & crawler-ready homepage — homepage now includes semantic marketing copy, structured data, Open Graph/Twitter cards, robots.txt, sitemap.xml, and llms.txt.
  • Asset version endpointGET /api/version returns {"version":"1.15.4"} for client-side cache-busting.
  • Cloudflare Turnstile CAPTCHA — optional bot-protection for login and self-registration. When TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY are set, Turnstile widgets are rendered on the login and registration forms; tokens are verified server-side before credentials are checked. The feature is fully disabled (and invisible) when the environment variables are not set.

Documentation

Document Location
Installation guide docs/installation.md
Maintenance & troubleshooting docs/maintenance.md
Search engine submission guide docs/search-engine-submission.md
User guide (in-app) /help route
Data & Use Policy (in-app) /policy route

Quick start (development)

# 1. Install dependencies
npm install

# 2. Build TypeScript
npm run build

# 3. Copy and configure environment
cp .env.example .env

# 4. Start the server
node dist/server.js

Server runs on port 3020 by default (set PORT in .env to override).

Then create the admin account — see Installation guide.


Environment variables

Variable Description Default
PORT Server port 3020
SESSION_SECRET Session signing secret (set this in production!) Random (changes on restart)
NODE_ENV Set to production to enable secure cookies (requires HTTPS)
APP_URL Full public base URL. Used for review links plus canonical, robots.txt, sitemap.xml, and llms.txt output. Request origin
SSL_CERT_DIR Directory containing Let's Encrypt certificate files /etc/letsencrypt/live/yourdomain
SSL_CERT Path to the certificate chain (auto-detects HTTPS if this file exists) $SSL_CERT_DIR/fullchain.pem
SSL_KEY Path to the private key $SSL_CERT_DIR/privkey.pem
TURNSTILE_SITE_KEY Cloudflare Turnstile site key — enables CAPTCHA on login and registration when set
TURNSTILE_SECRET_KEY Cloudflare Turnstile secret key — required alongside TURNSTILE_SITE_KEY

HTTPS is detected automatically. If both SSL_CERT and SSL_KEY exist on disk the server starts in HTTPS mode. Otherwise it starts in plain HTTP mode.

⚠️ In production, always set SESSION_SECRET to a long random string and serve over HTTPS.


Development

npm run dev   # ts-node src/server.ts  (no build step required)
npm run build # compile TypeScript → dist/

Architecture

src/
  server.ts               Express 5 app, middleware wiring, SSL detection, dynamic SEO shell rendering, /readyz health check, /api/version, robots/sitemap/llms, 30-day retention job
  db.ts                   SQLite schema + migrations + seed data, getDb(), getSetting(), setSetting(), TASKER_DB_PATH override for tests
  words.ts                Memorable two-word username generator
  turnstile.ts            Cloudflare Turnstile CAPTCHA helpers — isTurnstileEnabled(), verifyTurnstileToken()
  middleware/index.ts     requireAuth, requireAdmin, CSRF, logEvent
  routes/
    auth.ts               /api/auth/* — register, login, logout, change-password, me, account delete, invite, user-groups, set-group, propose-group, my-options, turnstile-config
    tasks.ts              /api/tasks/* — start, active, PATCH, GET; validates task start/end, assigned date, and interruption times are not future-dated
    analytics.ts          /api/analytics/* — session, history, export (xlsx)
    dropdowns.ts          /api/dropdowns/* — list, propose, admin CRUD
    admin.ts              /api/admin/* — stats, users, pending-users, approve, settings, backup, restore, user-groups, pending-groups

  __tests__/
    security.test.ts      241-test negative security suite (CSRF, IDOR, SQLi, XSS, input validation, resource exhaustion, error handling, session fixation, SMTP sanitisation, option allowlist)
    helpers/testApp.ts    Isolated Express app + test-user helpers for jest/supertest

public/
  index.html              SEO-aware SPA shell + static landing content template
  favicon.svg             SVG favicon (browser tab icon)
  manifest.json           PWA manifest
  social-preview.svg      Social preview asset for Open Graph / Twitter cards
  sw.js                   Service worker (cache-first static, network-first API)
  policy.html             Data & Use Policy  (served at /policy)
  help.html               User guide         (served at /help)
  css/app.css             Mobile-first styles
  js/app.js               Complete SPA — views, Chart.js charts, regression trendlines, browser history navigation, asset version checking, integrated combobox dropdowns
  icons/
    icon-192.png          PWA home-screen icon (192×192)
    icon-512.png          PWA splash / store icon (512×512)

docs/
  installation.md         Full installation guide (server, SSL, systemd, Nginx/Caddy)
  maintenance.md          Routine maintenance, backup/restore, troubleshooting

Security

  • CSRF tokens on all mutating requests (X-CSRF-Token header)
  • Rate limiting: auth 20/15 min, API 200/min (including /readyz health-check)
  • bcrypt cost factor 12 for passwords
  • Account lockout after repeated failed login attempts
  • Friendly error messages on failed login (username/password invalid)
  • HTTP-only, SameSite=strict session cookies
  • 30-minute idle session timeout with a 5-minute inactivity warning + midnight session expiry
  • Session ID regeneration on successful login and after 2FA verification (prevents session fixation)
  • Helmet.js security headers
  • Parameterised SQL queries throughout; explicit allowlist for any dynamic column names
  • Path validation on DB restore endpoint
  • Automatic HTTPS when certificates are present
  • /readyz health-check endpoint is unauthenticated but rate-limited and returns no sensitive data
  • safeId() helper sanitises combobox container IDs before insertion into inline event handlers
  • SMTP error details logged server-side only; clients receive generic safe messages
  • Constant-time comparison for MFA code verification (prevents timing attacks)
  • Unapproved dropdown options are rejected when users update their personal option list
  • Global error handler prevents accidental stack-trace leakage on unexpected errors
  • 241-test negative security suite covering CSRF, IDOR, SQL injection, XSS, input validation, resource exhaustion, error handling, session fixation, SMTP sanitisation, and option validation (npm test)
  • Cloudflare Turnstile CAPTCHA — optional bot-protection on login and self-registration; server-side token verification via src/turnstile.ts; disabled and invisible when env vars are not set

Data & Use Policy

See /policy for the full Data and Use Policy.


Changelog

v1.15.4 (July 2026) — Pending graph refresh and homepage label clarification

  • Pending-task graph refresh — logging a new pending-task count from the user's homepage now redraws the pending-task graph with the newest snapshot instead of leaving the previous chart instance visible.
  • Homepage metric label — renamed "Tasks logged" to "Recent tasks logged" on the main site homepage and user-facing homepage stat labels for clearer wording.
  • Version bump — incremented the bugfix release to 1.15.4 in package metadata and runtime version surfaces.
  • Documentation version sync — updated user-facing pages and manuals so current-version labels consistently show 1.15.4.

v1.15.3 (June 2026) — Static-first homepage and SEO alignment

  • Version bump — incremented the minor release to 1.15.3 in package metadata and runtime version surfaces.
  • SEO-first homepage rendering — kept the public homepage content in static HTML and limited JavaScript to progressively enhancing the app launch controls.
  • Landing page cleanup — simplified homepage calls to action and launch controls while preserving login, signup, and Turnstile flows.

v1.14.3 (June 2026) — Future date/time validation

  • Task submission validation — task start, end, assigned date, and interruption date/time fields now reject future values in the browser and at the API layer.
  • Route helper documentation — repository documentation updated to reflect the new task temporal validation functions.
  • Version bump — incremented the bugfix release to 1.14.3 in package metadata and runtime version surfaces.

v1.14.2 (May 2026) — Bugfix version and documentation alignment

  • Version bump — incremented the bugfix release to 1.14.2 in package metadata and runtime version surfaces.
  • Documentation version sync — updated user-facing pages and manuals so current-version labels consistently show 1.14.2.
  • Feature documentation correction — updated help/guide review-screen guidance to reflect the live product: structured task flags are supported and free-text notes are not.

v1.14.0 (May 2026) — Landing page, SEO, and crawler optimisation

  • Homepage repositioning — rewrote the public landing experience to emphasise Tasker’s real differentiators: self-hosting, anonymous usernames, privacy-first workload evidence, interruption tracking, analytics, and export-ready reporting for healthcare teams.
  • Search, AI crawler, and social readiness — added semantic homepage content, JSON-LD structured data, Open Graph/Twitter metadata, robots.txt, sitemap.xml, llms.txt, and a dedicated social preview asset.
  • Documentation update — expanded repository documentation with a search-engine submission guide and refreshed versioning to 1.14.0 across the current docs set.

v1.13.8 (May 2026) — Log Task quick-pick highlight refinement

  • Clicked-only blue highlights — on the Log Task screen, Task From and Task Type quick-pick buttons now turn dark blue only after the user actively selects them.
  • Recent option border retained — the most recently used quick-pick still stays pinned first with the existing green border cue.
  • Version bump — Version number incremented to 1.13.8; documentation updated to reflect the revised Log Task button behaviour.

v1.13.7 (May 2026) — Log Task quick-pick and date-start enhancements

  • Date assigned quick-start actions — the Log Task screen now provides three horizontally aligned start buttons: Prev (dd/mm) (green) to use the most recent task's assigned date, Yesterday (yellow), and Selected Date (blue) for the date currently shown in the picker.
  • Task From / Task Type quick picks expanded — quick-pick rows now show up to 9 options instead of 6, ordered by frequency with the most recently used option pinned first.
  • Persistent quick-pick highlighting — when a user taps a quick-pick button (or selects the same value in the combobox), the corresponding quick-pick stays highlighted to confirm the active selection.
  • Version bump — Version number incremented to 1.13.7; documentation updated to reflect the new Log Task behavior.

v1.13.2 (May 2026) — Bug fix: event listener mismatch in inactivity tracking

  • Bug fix: Event listeners not properly removedstopActivityTracking() was removing event listeners without the { passive: true } option, while startActivityTracking() added them with this option. According to browser specs, removeEventListener must be called with the exact same parameters as addEventListener, including the options object. This mismatch caused the listeners to never be properly removed, potentially causing listener accumulation and interfering with proper inactivity tracking. Updated stopActivityTracking() to include { passive: true } when removing event listeners.
  • Version bump — Version number incremented to 1.13.2; all page footers and documentation updated accordingly.

v1.13.1 (May 2026) — Version bump

  • Version bump — Version number incremented to 1.13.1; all page footers and documentation updated accordingly. Timeout functions (isTurnstileEnabled, verifyTurnstileToken) are already documented in technical manual §10a.

v1.13.0 (May 2026) — Cloudflare Turnstile CAPTCHA

  • Cloudflare Turnstile CAPTCHA — optional bot-protection added to the login and self-registration forms. When TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY environment variables are set, a Turnstile challenge widget is rendered on both forms. The token submitted by the browser is verified server-side (via src/turnstile.ts) before credentials are checked; an invalid or missing token returns 403 CAPTCHA verification failed. When the environment variables are not set, Turnstile is completely disabled — no widget is displayed and no network call is made. The Cloudflare Turnstile script (https://challenges.cloudflare.com) is now permitted in the Content-Security-Policy (scriptSrc, frameSrc, connectSrc). A new GET /api/auth/turnstile-config endpoint returns { enabled, siteKey } for the client to decide whether to render the widget.
  • Version bump — Version number incremented to 1.13.0; all page footers and documentation updated accordingly.

v1.12.4 (April 2026) — Version bump and technical manual update

  • Technical manual (§12.6) — Section 12.6 "Session Inactivity Tracking" rewritten to accurately describe the inactivity system as overhauled in v1.12.3: documents that the clock advances only on real user interaction (no passive background activityInterval), the single consolidated visibilitychange async handler (hide path no longer stamps the clock; show path calls checkClientInactivity() immediately before proceeding to interruption checks), and the window.focus belt-and-suspenders listener.
  • Version bump — Version number incremented to 1.12.4; all page footers and documentation updated accordingly.

v1.12.3 (April 2026) — Inactivity system deep-fix

  • Bug fix: activityInterval silently reset the inactivity clock every 60 sstartActivityTracking() was calling setInterval(updateLastActive, 60000). updateLastActive() writes Date.now() to localStorage, so the "last active" timestamp was unconditionally refreshed every minute regardless of user activity. This meant the 5-minute warning and 30-minute logout thresholds could almost never accumulate; whether they fired at all was a timing race between the interval and inactivityCheckInterval, explaining the intermittent/non-deterministic behaviour. Removed the activityInterval entirely. The clock is now only advanced by real user interaction (the ACTIVITY_EVENTS listeners) and inactivityCheckInterval (every 60 s) reliably reads the true elapsed idle time.
  • Bug fix: tab-hide path reset the inactivity clock — The async visibilitychange handler called updateLastActive() when document.hidden became true (i.e. the user switched away from the tab). This stamped "the moment you left" as the last-active time. Consequence: idle 20 min, switch tab — clock reset; return 5 min later — system sees 5 min idle, not 25 min; warning/logout never fires. Removed the updateLastActive() call from the hidden path entirely; the clock only moves on user interaction.
  • Bug fix: two competing visibilitychange handlers — A simple synchronous handler (line 443) and a complex async handler (line 4169) both responded to the same event. The simple handler correctly called checkClientInactivity() to show the banner; the async handler then called updateLastActive() which immediately dismissed it. Merged into a single canonical async handler: the duplicate simple handler has been removed and checkClientInactivity() (plus a _sessionExpiryInProgress guard) is now called at the top of the async handler.
  • Bug fix: updateLastActive() dismissed the banner it had just shown — Inside the interruption-check block for non-admin active-task users, updateLastActive() was called after checkInactivityInterruption(). updateLastActive() calls dismissInactivityWarning(), so any banner shown by checkClientInactivity() a few lines earlier was immediately removed. Removed updateLastActive() from this return-to-app path; the clock is reset naturally when the user next interacts via ACTIVITY_EVENTS.
  • Net behaviour — 30 min of uninterrupted idleness now reliably auto-redirects to the login screen; 5 min of idleness reliably shows the "App last used" ticker; any interaction dismisses the ticker and resets the clock; returning to the tab without interacting leaves the ticker visible until the user touches something.
  • Version bump — Version number incremented to 1.12.3; all page footers and documentation updated accordingly.

v1.12.2 (April 2026) — Fix inactivity warning banner not dismissing on refocus

  • Bug fix: banner persists on refocuscheckClientInactivity() had no else branch, so when the user refocused the app (via window.focus or visibilitychange) and the elapsed time had fallen back below the 5-minute warning threshold, the "App last used" strip was never removed. Added an else { dismissInactivityWarning(); } branch so that refocusing always dismisses the banner when the session is still within the warning window.
  • Version bump — Version number incremented to 1.12.2; all page footers and documentation updated accordingly.

v1.12.1 (April 2026) — Window-focus session-expiry catch-all

  • Refocus expiry check — Added a window.focus event listener as a belt-and-suspenders complement to the existing visibilitychange listener. When the browser window regains focus from another application (or after a screen-lock/wake cycle on platforms where visibilitychange does not fire), the session-expiry check now runs immediately, redirecting users to the login screen if the 30-minute inactivity timeout has elapsed.
  • Version bump — Version number incremented to 1.12.1; all page footers and documentation updated accordingly.

v1.12.0 (April 2026) — Session inactivity warning overlay

  • Inactivity warning overlay — After 5 minutes of no interaction a slim amber strip appears at the bottom of the screen showing "App last used: HH:MM". Any interaction (tap, key press, scroll) immediately dismisses it and resets the inactivity clock. The overlay has no interactive controls of its own (pointer-events: none) so the underlying app remains fully usable without a separate dismiss step. Correct iOS safe-area padding is applied so the strip never covers the home-indicator gesture bar.
  • Interaction-triggered expiry — If a user interacts with the app after the full 30-minute idle timeout has already elapsed (e.g. returning from a long background tab that missed the periodic check), the interaction itself immediately triggers the session-expiry flow instead of silently extending the clock.
  • Stale-token fix — "Log in again" after an inactivity logout now performs a full location.reload() rather than an in-place re-render. This guarantees a fresh CSRF token and clean client state, eliminating the second attempt needed bug on return-to-login.
  • renderLogin() CSRF refreshrenderLogin() now unconditionally fetches a fresh CSRF token before rendering, covering the 401-redirect code path that bypasses returnToLogin().
  • Bug fix: immediate re-expiry on fresh loginstartActivityTracking() previously called updateLastActive() at startup, which (with the new expiry-trigger guard) would immediately call forceSessionExpiry() if a stale tasker_last_active timestamp from a prior session was still in localStorage. Fixed: the session baseline is now stamped directly without running the expiry check.
  • Bug fix: double forceSessionExpiry invocation — Added a _sessionExpiryInProgress guard flag to prevent forceSessionExpiry() from being entered a second time from a visibilitychange event that fires between stopActivityTracking() and state.user = null.
  • Version bump — Version number incremented to 1.12.0; all page footers and documentation updated accordingly.

v1.11.1 (April 2026) — Final UI & functional verification

  • Full UI and functional check — all routes, middleware, SPA views, and user flows reviewed end-to-end. No functional regressions found. All 241 tests pass; TypeScript compiles with zero errors.
  • Version bump — Version number incremented to 1.11.1; all page footers and documentation updated accordingly.

v1.10.0 (April 2026) — Security hardening

  • Session fixation prevention — The session ID is now regenerated (req.session.regenerate()) immediately after successful credential validation on both the standard login path and after 2FA code verification. This eliminates the session fixation attack vector.
  • SMTP error sanitisation — Raw nodemailer error messages (which can contain SMTP host names, port numbers, and authentication failure details) are no longer forwarded to clients. All email-delivery failures now return a generic "SMTP error" message. The full error is logged server-side only.
  • Global error handler — An Express error-handling middleware has been added as the last registered middleware in server.ts. Any unexpected synchronous or asynchronous error is caught, logged, and returned as a generic 500 JSON response, preventing accidental stack-trace or path leakage.
  • MFA constant-time comparison — The 6-digit 2FA code is now compared using crypto.timingSafeEqual() instead of a plain string equality check, eliminating a theoretical timing side-channel.
  • User option allowlist enforcementPUT /api/auth/my-options now validates that every submitted option ID corresponds to an approved=1 dropdown option. Unapproved IDs are silently discarded. Previously a user could pin an unapproved (pending) option to their account.
  • /readyz rate-limited — The health-check endpoint now sits behind the same apiLimiter (200 req/min per IP) as all other public endpoints, preventing it from being used as an open amplification target.
  • Column-name allowlist in common-fields — The topN helper in GET /api/tasks/common-fields now includes an explicit ALLOWED_FIELDS Set guard before interpolating column names into SQL, providing defence-in-depth against any future refactoring that might pass user input to the function.
  • Security test suite expanded — 7 additional tests added (session fixation, SMTP sanitisation ×3, option allowlist ×2) bringing the total to 241 negative security tests.
  • Version bump — Version number incremented to 1.10.0.

v1.9.1 (April 2026)

  • Analytics XLSX report — Replaced the "Print / Save as PDF" button in the analytics section with a "Download Analytics (.xlsx)" button. Clicking it downloads Tasker-Analytics-YYYYMMDDHHmm.xlsx — a multi-sheet workbook with one data table sheet per chart, mirroring all graphical output: Summary, Time by Category, Duty vs Personal, Outcome Distribution, Outcome by Category, Avg Duration (Category), Tasks by Type, Avg Duration (Task Type), Task Types by Source Group, Flag Distribution, Flags by Source Group, Activity by Hour, Activity by Day of Week, Task Types by Day Assigned, Personal by Day (Origin), Personal by Day (Type), Tasks Over Time (with optional regression trend column), Interruptions Over Time, and Assignment Lag. Sheets are only included when the corresponding chart would be visible. Served by a new GET /api/analytics/report endpoint that accepts the same filter parameters as the history view.
  • Version bump — Version number incremented to 1.9.1; all page footers and documentation updated accordingly.

v1.9.0 (April 2026)

  • Version bump — Version number incremented to 1.9.0; all page footers and documentation updated accordingly.

v1.8.6 (April 2026)

  • Suggestion safety notice — The "Send suggestion to developers" input now displays a prominent warning instructing users not to submit any patient, location, or staff-identifiable information. The notice also clarifies that submitted freetext is sent to an NHS.net email address and invites users to include their own email address if they wish to receive a reply.
  • Documentation updates — help.html, guide.html, dpia.html, technical-manual.html, installation.md, and maintenance.md updated to document the suggestion feature data flow and acceptable-use requirements.

v1.8.1 (April 2026)

  • SMTP email configuration — Added SMTP settings section in the admin panel. Dropdown and flag suggestions from users are now emailed to the administrator instead of being stored on the server. This removes free-text personal data from the database in line with data protection principles. Supports STARTTLS (port 587) and SSL/TLS (port 465). SMTP password is encrypted at rest using AES-256-GCM.
  • Task flags replace free-text notes — The free-text "Notes" field has been removed from task review. Instead, users select from an admin-managed list of structured flag options (e.g. "Sent to wrong user", "Priority too high"). Multiple flags can be applied per task. Flags are stored per-task in a dedicated task_flags table.
  • User-suggestable flags — Users can suggest new flag options from the task review screen. Suggestions are sent by email to the administrator and never stored on the server.
  • Notices — Administrators can create, edit, activate/deactivate, and delete notices that appear prominently on every user's home screen.
  • User messages — Administrators can send messages to individual users or broadcast to all active users. Messages appear on the user's home screen with individual dismiss controls.
  • Auto-notification on dropdown approval — When an admin adds a new dropdown option for a field, users who had pending email proposals for that field automatically receive a user message confirming the update.
  • Analytics updates — New "Flagged tasks" stat card; new "Task Flag Distribution" bar chart; flag labels shown on individual task cards; export includes Flags column instead of Notes.
  • Default flag options — Five default task flag options are seeded on first run: "Sent to wrong user", "Priority too high", "Priority too low", "Should be sent to group", "Should be sent to specific user".
  • Dependency — Added nodemailer@8.0.5.

v1.7.1 (April 2026)

  • Policy update — Removed restriction on use over NHS networks or NHS Wi-Fi. The application may now be accessed from any network. Updated Data and Use Policy, DPIA, and all supporting documentation accordingly.

v1.5.0 (April 2026)

  • User groups — administrators create named groups that control which dropdown options users see. Each group has an independent option set configurable from the admin panel.
  • Personal option customisation — after selecting a group, users are presented with a ⚙️ Customise My Options screen showing all group defaults as tick-boxes. Users can untick options they never use; their choices are stored per-account and override group defaults in all task forms. The screen is accessible at any time from ⚙️ Settings.
  • Group proposals — users can suggest new group names from the group-selection screen. Proposals appear in a new Pending Group Proposals section of the Admin Panel for administrator approval or rejection.
  • Option proposals — users can suggest new dropdown values (Task From, Task Type, Outcome) inline from the Customise My Options screen. Proposals appear in the existing Pending User Proposals section.
  • Integrated combobox dropdowns — all task-form dropdowns (Task From, Task Type, Outcome) are now fully searchable comboboxes. Clicking opens a panel; typing filters options instantly; arrow keys navigate; Enter selects; Escape closes. No separate search boxes.
  • Admin desktop layout — the admin panel is now wider (max-width 900 px) on desktop with Users/User Groups in a two-column grid and Dropdown Options shown three-across.
  • Modal positioning fix — option and group modals are now centred in the viewport on screens ≥640 px with action buttons pinned to the bottom of the dialog.
  • Security hardeningPOST /api/auth/set-group now enforces is_approved=1, preventing users from joining a pending/unapproved group. A safeId() helper strips non-identifier characters from combobox IDs before insertion into inline HTML event handlers.
  • Security test suite — 52 negative tests (src/__tests__/security.test.ts, run with npm test) covering CSRF, authentication, IDOR, SQL injection, XSS, input validation, resource exhaustion, error handling, temporal consistency, path traversal, and group access control.
  • TASKER_DB_PATH env var — allows test isolation by pointing the DB singleton at an in-process temp file.

v1.4.0 (April 2026)

  • SPA back/forward navigation — browser Back and Forward buttons now work correctly throughout the app. Every view transition records itself in the browser history stack (history.pushState); a popstate listener dispatches navigation events back to the correct render function with an auth guard.
  • Asset version-gate reload — on startup the app fetches /api/version (network-first, bypassing the service worker cache) and compares it to the version stored in localStorage. On a mismatch all service worker caches are cleared, the service worker is unregistered, and the page reloads to guarantee fresh app.js, app.css, and index.html are loaded.
  • GET /api/version — new lightweight endpoint returning { "version": "1.4.0" }, rate-limited.

v1.2.0 (April 2026)

  • Health-check endpointGET /readyz returns {"ok":true,"service":"Tasker","version":"1.2.0","timestamp":"..."} for uptime/heartbeat polling servers. No authentication required.
  • Login error messages — failed login attempts (wrong username or password) now display the server's friendly error message in the login form instead of silently resetting the form.

v1.1.0

  • Initial public release with task logging, analytics, admin panel, Excel export, PWA support, and configurable registration.

About

Task logger for staff members to keep track of job requests

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages