Release: PEMS overhaul, platform hardening & maintenance mode - #18
Merged
Conversation
- Sticky blurred command header with brand tile, Alt+N shortcut hint - CommandCenterKpis v2: icon tiles, trends, live sync time, responsive grid - Quick-view pills with icons; view switcher with icons - Filters moved to a drawer (adds Frequency filter), active filter chips - Task list: token styling, skeleton loading, per-page selector, richer empty state - Floating bulk-action bar with working Approve/Reject/Export - Create-task wizard rebuilt with antd Steps + inline validation - Right insights panel sticky on wide screens, drawer below 1360px - Full --bc-* design-token adoption; add TASK_LIST_GRID constant - PremiumTaskRow: styling-only changes (hover/selection classes, tokens) All data flow / API logic preserved; verified with esbuild + babel scope checks. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- Introduced CSS rules for mobile and desktop views. - Added visibility toggles for mobile-only and desktop-only elements. - Implemented hover effects for task rows to enhance user interaction.
- Drop BoardView/CalendarView imports, view options and render branches (List / Seller / Objectives remain) - Quick-view pills: uniform 28px height, gradient active state, icon/label alignment, press + focus-visible feedback, hidden scrollbar - Pills now keyboard-accessible (Enter/Space) with tablist/tab semantics Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… SQL TLS to IP - rateLimiter: use ipKeyGenerator() helper for the IP fallback (fixes ERR_ERL_KEY_GEN_IPV6 validation errors on express-rate-limit v8) - db.js / config/env.js: disable TLS by default when the SQL host is an IP literal (Node 24+/26 refuses servername=IP, ERR_INVALID_ARG_VALUE); DB_ENCRYPT=true|false overrides, hostnames keep encrypt:true - db.js: attach pool 'error' listeners to prevent uncaught event crashes - server.js: global unhandledRejection/uncaughtException guards — transient DB/Redis failures log loudly instead of killing the process Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
ipKeyGenerator(ip, ipv6Subnet) is the key generator itself (takes the IP string), not a factory. Calling ipKeyGenerator()(req) threw at runtime: 'ipKeyGenerator(...) is not a function' -> 500 on /api/auth/login. Verified with a live express + HTTP test (IPv4 + IPv6 paths all 200). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… namespaces
- backend/database/migrate.js: numbered migration runner + SchemaMigrations
tracking; supports legacy (runMigration) and modern (up) shapes
- backend/migrations/004_pems_v4.js: recurrence columns/log, SLA dedup
columns, unique event-store version index, query-support indexes
- backend/scripts/runMigrations.js: CLI runner
- db.js: withTransaction() helper (begin/commit/rollback)
- cacheService + middleware/cache.js: namespace-based cacheRoute /
invalidateCache (keys route:{namespace}:{path}) — fixes stale-cache bug
- pemsRoutes/eventHandlers: migrated to namespace invalidation
- server.js: idempotent migrations at startup (RUN_MIGRATIONS_ON_STARTUP gate)
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- New POST /api/pems/instances/bulk/transition (registered before :id routes) with per-id validation, updated/skipped reporting, 200-id cap - submitReview honors REWORK decision via resolveReviewTransition() - Bridged rule tasks now return IsRuleTask: true (matches frontend contract) - Remove duplicate getFilterOptions export (keeps richer v3 version) - notificationMergeService: real UNION of PEMS + legacy Notifications with Source flag and bounded limit - /dashboard/live-tasks: ?limit= (1–50, default 15) - workflowEngine: resolveReviewTransition + 3 unit tests (46 pass) Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- New recurrenceService: hourly materialization of recurring templates with PemsRecurrenceLog idempotency guard, cron-parser for CUSTOM frequency (graceful fallback), batch cap 100, NextScheduledDate advance - schedulerService: hourly PEMS recurrence job + every-30-min SLA escalation job (gates: PEMS_RECURRENCE_ENABLED / PEMS_SLA_ESCALATION_ENABLED) - pems-notification processor: best-effort email dispatch after in-app notification (PEMS_EMAIL_ENABLED=true); emailNotificationService gained skipInApp option + fixed SocketService require path - checkEscalations: dedup windows (SLA_WARNING ≤1/12h, SLA_BREACH ≤1/24h) using LastSlaWarningAt/LastSlaBreachAt columns - package.json: + cron-parser - Unit tests: recurrence math (6 tests) — 52 pass Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…, auth - createInstance / completeSubTask wrapped in withTransaction; writeAuditLog, transitionStatus, submitReview accept optional tx - New submitReviewAndTransition: review insert + workflow transition atomic - eventStore.append: transactional with UPDLOCK+HOLDLOCK versioning + single retry on duplicate key (unique index from 004) - getInstanceById: single-query activity hydration (N+1 fix) - liveDataRoutes: auth on all endpoints (was unauthenticated) - New pemsPolicy (pure access rules) + pemsAccess middleware (assignee / reviewer / global roles; resolves task via subtask/activity ids) - Routes: template writes + instance create require tasks_manage; transition/achievement/subtask/activity/evidence/review require entity access; bulkTransition enforces per-task access (NO_ACCESS skip) - Unit tests: pemsPolicy matrix — 57 pass Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- pemsApi.js: add bulkTransition(ids, toStatus, details) → POST /api/pems/instances/bulk/transition with error body passthrough - TaskInstancesPage bulk bar: single API call, updated/skipped counts surfaced in the toast (replaces per-task Promise.allSettled loop) - docs: implementation status table added to plan Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…lockfile registry
- migrate.js: accept module.exports = async function (pool, sql) —
fixes 'Migration 004_password_resets.js must export up() or runMigration()'
- package-lock.json + backend/package-lock.json: replace 1268 npmmirror
tarball URLs with registry.npmjs.org — fixes npm EALLOWREMOTE
('Fetching packages of type remote have been disabled')
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
The M4 route-guard patch referenced requirePermission/requireTaskAccess but the import line was never written (an earlier script aborted before writing). Caused ReferenceError at startup. All 22 touched backend files re-scanned with a Babel scope checker — zero unresolved identifiers. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- New src/pages/UnderMaintenance.jsx: branded standalone screen (design tokens, animated cog, status pill, customizable message/ETA) - main.jsx: when VITE_MAINTENANCE_MODE=true renders ONLY the maintenance screen — no router, no providers, no API calls - New backend/middleware/maintenanceMode.js: MAINTENANCE_MODE=true returns 503 for all /api/* (health endpoints exempt); wired before routes - .env.example / .env.production.example / .env.staging.example: VITE_MAINTENANCE_MODE, VITE_MAINTENANCE_MESSAGE, VITE_MAINTENANCE_ETA, MAINTENANCE_MODE (all default false/empty) - Middleware behavior verified: api→503, health→pass, off→pass Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…c edition - Dark luxury-storefront aesthetic: aurora light blobs, dotted grid, film grain, glass emblem with rotating dashed rings - Headline with gradient serif-italic accent (We're *restocking* the shelves.) - LIVE system-status console: self-cycling checklist (fills → holds 4s → resets), terminal-style cursor line - Shimmer 'restock progress' bar, ETA chip, support-email footer - Mouse parallax on the aurora layer + full prefers-reduced-motion support - New env overrides: VITE_MAINTENANCE_TITLE (pipe = accent), VITE_MAINTENANCE_EMAIL; documented in .env.example Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Rebuild of UnderMaintenance with an experienced-dev standard: - Light, product-matched theme (design tokens, slate + brand blue) - Real BrandCentral logo with resilient fallback chain: VITE_MAINTENANCE_LOGO → /brandcentral-logo.png → brandcentral.in URL → /retailops-logo.svg (never a broken image) - Quiet motion: one-time fade-up + subtle status-dot pulse, full prefers-reduced-motion support - Semantic layout: centered status card, ETA chip, hairline footer with © BrandCentral Pvt. Ltd. + support email - Sets document title to 'Under Maintenance · BrandCentral' - Removed gimmicks (aurora, checklist console, progress bar, serif accents) - .env.example: documented VITE_MAINTENANCE_LOGO and simplified overrides Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- Uses the project's own RetailOpsWordmark component (same logo as the sidebar: rich black tile + enterprise gold) — no external images - Light product theme matching the app (design tokens, DM Sans) - Title supports |accent| syntax — pipe-wrapped word renders in brand gold serif-italic (matches the wordmark's gold accent) - ETA block designed for long values: wraps cleanly, never truncates, with 'Estimated downtime' label - Optional VITE_MAINTENANCE_LOGO override with wordmark fallback - document.title = 'RetailOps · Under Maintenance' - .env.example documents the exact usage (title pipes, ETA=ASAP, email) Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ntral-Pvt/RetailOps into arena/019fc604-retailops
…ailops # Conflicts: # backend/config/env.js # backend/database/db.js # backend/middleware/rateLimiter.js Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…lops Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
PEMS overhaul: backend reliability, automation engine, RBAC, maintenance mode
# Conflicts: # backend/database/db.js # backend/middleware/rateLimiter.js # backend/package-lock.json Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Reconcile: merge main's history into develop (enables develop → main release)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release — develop → main
Promotes everything merged into
develop(PR #17 + earlier) tomain:004_pems_v4, SQL transactions, event-store version locking, RBAC, live-data auth, cache namespacesVITE_MAINTENANCE_MODE/MAINTENANCE_MODEenv-gated screen + API 503docs/pems-backend-report.md,docs/pems-backend-plan.md