Skip to content

chore: release v14.4.0 - promote staging to main#260

Closed
parth0025 wants to merge 322 commits into
mainfrom
release/v14.4.0
Closed

chore: release v14.4.0 - promote staging to main#260
parth0025 wants to merge 322 commits into
mainfrom
release/v14.4.0

Conversation

@parth0025

@parth0025 parth0025 commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Release v14.4.0 β€” staging β†’ main promotion

Promotes the full staging line to production for the v14.4.0 release. Cut as release/v14.4.0 because the main branch-name check requires release/vX.Y.Z.

Headline contents

Merge instructions

  • Use a merge commit (not squash) β€” per the AlianHub release flow.
  • After merge, back-merge main β†’ staging to keep the two branches aligned.

πŸ€– Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Two-Factor Authentication (TOTP-based 2FA with recovery codes)
    • Recurring Tasks with scheduling (daily, weekly, monthly)
    • CSV and Trello board imports
    • Agile Reports (Burndown, Velocity, Cumulative Flow Diagram charts)
    • Gantt/Timeline View with drag-and-drop scheduling and dependencies
    • Story Points estimation scale (fibonacci, linear, t-shirt, hours)
    • Epic enhancements (start/due dates, owner, priority levels, in-progress status)
    • Password-protected public shares with expiry dates
    • @Mentions in comments with notifications
    • Blocked task warnings (indicator when blocked by open tasks)
    • Webhook integrations for Slack and Discord
  • Improvements

    • Enhanced task update tracking with changed-fields metadata
    • Improved public share token security

shyamvadaliya12 and others added 30 commits May 12, 2026 11:08
CLAUDE.md says the project standardised on Luxon. The backend still
imported `moment` in five files for trivial date formatting; this PR
removes those usages and drops `moment` from the root package.json.

Frontend `moment` usage (hundreds of call sites across Timesheet /
TimeLog / composables) is NOT touched here β€” that's a much larger
migration scoped separately. The frontend's own `package.json` keeps
its `moment` entry so the Vue build doesn't break.

New helper:
* `utils/dateHelpers.js` exposes
  - `formatDate(input, fmt)` β€” accepts JS Date, millis, ISO string,
    or `{seconds}` shape, and translates moment-style format tokens
    (YYYY/MM/DD/HH/mm/ss/A/MMM/ddd) to luxon-style under the hood
    so existing callers don't have to change their format strings.
  - `formatNotificationDate(input)` β€” exact replacement for the two
    `moment.calendar()` sites in `Modules/notification/sendEmail/`,
    which both used the same format string for every branch (so the
    relative-time wrapper was a no-op). Preserves the original
    output, including the pre-existing `HH:MM` token quirk.

Migrations:
* `Modules/logTime/controllerV2.js` β€” single `.format("YYYY-MM-DD")`
  call β†’ `formatDate(date, 'yyyy-LL-dd')`.
* `Modules/notification/sendEmail/controller.js` and
  `Modules/notification/sendEmail/controllerV2.js` β€”
  `moment().calendar(...)` β†’ `formatNotificationDate(...)`.
* `Modules/tasks/helpers/helper.js` and
  `Modules/tasks/helpers/mongo_helper.js` β€” `changeDateFormat`
  delegates to `formatDate` (which keeps the moment-style API its
  callers pass).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two affordances dispatched click handlers on non-semantic elements
(no role, no aria-label, no keyboard focus, no screen-reader
announcement):

* `frontend/src/components/atom/Modal/Modal.vue` β€” the modal close
  icon was a bare `<img @click="closeModal()">`. Wrap in
  `<button type="button" :aria-label="$t('Projects.close') || 'Close'">`
  with the icon inside as a presentational `<img alt="">`.
* `frontend/src/components/atom/Attachments/Attachments.vue` β€” the
  "Download All" affordance was a `<span @click="downloadAllImages()">`.
  Replace with `<button type="button" class="download-all-btn ...">`.

Both components' stylesheets gain a tiny rule to strip native button
chrome (so the visual result matches the old elements) but preserve
`:focus-visible` so keyboard users see the focused state.

