9.3 KiB
9.3 KiB
Changelog
All notable changes to FORGE are documented here. Format based on Keep a Changelog; this project uses Semantic Versioning.
[2.3.2] — 2026-08-29
Changed
- PM Insights — full-width category items. Inside Alert categories and
Watch list, each category is now a full-width accordion stacked in a single
column (was a narrow multi-column grid), with more breathing room: larger inter-card
gap, roomier card headers and ticket rows, and a taller expanded list. The click-to-
expand behaviour per category is unchanged. (CSS-only: the
.gridbecomes a flex column;.cardHead/.rowpadding widened.)
[2.3.1] — 2026-08-29
Changed
- PM Insights — collapsible sections. The Alert categories and Watch list
sections are now accordions: each heading is a button (chevron + a category-count
badge,
aria-expanded/aria-controls) that collapses/expands its card grid. Both default to open; the per-card ticket expand and the Per-PM roll-up table are unchanged. Adds aChevronIcon(rotates with the section) and a.grid[hidden]rule so a collapsed grid actually hides.
[2.3.0] — 2026-08-27
Added
- Jira status durations (chart #17) — a new "Jira status durations (avg days)"
chart on the Active-stats page: average time each Jira workflow status is held,
in the board's column order, min-2-tickets. Server endpoint
GET /api/analytics/jira-durations(PM+) aggregatesjira.statusDurations(ms) across tickets. - The extension's Jira collector now fetches each issue's changelog
(
expand=changelog) and computesstatusDurations(time per status) +movements({at, who, from, to}), sent inside thejiraobject. - Seed enrichment:
statusDurations+ the Jira workflow column order are ingested from the dump'sjira_board_state(so the chart is populated before any live sync — 73 seeded tickets carry durations).JiraInfotype extended withstatusDurations/movements.
[2.2.0] — 2026-08-27
Added
- Jira sync in the extension (per the sync ADR). One "Sync now" now refreshes
SNOW then Jira: SNOW stays as the in-page same-origin session collector →
/api/sync; Jira is pulled by a new service-worker collector via direct REST (/rest/agile/1.0/board/{id}/issue) authenticated with a Jira API token — Basic (email+token, Cloud) or Bearer PAT (Server/DC, e.g.support.dataart.com). Issue links are built as<baseUrl>/browse/<KEY>(custom Jira domains supported). - New extension options: Jira base URL, email, API token/PAT, and board id(s).
- New server endpoint
POST /api/sync/jira— attach-only: updates only thejiraJSONB (merged) +jira_keyon existing tickets, keyed by RITM number; never touches status/state/assignee/activity (avoids the ticket-upsert clobber). Token-authed. Jira RITM↔issue resolved viacustomfield_26001or aRITM\d+regex; Jira failures are best-effort and never fail a successful SNOW sync.
Added
- Polished Excel export — the board's Excel export is now filterable and readable:
the ticket Number is a clickable ServiceNow hyperlink (a real OOXML hyperlink
relationship — locale-proof, unlike a
HYPERLINK()formula which breaks in;-locale Excel), auto-filter on every column, zebra-striped rows, taller rows + wider columns, a frozen indigo header, right-aligned numbers,#,##0cost, short dates, and a dated filename (forge-active-tickets-YYYY-MM-DD.xlsx). The standalone Link column was folded into the Number cell. (auto-filter + hyperlinks injected viafflate.) - App favicon (indigo snowflake) +
theme-color. - A proper Excel-brand button icon (green tile) replacing the placeholder glyph.
Changed
- RITM number links out to ServiceNow in the ticket table + board cards (new tab).
- Deploy: ported Husky's
push-to-nas.sh+ on-NASdeploy.sh(SSH key pinning, openrsync→tar fallback, Synology PATH/sudo, health poll,forge-dbvolume preserved on--fresh); macOS AppleDouble (._*) files excluded from sync/build/tests.
Dependencies
- Added
fflate(xlsx auto-filter post-processing).write-excel-filepinned at 2.x (v4 drops the default export + still has no hyperlink support).
2.0.0 — 2026-08-27 · FORGE 2.0
The analytics release. FORGE grows from a ticket board into a full ServiceNow analytics portal ported from the Let it Snow Chrome extension, with role-based access, admin tooling, and the complete statistics suite.
Added
- Full analytics data ingest. The seed now loads the entire
analytics_datamaster (954 ticket records) merged with the operational cache, plus SLA norms, FX rates, size thresholds, brand palette, and the colleague roster. New ticket columns (all additive):currency_code, opened_by, opened_date, closed_date, to_do_at, in_uat_at, jira_key, ticket_year, size, po_number, invoiced. A reproducibledump-to-archives→reseedpipeline regenerates seed data from a storage dump.app_configkey/value table for norms/thresholds/palettes. - Server analytics engine (
server/analytics.ts,server/insights.ts):/api/analytics/overview,/api/analytics/sla,/api/insights,/api/config. - Overall statistics page — year-overlay grouped bars (opened/closed/revenue, bars↔line + YoY%), a Cost↔Tickets toggle, a ticket-share donut (#/% + top-N), brand→market and requester→brand drill-downs, KPI tiles, lifetime histogram.
- Active statistics page — by-status, age distribution, opened-per-month, median days-in-status, by-brand.
- PM KPIs — SLA page — six PM×size heatmaps (TTFR, PM response, avg-close, OTD, assign, preview) scored against per-size norms, green/red vs target.
- PM Insights page — problem/alert KPIs over the active backlog (unassigned, on-hold, WIP-stalled, customer-replied, awaiting, lifetime, inactive), Jira-breach and client-owed rules, waiting-PO with L1/L2/L3 escalation, revenue-at-risk, and a per-PM roll-up. (Rev-at-risk matches the initial app's own figure within rounding.)
- Board redesign — 7-state kanban (Unassigned → Open/Assigned → On Hold → WIP → Customer replied → Awaiting) with the WIP→"Customer replied" pseudo-status, SLA subtitles, per-column counts, brand/market/PM filters, board/list toggle, and a ticket detail modal.
- Role-based access control — four roles (Viewer, PM, Project Leadership, Admin) enforced server-side per route; the client hides nav/pages above a user's role. Only admins can create admins.
- Admin page — user management (Project Leadership+) and API-token management
(Admin only): create/list/revoke
fg_…sync tokens from the UI. - Filtered Excel export — the board's ⭳ Excel button exports the currently
filtered tickets as a styled
.xlsx(branded indigo frozen header, per-column widths, right-aligned numbers,#,##0cost, short dates, grid borders). - Finance ingest — cost + PO + invoiced per ticket from the finance sheet, enriching active tickets with cost/size and powering waiting-PO.
- Config bundle exposed via
/api/config(brand colours, colleagues, norms, FX).
Changed
- All analytics pages are full-width (removed the 1280px cap).
/api/tokensis now gated by the admin session role instead of anADMIN_KEYheader. Themint-tokenCLI is unchanged.- Non-destructive sync upsert: a thin sync no longer nulls seeded-rich fields
(
COALESCE/CASEpreserve brand/market/description/jira/activity/analytics).
Fixed
due_datetimezone off-by-one (emit localYYYY-MM-DD, nottoISOString()).- Activity render-crash vector (ingest sanitizes activity entries;
parseDateguards). - Seed "active wins" ordering on tickets present in both archives.
- Ticket-share donut used a truncated distribution (center 375); now the full 966.
Security
- Read-API authentication (session, username+password, bcrypt, Postgres session store).
- Least-privilege database role (
forge_app, not a superuser) owns the app tables. - API tokens:
fg_<id>_<secret>, only the SHA-256 stored, constant-time verify, revocable;token_hashnever leaked by the list endpoint. - RBAC hardening (post-audit): only an admin can delete an admin; the last admin cannot be deleted (lockout guard); deleting a user purges their sessions; the session id is regenerated on login (anti session-fixation); delete of a missing user returns 404.
1.0.0 — 2026-08-27
Initial full-stack scaffold, ported from the Let it Snow Chrome extension onto the Husky repo list template.
Added
- Vite + React 18 + TypeScript client (SCSS modules, react-router) with a Sidebar/ TopBar layout; Active board, Closed, and basic Statistics pages.
- Express + TypeScript server on Postgres (
forge); self-bootstrapping schema (initDB) that seeds bundled ticket archives on first boot. - REST API:
/api/tickets,/api/tickets/:number,/api/stats,/healthz, and a token-authed/api/syncingest. - Chrome sync extension ("FORGE Snow Sync") — reads active RITM tickets from the ServiceNow Table API and pushes them to the portal with a bearer token.
- Multi-stage Dockerfile + docker-compose (bundled Postgres) targeting
forge.mycloud.dp.ua; README + SETUP docs.