Note: a couple of nearby affordances (Attachments' "See All" `<div>`
and the help-icon popover) have the same anti-pattern but are out of
scope here β€” the audit specifically flagged the `<span>` and `<img>`
cases above.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Modal atom rendered a bare `<div class="modal">` β€” no role,
no aria-modal, no aria-labelledby. Screen readers couldn't announce
the modal as a dialog and focus could leave the modal via Tab and
reach background controls.

Changes to `frontend/src/components/atom/Modal/Modal.vue`:

* Template:
  - Root `<div class="modal">` gains `role="dialog"`,
    `aria-modal="true"`, `:aria-labelledby="titleId"`, and
    `tabindex="-1"` (so focus can land on the dialog itself when no
    children are focusable).
  - The title `<span>` now carries the `:id="titleId"` that
    aria-labelledby points at.
  - `@keydown.tab="handleTabKeydown"` traps Tab; `@keydown.esc.stop`
    closes the modal on Escape.

* Script:
  - `modalRef` template ref + `titleId` computed.
  - `handleTabKeydown` cycles focus between the first and last
    focusable descendants (queries the standard focusable selector
    list, skipping aria-hidden and offscreen elements).
  - `activateFocusTrap` captures the previously-focused element and
    moves focus to the first focusable inside the modal (or the
    dialog itself if there are none). Called on mount-if-open and
    when `modelValue` flips to true.
  - `deactivateFocusTrap` restores focus to the captured element on
    close / unmount.

No new dependency: the trap is ~40 lines of inline logic; we don't
need `focus-trap` for one component.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`npm test` was a placeholder (`echo "Error: no test specified" && exit 1`)
even though jest was already installed as a devDependency. This PR
wires it up as a working bootstrap suite that future fixes can grow
into.

Changes:

* `package.json` β€”
  - `test` now runs `jest`.
  - new `test:watch` (development) and `test:naming` (the pre-existing
    structural-audit test, kept off the default run because it flags
    legacy naming inconsistencies tracked separately).
* `jest.config.js` β€” points jest at `tests/`, ignores
  node_modules/frontend/installation/time-tracker-app/.claude and the
  naming-conventions audit, and runs in `node` environment.
* `tests/smoke.test.js` β€” minimal guarantee the harness is alive
  (always runs).
* `tests/utils/dateHelpers.test.js`, `tests/utils/safeServiceFile.test.js`,
  `tests/utils/imageGuard.test.js` β€” behaviour tests for the helpers
  introduced earlier in this audit (BUG-042, BUG-036, BUG-023). Each
  suite is wrapped in a graceful skip when its target module isn't on
  the current branch, so this PR lands cleanly today and the tests
  light up automatically once the corresponding helper PRs merge to
  staging.

`npm test` exits 0 β€” 3 passed (smoke) + 16 skipped (helpers pending
merge). After BUG-023/036/042 merge, all 19 should pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`Modules/tasks/helpers/{helper,mongo_helper}.js`'s `HandleHistory`
wrote `createdAt` / `updatedAt` manually using `DateTime.utc().ts`,
which is a numeric millisecond value β€” not a BSON Date. Existing
documents ended up with inconsistent shapes (number vs Date) depending
on which code path created them.

Every other schema in `utils/mongo-handler/createSchema.js` is built
with `{ timestamps: true }` so Mongoose owns the timestamps. The
history schema alone was missing that option.

Changes:

* `utils/mongo-handler/createSchema.js` β€” add
  `{ strict: false, timestamps: true }` to `historySchema`.
* `Modules/tasks/helpers/mongo_helper.js` (HandleHistory) and
  `Modules/tasks/helpers/helper.js` (HandleHistory) β€” drop the manual
  `createdAt: utcDateTime.ts, updatedAt: utcDateTime.ts` lines.
  Mongoose populates both as BSON Dates on `.save()`.
* `utils/mongo-handler/schema.js` β€” keep `createdAt`/`updatedAt`
  declared on the history shape so callers that read them still work,
  but drop `required: true`. Mongoose sets them on `.save()`; making
  them required on updates would reject legacy docs that never had
  them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`frontend/src/components/molecules/DropDown/CustomDropDown.vue` is the
shared custom dropdown atom used across the app. Pre-fix:

* The trigger `<div @click="buttonClick()">` had no role,
  no aria-haspopup, no aria-expanded, no tabindex β€” keyboard users
  couldn't reach or open it.
* The floating panel had no role="listbox" β€” screen readers couldn't
  identify it as a menu.
* The mobile-view close affordance was a bare clickable `<img>`.

Changes:

* Trigger gains role="button", tabindex="0", :aria-haspopup="'listbox'",
  :aria-expanded (bound to open state), :aria-controls (panel id).
* Trigger handles keyboard:
  - Enter / Space β€” open/close (mirrors click).
  - Escape β€” close.
  - ArrowDown β€” open AND move focus to the first focusable child
    inside the options slot. (We can't enforce role="option" on
    user-provided slot content, but moving focus there gets keyboard
    users navigating immediately.)
* Floating panel gains role="listbox" and an @keydown.esc handler.
* Mobile close `<img>` wrapped in a real `<button type="button">`
  with aria-label="Close" and a style rule (`.dropdown-close-btn`)
  that strips native chrome but preserves :focus-visible.
* New helpers: `closeDropdown()` and `openAndFocusFirstOption()`.

Note: the sibling `DropDown.vue` and `MobileDropDown.vue` follow the
same anti-pattern but were not flagged by the audit; they'd benefit
from a similar sweep in a follow-up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Done - Test Case
…itation-body

fix(security): stop overwriting req.body, allow-list invite keys (BUG-011 / #65)
fix(security): tighten + env-configure auth rate limit (BUG-012 / #66)
…-revalidation

fix(security): re-validate company membership per request, cached (BUG-013 / #67)
…on-token-empty

fix(security): tighten verifyEmail against loose-equality bypass (BUG-014 / #68)
…er-resolve

fix(stability): stop calling reject after resolve in HandleTask (BUG-016 / #70)
fix(stability): replace forEach(async) fire-and-forget pattern (BUG-017 / #71)
…-rejection

fix(stability): surface allSettled rejection reasons (BUG-018 / #72)
…lobal-setchat

fix(stability): declare setChat with const (BUG-019 / #73)
…stringify

fix(stability): align cache set/remove key in MainChats (BUG-020 / #74)
perf: add MongoDB indexes for hot query paths (BUG-021 / #75)
chore(deps): upgrade sharp 0.32.6 β†’ ^0.34.0 (BUG-022 / #76)
…-limits

fix(security): guard sharp() inputs against pixel-bomb DoS (BUG-023 / #77)
…-handlers

perf: switch readFileSync in request handlers to async (BUG-024 / #78)
…g-leaks

fix(observability): route console.* through Winston (BUG-025 / #79)
…ality

fix(stability): strict equality on isEmailVerified check (BUG-026 / #80)
…age-fix

fix: correct copy-paste error in companyId validation message (BUG-028 / #82)
…on-null-guard

fix: validate timeDuration shape before .split(':') (BUG-029 / #83)
…a-null-guard

fix(stability): guard against missing response.data in sprints (BUG-030 / #84)
…-send

fix(stability): guard checkUserAndCompany against duplicate res.send (BUG-027 / #81)
…fication-silent-catch

fix(observability): log silently-swallowed fetch failures (BUG-031 / #85)
…e-filtering

fix(BUG-032): consistent soft-delete filtering on list/count endpoints
parth0025 and others added 23 commits June 16, 2026 18:14
…249)

* fix: address safe CodeRabbit findings from the promotion (#240) review

Six low-risk, verified fixes:
- Webhooks/dispatcher.js: guard against an undefined pending entry in the debounce callback (entry.doc could throw).
- gitlabOAuth/controller.js: add a 15s timeout to the token-exchange axios call (was unbounded).
- Admin/common/controller.js: drop an erroneous JSON.parse in the missing-file branch (makeDefaultBrandSettings resolves an object) - fixes a first-run 404 on getBrandSettingsData.
- Stickies/helpers/stickyRules.js: strict boolean for isPinned (the string 'false' no longer coerces to true).
- StickiesPanel.vue: clear the pending debounced save in remove() so it cannot fire a stale PUT after delete.
- README.md: 'Priority support & SLAs' -> 'response-time targets' to match SUPPORT.md.

Verified: node --check (backend), sticky-rules jest 16/16, StickiesPanel SFC compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: scope updateMember role-promotion guard to PAT requests

Companion to #248: the owner-only role-promotion check in updateMember now runs only for PAT/MCP requests (req.apiToken), so the web app's role management behaves exactly as before. Same 2026-06-15 MCP-isolation hardening as permissionGuard.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(release): back-merge main into staging after v14.3.0
feat(auth): add opt-in TOTP two-factor authentication (Phase 1)
…ion-aware notifications

Integrations (Settings β†’ Integrations):
- Manage Slack / Discord / JSON outgoing webhooks with per-event
  subscriptions and delivery logs
- Action-aware notifications: announce the specific change (status,
  assignee, priority, due, rename, estimate, …) with fromβ†’to diffs and
  assignee/lead ids resolved to names
- Deliver exactly one task.created on create (suppress create-flow churn
  and the project-counter phantom emit); re-read the full task before
  delivery so payloads are complete

Importers (project filter toolbar):
- CSV and Trello importers mirroring the Jira importer; map columns /
  lists onto the project's statuses
- Resolve statuses from the project's taskStatusData with a guaranteed
  type/key so imports never fail statusType validation; route the Jira
  importer through the same shared helper
- Downloadable sample templates in all three import modals

Tasks:
- Stop the automatic AI time estimate on task creation (manual-only now)

Tests: 198 passing (webhook-rules, csv-rules, trello-rules).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ention notifications

S3-01 Trello rich import: extract checklists, comments, labels, attachments and member emails from board JSON; enrich imported tasks (assignee resolution by email, checklist items, attachment link-refs, labels appended to description) and create comments post-import.

S3-02 Story points: points field + updatePoints action and permission; per-project estimation scale (fibonacci/linear/tshirt/hours) with a config modal and POST /api/v1/projectSetting/estimationScale; a scale-aware points picker on the task detail panel; and a points rollup in list group headers.

S3-04 @mention notifications: parse [Name](userId) mentions from comment text, persist a mentions record, and dispatch the "@mentioned" notification on comment create and update.

S3-03 backlog view was skipped (AlianHub has no un-sprinted tasks) and its scaffolding removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation

feat(integrations): sprint 2 β€” webhooks UI, CSV/Trello importers, action-aware notifications
…ivity

node-global-key-listener ships a native hook binary (WinKeyServer.exe) that antivirus (Bitdefender) flags as a keylogger and quarantines, silently zeroing all keyboard/mouse activity counts. Replace it with Electron's built-in powerMonitor.getSystemIdleTime(): while tracking, sample once per second and emit an activity tick per active second. No native binary, no accessibility permission, AV-proof, cross-platform.

Desktop: background.js runs a 1 Hz idle sampler emitting 'activity:tick'; timelog.js setActivityTick buckets ticks per minute as { active: N }; trackerRunning.jsx and tracker.js consume it and strokes carry { active }; package.json drops the dependency. Frontend helper.js surfaces the active value in the existing Keyboard column (Mouse stays 0); old timesheets keep their original keyboard/mouse counts. Backend and DB schema unchanged - strokes are stored opaquely in trackShots.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation

feat(sprint3): story points, estimation scale, Trello rich import, @mention notifications
Refines the powerMonitor approach so the timesheet shows real Keyboard AND Mouse activity instead of one combined value. Each second while tracking, the sampler reads two hook-free signals - powerMonitor.getSystemIdleTime() and screen.getCursorScreenPoint(): cursor moved => mouse activity; input with no cursor movement (typing) => keyboard activity. Still no global input hook, so antivirus does not flag it. A click that does not move the cursor counts as keyboard (acceptable trade-off vs the AV-flagged hook).

Strokes return to the { keyboard, mouse } shape, so the web frontend needs no change: helper.js reverts to its original (reads keyboard/mouse) and the production website displays the data correctly with no deploy.

background.js: cursor-movement + idle sampler emits activity:tick with a type; timelog.js setActivityTick buckets per minute as { keyboard, mouse }; trackerRunning.jsx and tracker.js pass the type and build keyboard/mouse strokes; helper.js reverted to original.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…owermonitor

fix(tracker): AV-safe keyboard/mouse activity detection
S4-01 burndown: Sprints/burndown.js now also computes story points (totalPoints + per-day remainingPoints/idealPoints) alongside the existing count/hours, exposed at GET /api/v1/agile/burndown (query-aware, reuses the existing handler).

S4-02 velocity + S4-03 CFD: new Modules/AgileReports/ β€” GET /api/v1/agile/velocity (committed vs completed points per sprint + rolling-3 avg) and /cfd (status-band counts per day). Computed on-the-fly from tasks + Task_Status history instead of a snapshot cron: the cron is production-only (untestable locally) and history already holds the transitions, so no new collection/cron and it works immediately.

S4-04 PDF: new Modules/Export/ β€” POST /api/v1/export/pdf renders a branded PDF from a client payload (table rows + chart dataURI images) via pdfmake (lazy-required so a missing install never breaks startup; standard Helvetica font). Export PDF buttons on each Reports chart.

Frontend: views/Projects/Reports/ (ReportsView + Burndown/Velocity/CFD ApexCharts). Reports added as a first-class add/removable view via the +View catalog (projectTabs response injection + ViewsDropdown preview + projectComponentsIcons + i18n). No DB schema change; backend suite unaffected (208 pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation

feat(sprint4): agile reports β€” burndown, velocity, CFD, PDF export
S5-01 (AHE-3710): chose dhtmlx-gantt (GPL) as the Gantt foundation β€” ADR in docs/adr/gantt-library.md. Lazy-loaded so it never enters the main bundle.

S5-02 (AHE-3714): GanttView.vue β€” a first-class add/removable project view (keyName 'GanttView'). Bars from startDate/DueDate fed live from the Vuex projectData store; drag/resize -> new 'updateDates' task action (PATCH /api/v2/tasks, mirrors updatePoints); dependency arrows from task relations ('blocks' => finish-to-start) with draw/delete -> /api/v2/tasks/relations; day/week/month zoom; unscheduled tray; milestone diamonds from /api/v1/milestone/project/:pid; read-only when the user lacks task-edit permission. Uses the dhtmlx singleton (no destructor) so reopening the tab re-inits cleanly.

S5-03 (AHE-3715): recurring tasks. New RECURRING_TASKS collection wired through the mongo-core path (schemaType/collections/schema/createSchema/mongoQueries). Modules/RecurringTasks/ β€” CRUD + a node-schedule cron (every 15 min, prod-only) that instantiates real tasks via taskMongo.create across all companies, plus /run-now and /run-due endpoints so it is testable in dev. Frontend RecurringTasksManager.vue as an add/removable 'RecurringTasks' view.

Notes: the Gantt/RecurringTasks/Reports views are surfaced in the + View catalog via PROJECT_TAB_COMPONENTS DB records (added per-company), not controller injection. dhtmlx-gantt added to frontend deps. Additive only β€” 208 backend tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation

feat(sprint5): gantt/timeline view + recurring tasks
When Gantt was the active view on a fresh reload, the Vuex task store was empty (only List/Table/Board mount triggers the load via taskListHelper), so the chart rendered nothing. GanttView now triggers the same loader on mount when the store is empty for the project+sprint, and retries if sprints arrive late; the existing reactive watch renders once data lands. Retains the earlier reopen-crash fix (dhtmlx singleton, no destructor, guarded init).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per-feature files in .claude/test-cases/ following the existing template: Integrations (Slack+Discord), CSV importer, Trello importer, story points, @mentions, velocity, CFD, reports PDF export, Gantt, recurring tasks. Includes third-party setup steps (Slack app webhook, Discord webhook, Trello JSON export) and Gantt reload/reopen regression cases. Skips BurndownChart (already present); excludes n8n (not built).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(gantt): render on direct reload + Sprint 2-5 QA test cases
…evoke, rate-limit

S6-02 hardening, all backward-compatible (legacy 16-byte/no-expiry/no-password shares keep working).

Backend: 32-byte tokens (legacy 32-hex still resolve); optional expiresAt (resolveShare 404s expired); optional bcrypt password gate on the public page (POST /share/:token unlock); hard revoke via DELETE /api/v2/public-shares/:id (removes the share + the global token-index row); express-rate-limit on /share/:token (60/min) and intake (10/min); passwordHash never returned (responses expose hasPassword).

Frontend: PublicShareModal exposes expiry + password on create, a lock/expiry status row, and a Delete-link button; + i18n keys.

Verified: 209 backend tests pass (added a legacy-token backward-compat test); SFC + en.js compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dening

feat(public-share): harden read-only links β€” expiry, password, hard-revoke, rate-limit
…rogress

Relations: a task blocked_by an open task now shows a "Blocked by N open
task(s)" alert in its Linked Tasks panel β€” making AlianHub's blocked-task
alert real. Adds getOpenBlockers + the pure selectOpenBlockers helper and an
`openBlockers` action on POST /api/v2/tasks/relations. Additive: the central
status-write path is untouched; the panel reuses data it already loads.

Epics: schema gains startDate, dueDate, ownerUserId, priority; status adds
in_progress; create/update accept + validate the new fields (parseEpicDates,
EPIC_PRIORITIES). EpicsPanel shows a priority badge, owner, dates, a % label
and an inline status select on top of the existing progress bar.

Tests: +16 (selectOpenBlockers/isClosedStatusType, parseEpicDates, priority
& status) β€” full suite 225 pass. Test-cases added under .claude/test-cases/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nhancements

feat(tasks,epics): blocked-task warning + epic dates/owner/priority/progress
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d58bf23-bf51-4296-9a29-fd4920a2087d

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 02d04a0 and b06ee2a.

β›” Files ignored due to path filters (3)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
  • time-tracker-app/package-lock.json is excluded by !**/package-lock.json
πŸ“’ Files selected for processing (108)
  • .claude/import-samples/sample-trello-board.json
  • .claude/test-cases/BlockedTaskWarning.md
  • .claude/test-cases/CsvImporter.md
  • .claude/test-cases/CumulativeFlowDiagram.md
  • .claude/test-cases/EpicEnhancements.md
  • .claude/test-cases/GanttView.md
  • .claude/test-cases/Integrations.md
  • .claude/test-cases/Mentions.md
  • .claude/test-cases/RecurringTasks.md
  • .claude/test-cases/ReportsPdfExport.md
  • .claude/test-cases/StoryPoints.md
  • .claude/test-cases/TrelloImporter.md
  • .claude/test-cases/TwoFactorAuth.md
  • .claude/test-cases/VelocityChart.md
  • .env.example
  • Config/collections.js
  • Config/permissionGuard.js
  • Config/schemaType.js
  • Config/setMiddleware.js
  • Modules/AgileReports/cfd.js
  • Modules/AgileReports/init.js
  • Modules/AgileReports/routes.js
  • Modules/AgileReports/velocity.js
  • Modules/Auth/controller.js
  • Modules/Auth/controller/authHelpers.js
  • Modules/Auth/controller/loginSession.js
  • Modules/Auth/controller/twoFactor.js
  • Modules/Auth/helpers/twoFactorRules.js
  • Modules/Auth/routes.js
  • Modules/Comments/controller.js
  • Modules/Comments/helpers/parseMentions.js
  • Modules/Epics/controller.js
  • Modules/Epics/helpers/epicRules.js
  • Modules/Export/init.js
  • Modules/Export/pdf.js
  • Modules/Export/routes.js
  • Modules/Importers/controller.js
  • Modules/Importers/helpers/csvRules.js
  • Modules/Importers/helpers/trelloRules.js
  • Modules/Importers/routes.js
  • Modules/PublicShares/controller.js
  • Modules/PublicShares/helpers/shareRules.js
  • Modules/PublicShares/publicRenderer.js
  • Modules/PublicShares/routes.js
  • Modules/RecurringTasks/controller.js
  • Modules/RecurringTasks/helper.js
  • Modules/RecurringTasks/init.js
  • Modules/RecurringTasks/routes.js
  • Modules/Sprints/burndown.js
  • Modules/Tasks/helpers/taskMongo/create.js
  • Modules/Tasks/helpers/taskMongo/relationRules.js
  • Modules/Tasks/helpers/taskMongo/relations.js
  • Modules/Tasks/helpers/taskMongo/updateBasic.js
  • Modules/Tasks/routes.js
  • Modules/Webhooks/dispatcher.js
  • Modules/Webhooks/helpers/webhookRules.js
  • Modules/projectSetting/estimationScale.js
  • Modules/projectSetting/routes.js
  • cron.js
  • docs/adr/gantt-library.md
  • frontend/package.json
  • frontend/src/components/atom/StoryPoints/StoryPoints.vue
  • frontend/src/components/molecules/Epics/EpicsPanel.vue
  • frontend/src/components/molecules/EstimationScale/EstimationScaleModal.vue
  • frontend/src/components/molecules/ImportCsv/ImportCsvModal.vue
  • frontend/src/components/molecules/ImportJira/ImportJiraModal.vue
  • frontend/src/components/molecules/ImportTrello/ImportTrelloModal.vue
  • frontend/src/components/molecules/ProjectViews/ViewsDropdown.vue
  • frontend/src/components/molecules/PublicShare/PublicShareModal.vue
  • frontend/src/components/organisms/ItemList/ItemList.vue
  • frontend/src/components/organisms/LinkedTasks/LinkedTasks.vue
  • frontend/src/components/organisms/TaskDetailRightSide/TaskDetailRightSide.vue
  • frontend/src/components/templates/Settings/Settings.vue
  • frontend/src/composable/commonFunction.js
  • frontend/src/config/env.js
  • frontend/src/locales/en.js
  • frontend/src/router/settings/index.js
  • frontend/src/utils/TaskOperations/index.js
  • frontend/src/views/Authentication/Login/Login.vue
  • frontend/src/views/Projects/GanttView/GanttView.vue
  • frontend/src/views/Projects/Projects.vue
  • frontend/src/views/Projects/RecurringTasks/RecurringTasksManager.vue
  • frontend/src/views/Projects/Reports/BurndownChart.vue
  • frontend/src/views/Projects/Reports/CFDChart.vue
  • frontend/src/views/Projects/Reports/ReportsView.vue
  • frontend/src/views/Projects/Reports/VelocityChart.vue
  • frontend/src/views/Projects/Reports/reportsPdf.js
  • frontend/src/views/Projects/components/ProjectFiltersToolbar.vue
  • frontend/src/views/Settings/Integrations/Integrations.vue
  • frontend/src/views/Settings/TwoFactorAuth/TwoFactorAuth.vue
  • index.js
  • package.json
  • tests/csv-rules.test.js
  • tests/epic-rules.test.js
  • tests/parse-mentions.test.js
  • tests/share-rules.test.js
  • tests/task-relations-rules.test.js
  • tests/trello-rules.test.js
  • tests/twofactor-rules.test.js
  • tests/webhook-rules.test.js
  • time-tracker-app/main/background.js
  • time-tracker-app/package.json
  • time-tracker-app/renderer/controller/tracker/tracker.js
  • time-tracker-app/renderer/pages/trackerRunning.jsx
  • time-tracker-app/renderer/store/timelog.js
  • utils/mongo-handler/createSchema.js
  • utils/mongo-handler/mongoQueries.js
  • utils/mongo-handler/schema.js

πŸ“ Walkthrough

Walkthrough

This PR adds 2FA, agile reports with PDF export, CSV and Trello importers, recurring tasks, story points and estimation scale support, Gantt and epic updates, mentions, protected public shares, richer webhook integrations, related tests/docs, and a separate desktop time-tracker activity sampling change.

Changes

Application features

Layer / File(s) Summary
Two-factor authentication flow
Modules/Auth/..., frontend/src/views/Authentication/Login/Login.vue, frontend/src/views/Settings/TwoFactorAuth/TwoFactorAuth.vue, .env.example, tests/twofactor-rules.test.js, .claude/test-cases/TwoFactorAuth.md
Adds TOTP setup, verification, disable, login second-step validation, temp-token/session handling, settings and login UI, persisted 2FA state, env configuration, and tests/spec coverage.
Agile reports and PDF export
Modules/AgileReports/*, Modules/Sprints/burndown.js, Modules/Export/*, frontend/src/views/Projects/Reports/*, .claude/test-cases/{CumulativeFlowDiagram,ReportsPdfExport,VelocityChart}.md
Adds velocity and CFD APIs, extends burndown with point metrics, introduces reports tabs and charts, and adds backend/frontend PDF export support.
CSV and Trello import pipeline
Modules/Importers/*, Modules/Tasks/helpers/taskMongo/create.js, frontend/src/components/molecules/Import*, .claude/import-samples/sample-trello-board.json, tests/{csv-rules,trello-rules}.test.js
Refactors imports around shared context/job execution, adds CSV and Trello import endpoints and parsers, enriches imported tasks/comments, and adds import modals, fixtures, tests, and test-case docs.
Planning data, task scheduling, and project views
Modules/RecurringTasks/*, Modules/projectSetting/*, Modules/Epics/*, Modules/Tasks/helpers/taskMongo/{relationRules,relations,updateBasic}.js, frontend/src/views/Projects/{GanttView,RecurringTasks,Projects.vue,...}, frontend/src/components/{atom/StoryPoints,molecules/Epics,...}, utils/mongo-handler/*, docs/adr/gantt-library.md
Adds recurring task definitions and cron processing, estimation scale and story points updates, Gantt scheduling/date updates, blocker detection, richer epic fields/statuses, new project views, schema updates, and related tests/docs.
Mentions and protected public shares
Modules/Comments/*, Modules/PublicShares/*, frontend/src/components/molecules/PublicShare/PublicShareModal.vue, tests/{parse-mentions,share-rules}.test.js, .claude/test-cases/Mentions.md
Adds mention parsing and notification persistence on comments, and extends public shares with password/expiry handling, sanitized responses, unlock POST flow, deletion, and UI updates.
Webhook summaries and integrations settings
Modules/Webhooks/*, frontend/src/views/Settings/Integrations/Integrations.vue, frontend/src/router/settings/index.js, tests/webhook-rules.test.js, .claude/test-cases/Integrations.md
Adds changed-field webhook summaries with previous snapshots and enriched task payloads, plus a settings UI for webhook CRUD, event selection, logs, and secret handling.

Time tracker activity sampling

Layer / File(s) Summary
Hook-free activity tick pipeline
time-tracker-app/main/background.js, time-tracker-app/renderer/..., time-tracker-app/package.json
Replaces keyboard-hook tracking with sampled activity:tick events, updates renderer/store handling to aggregate keyboard and mouse counts, and bumps the desktop app version.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LoginUI
  participant AuthAPI
  participant TwoFactorAPI
  participant Session
  User->>LoginUI: submit email and password
  LoginUI->>AuthAPI: login request
  AuthAPI-->>LoginUI: twoFactorRequired + tempToken
  User->>LoginUI: enter TOTP or recovery code
  LoginUI->>TwoFactorAPI: validate tempToken + code
  TwoFactorAPI->>Session: finalize session
  Session-->>LoginUI: uid + auth tokens
Loading
sequenceDiagram
  participant User
  participant ReportsUI
  participant AgileReportsAPI
  participant PdfExportAPI
  User->>ReportsUI: open report tab
  ReportsUI->>AgileReportsAPI: fetch burndown/velocity/cfd
  AgileReportsAPI-->>ReportsUI: report data
  User->>ReportsUI: export PDF
  ReportsUI->>PdfExportAPI: send title, chart image, table
  PdfExportAPI-->>ReportsUI: PDF file
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • joshishiv4

Poem

πŸ‡ I hopped through charts and tasks today,
With imports, shares, and locks in play.
A secret code, a gantt so wide,
Recurring plans all neatly tied.
And tiny ticks now softly drumβ€”
More rabbit work has nicely come.

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v14.4.0

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

πŸ”§ ast-grep (0.43.0)
utils/mongo-handler/schema.js

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@parth0025 parth0025 requested a review from joshishiv4 June 19, 2026 13:01
@parth0025 parth0025 changed the title Release v14.4.0 β€” promote staging β†’ main chore: release v14.4.0 - promote staging to main Jun 19, 2026
@parth0025

Copy link
Copy Markdown
Collaborator Author

Superseded by a staging β†’ main promotion PR. The per-commit commitlint job only exempts head=staging/main (not release/*), so the documented release-branch head tripped it on legacy commits; reopening from staging per the established promotion flow (cf. #240/#222/#216). Title fix carries over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants