Skip to content

feat: form/workflow builder — full CRUD, interactive actions, CSV import, playbooks#6

Open
alikahwaji wants to merge 55 commits into
mainfrom
develop
Open

feat: form/workflow builder — full CRUD, interactive actions, CSV import, playbooks#6
alikahwaji wants to merge 55 commits into
mainfrom
develop

Conversation

@alikahwaji

Copy link
Copy Markdown
Contributor

Summary

  • P0 CRUD: Suppliers Add/Edit/Delete + CSV import, Risks Add/Edit, Components Add + CSV import
  • P1 Interactive Dashboard: DateRangePicker, clickable KPI cards → filtered pages, URL param filters
  • P2 Action Workflows: Alert acknowledge + notes, risk status workflow (Open→Resolved), owner assignment, comments, procurement approve/reject
  • P3 Custom Alert Rules: Severity/probability threshold sliders, 7-dimension risk scoring weight sliders
  • P4 Data Import: CSV upload wizard with drag-and-drop, column validation, preview for Suppliers & Components
  • P5 Incident Playbooks: 4 templates (Supplier Disruption, Cyber, Regulatory, Natural Disaster) with step tracking and progress bar
  • UI Library: 14 reusable components (Modal, SlideOver, ConfirmDialog, form fields) + useForm validation hook
  • i18n: 327 keys across 12 languages, severity badges + SVG text translated
  • Backend: 5 new API gateway proxy endpoints, risk CRUD on coordinator

58 files changed, 3,262 insertions, 272 deletions

Test plan

  • Navigate to /suppliers → click "Add Supplier" → fill form → submit → verify in table
  • Click edit icon on supplier → modify → save → verify update
  • Click delete icon → confirm → verify removal
  • Navigate to /risks → click "Add Risk" → fill form → submit
  • Click into a risk → verify owner assignment dropdown, status selector, comments panel, "Run Playbook" button
  • Navigate to /alerts → click "Acknowledge" on active alert
  • Navigate to /events → click "Create Event" → fill form → submit
  • Navigate to /components → click "Import CSV" → test drag-and-drop upload
  • Dashboard KPI cards are clickable → navigate to filtered pages
  • Settings page → drag alert threshold and scoring weight sliders
  • Test all above in dark mode + non-English language

🤖 Generated with Claude Code

alikahwaji and others added 30 commits April 13, 2026 20:34
- Add shared Pydantic models (libs/common/models.py): Risk, Recommendation,
  Organization, User, and all agent request/response types
- Add async SQLAlchemy database layer (libs/common/database.py) with
  connection pooling and FastAPI dependency injection
- Add ORM models (libs/common/db_models.py): 8 tables covering organizations,
  users, risk assessments, risks, recommendations, quality reviews, and audit logs
- Add Alembic migration setup with initial schema migration (001)
- Add seed data script (scripts/init-db.sql) with 3 orgs and 4 users
- Implement Coordinator Agent (services/coordinator/main.py) that orchestrates
  the full Planner -> Researcher -> Executor -> Reviewer pipeline with graceful
  degradation when agents are unavailable
- Fix API Gateway Pydantic v2 compatibility (dict -> model_dump)
- Fix docker-compose env var names to match service code expectations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add database schema, shared models, and Coordinator Agent
- Add shared LLM client (libs/common/llm.py) with OpenAI + Anthropic
  support, automatic fallback between providers, retry logic, and
  structured JSON output parsing
- Implement Researcher Agent (services/researcher/main.py) with Weaviate
  vector search, built-in supply chain knowledge base fallback, and
  LLM-powered finding synthesis
- Enhance Planner Agent with LLM-powered pharma context analysis,
  geographic risk assessment, and priority determination
- Enhance Executor Agent with LLM-generated context-aware recommendations
  and executive mitigation strategy narratives
- Enhance Reviewer Agent with LLM-powered semantic compliance checking
  that goes beyond keyword matching
- All agents gracefully fall back to rule-based logic when LLM is not
  configured, maintaining full functionality without API keys
- Add LLM configuration to docker-compose.dev.yml and .env.example
- Remove broken import of non-existent libs.cag.context_engine from planner

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add Researcher Agent (RAG) and LLM integration across all agents
- Scaffold Vite + React 18 + TypeScript + Tailwind CSS project
- Add 6 pages: Login, Dashboard, Risk List, Risk Detail, New Assessment,
  Recommendations
- Add auth system: AuthContext with JWT decode, ProtectedRoute, login/logout
- Add sidebar Layout with navigation using Heroicons
- Add shared components: SeverityBadge, SeverityChart (Recharts pie),
  Pagination, EntityForm, PriorityMatrix (scatter chart)
- Add data hooks: useRisks, useRisk, useMetrics
- Fix api.ts for Vite (process.env -> import.meta.env), add login method
- Add login endpoint to API Gateway (POST /api/v1/auth/login) with
  dev user credentials matching seed data
- Add Dockerfile.dev for frontend container
- Fix docker-compose env vars (REACT_APP_* -> VITE_*)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: build complete frontend dashboard with 6 pages and login flow
- Add shared security module (libs/common/security.py) with centralized
  CORS configuration, in-memory rate limiter, and environment-aware
  origin management
- Lock down CORS across all 6 services: replace allow_origins=["*"] with
  environment-configured origins (localhost in dev, specific domains in prod)
- Remove hardcoded JWT secret default, emit warning when JWT_SECRET_KEY
  is not set in environment
- Add rate limiting to API Gateway (100 req/min, 200 burst) with
  automatic bypass for health/metrics endpoints
- Add password validation to login endpoint using bcrypt verify_password
- Add /ready endpoint to API Gateway for Kubernetes readiness probes
- Add JWT_SECRET_KEY, ENVIRONMENT, CORS_ALLOWED_ORIGINS to .env.example
  and docker-compose.dev.yml
- Clean up unused CORSMiddleware imports across all services

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: security hardening — CORS lockdown, rate limiting, JWT enforcement
- Add missing Dockerfiles for api-gateway, planner, executor, reviewer
- Fix Dockerfiles for coordinator and researcher (use inline pip install
  instead of referencing out-of-context requirements.txt)
- Add CREATE TABLE statements to init-db.sql so PostgreSQL can seed data
  on first startup (tables must exist before INSERT)
- Fix API Gateway: move setup_monitoring() out of lifespan handler to
  avoid "Cannot add middleware after startup" error
- Fix login endpoint: use plaintext dev password check instead of invalid
  bcrypt hash placeholder

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add risks[] field to executor's RecommendationResponse and return
  identified risks alongside recommendations
- Update coordinator to pass through executor's risks and recommendations
  into the final RiskAssessmentResponse (was returning empty arrays)
- Fix planner entity handling: convert Pydantic Entity objects to dicts
  before calling .get() in analysis methods

Dashboard, Risk List, and Recommendations pages now populate with real
data from the 4-agent pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add GET /risks/{risk_id} to coordinator for individual risk lookup
- Add GET /recommendations/{risk_id} to coordinator for risk-specific
  recommendations
- Add GET /api/v1/risks/{risk_id} to API Gateway, routing to coordinator
- Fix recommendations endpoint to route through coordinator instead of
  executor (data lives in coordinator's in-memory store)

Risk Detail page now loads with full risk data and associated
recommendations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1 gap closure addressing 29 documented requirements:

Database (migration 002):
- Add suppliers table with risk_score, risk_tier, org multi-tenancy
- Add agent_runs + agent_steps tables for pipeline telemetry
- Add rag_collections, rag_documents, rag_chunks for RAG persistence
- Add alerts table with severity, status tracking, acknowledgment
- Seed 5 suppliers across 2 organizations

Backend:
- Add supplier CRUD endpoints (GET /suppliers, GET /suppliers/:id, POST, PUT)
- Add alerts endpoint (GET /alerts, POST /alerts/:id/acknowledge)
- Add risk history endpoint (GET /risks/history)
- Auto-generate alerts for high/critical risks during assessment pipeline
- Add real WebSocket events (risk_update, alert_triggered) on assessment
- Route all new endpoints through API Gateway with auth

Frontend:
- Add Suppliers page with risk score bars, tier badges, filtering
- Add Alerts page with status badges, severity filtering
- Add Suppliers and Alerts to sidebar navigation
- Add Supplier, Alert interfaces and API methods to api.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 gap closure:

Backend:
- Add 7-day disruption prediction endpoint (GET /predictions) with
  rule-based forecasting from risk landscape trends
- Add supply chain map endpoint (GET /supply-chain/map) returning
  nodes (orgs, suppliers, risks) and edges for graph visualization
- Add scenario simulation endpoint (POST /scenarios/simulate) with
  financial impact estimation and recovery timeline modeling
- Route all endpoints through API Gateway with auth

Frontend:
- Add Predictions page with disruption probability bar chart (Recharts)
  and per-category prediction cards
- Add Supply Chain Map page with node visualization, connection graph,
  and summary stats (orgs/suppliers/risks)
- Add both pages to sidebar navigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Authentication:
- Add TOTP MFA with RFC 6238 implementation (generate secret, verify
  codes with time-window tolerance, otpauth URI for authenticator apps)
- Add MFA enrollment endpoint (POST /auth/mfa/setup)
- Add MFA verification endpoint (POST /auth/mfa/verify)
- Login returns mfa_required=true when MFA is enabled for the user
- Add refresh token support (30-day expiry, POST /auth/refresh)

OAuth 2.0:
- Add OAuth authorization endpoint (GET /auth/oauth/authorize) with
  provider-specific URL generation (mock for dev, production-ready pattern)

Row-Level Security:
- Add migration 003 with RLS policies on all multi-tenant tables
  (suppliers, risk_assessments, risks, recommendations, alerts, agent_runs)
- Policies enforce org isolation via current_setting('app.current_org_id')
- Gracefully allows access when no org context is set (dev mode)

Service-to-Service Auth (Zero Trust):
- Add X-Service-Key header validation for inter-agent communication
- require_service_auth() dependency enforced in production environment
- SERVICE_API_KEY configurable via environment variable

Role Enforcement:
- Implement proper require_role() as FastAPI dependency with role checking
- Add require_any_role() for endpoints that just need authentication
- User extracted from JWT and attached to request.state

Database:
- Add mfa_secret, mfa_enabled, last_login_at columns to users table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Observability:
- Add OpenTelemetry tracing module (libs/common/tracing.py) with
  auto-instrumentation for FastAPI and httpx, OTLP gRPC exporter,
  graceful fallback when packages not installed
- Add Grafana provisioning: Prometheus datasource auto-config and
  SCIRM overview dashboard with 8 panels (request rate, P95 latency,
  error rate, agent success gauge, processing time, active connections,
  24h request/task counters)

Accessibility (WCAG 2.1 AA):
- Add enhanced focus-visible indicators (blue outline, 2px offset)
- Add skip-to-content navigation link
- Add ARIA landmarks (role="navigation", role="main", aria-label)
- Add minimum touch target sizing (44px per WCAG)
- Add prefers-reduced-motion media query support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7 new D3.js components with animations, tooltips, and interactivity:

1. DonutChart — animated arc transitions, hover explosion effect,
   center stat display, smooth entry animations
2. ScatterQuadrant — quadrant scatter plot with labeled zones
   (Quick Wins, Strategic, Low Priority, Questionable), animated
   point entry with back-ease, hover zoom, custom tooltips
3. AnimatedBars — horizontal animated bars with staggered entry,
   value labels, hover highlight effects
4. ForceGraph — force-directed network graph with physics simulation,
   drag-to-move nodes, zoom/pan, arrow markers, type-colored nodes
   (org=blue, supplier=green, risk=red), animated entry
5. RiskHeatmap — category x severity matrix with sequential color
   scale (YlOrRd), animated cell fill, hover highlight with border
6. GaugeChart — animated circular gauge with sweep transition,
   color-coded by value (green/yellow/orange/red), counter animation
7. Sparkline — mini inline trend chart with gradient area fill,
   animated line draw, end-point dot

Page updates:
- Dashboard: animated donut + risk heatmap side by side
- Supply Chain Map: interactive force-directed graph (replaces grid)
- Predictions: animated horizontal bars + gauge charts per category
- Recommendations: quadrant scatter with interactive tooltips
- New Assessment: gauge chart for confidence score in results

Infrastructure:
- Replace recharts with d3 ^7.9.0 + @types/d3 in package.json
- Fix docker-compose frontend to run npm install on start

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the generic force-directed graph with a purpose-built
supply chain flow visualization:

- 3-tier layout: Suppliers → Organization → Risks (left to right)
- Curved gradient links with thickness proportional to risk score
- Color-coded nodes: blue (suppliers), purple (org), red (risks)
- Risk tier coloring on supplier nodes (green/yellow/orange/red)
- Glow effect on high-risk nodes (risk_score > 60)
- Animated entry: staggered node pop-in + link fade-in
- Rich tooltips with risk score, tier, region, supplier type
- Link hover shows source → target relationship and risk score
- Self-explanatory legend with link thickness meaning

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

Infrastructure:
- Add nginx reverse proxy with TLS 1.3, security headers (HSTS, CSP,
  X-Frame-Options), rate limiting zones, WebSocket proxy, HTTP→HTTPS
  redirect, and self-signed cert generation script
- Add ELK Stack docker-compose overlay (Elasticsearch 8.11, Logstash
  with JSON pipeline, Kibana) — run with -f docker-compose.elk.yml
- Add k6 load test script targeting 100K concurrent users with ramp-up
  stages, custom metrics, and SLO thresholds (P95 < 500ms, errors < 1%)

Security:
- Add OAuth 2.0 module (libs/common/oauth.py) with Google and Azure AD
  provider configs, authorization URL generation, code exchange, and
  user info retrieval via OIDC
- Add PagerDuty Events API v2 integration (libs/common/alerting.py)
  with Slack webhook and generic webhook support — dispatch_alert()
  sends to all configured channels simultaneously

Frontend:
- Add react-i18next with 12 languages: English, Spanish, French,
  German, Portuguese, Chinese, Japanese, Korean, Arabic, Hindi,
  Italian, Dutch — all with full UI translation coverage
- Add language detection (localStorage + navigator) with fallback

Configuration:
- Add OAuth, alerting, and tracing env vars to .env.example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-Refresh (FR-001 completion):
- Add background asyncio task that re-assesses all known entities
  every 15 minutes (configurable via AUTO_REFRESH_INTERVAL_MINUTES)
- Collects unique entities from previous assessments and runs fresh
  pipeline automatically
- Enabled by default, configurable via AUTO_REFRESH_ENABLED env var
- Graceful error handling with 1-minute retry on failure

ERP Connectors (NFR-004 completion):
- Add abstract ERPAdapter base class with standard interface:
  get_suppliers, get_purchase_orders, get_inventory, get_shipments
- Implement SAPAdapter for SAP S/4HANA via OData v4 APIs
- Implement OracleAdapter for Oracle Fusion Cloud via REST APIs
- Implement DynamicsAdapter for Microsoft Dynamics 365 via Dataverse
  OData with Azure AD OAuth2 token acquisition
- All adapters include mock data for development (works without
  real ERP credentials)
- Add ERPManager for unified multi-ERP sync and health checking
- Add API endpoints: GET /erp/status, POST /erp/sync, GET /erp/suppliers

All 11 functional and non-functional requirements now have complete
code coverage. Zero partial, zero not-started.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- Add POST /api/v1/auth/signup endpoint with email, password, name
- Password validation (minimum 8 characters)
- Duplicate email check against existing and registered users
- Auto-assigns 'analyst' role to new signups
- Returns access_token + refresh_token immediately (auto-login)
- In-memory user store for dev (production would persist to DB)

Frontend:
- Add SignupPage with name, email, password, confirm password fields
- Client-side validation (password match, min length)
- Error display for server-side validation failures
- Auto-redirect to dashboard on successful signup
- Add /signup route to App.tsx
- Add 'Create one' link on LoginPage → /signup
- Add 'Sign in' link on SignupPage → /login
- Add signup() method to AuthContext and api.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Login endpoint now checks both dev users (DEV_PASSWORD) and
registered users (their signup password). Previously only dev
users could log in.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1.1 — Multi-Dimensional Risk Intelligence:
- Add migration 004 with risk_dimensions table and supplier composite
  score columns
- Create Risk Scorer microservice (services/risk-scorer/) scoring
  suppliers across 7 dimensions: ESG, Cyber, Financial, Geopolitical,
  Catastrophic, Operational, Regulatory
- Add risk_rubrics.py with dimension-specific scoring criteria,
  weights, high/low risk indicators, and LLM prompt generation
- LLM-enhanced scoring with rule-based fallback per dimension
- Create D3 RadarChart component with animated line draw, data points,
  hover tooltips, and dimension-colored markers
- Update Suppliers page: click any supplier to see 7-dimension risk
  profile in modal with radar chart + dimension breakdown
- Add /api/v1/risk-score and /api/v1/risk-dimensions endpoints
- Add risk-scorer to docker-compose (port 8006)

Phase 1.2 — Data Repository Layer:
- Create libs/common/repository.py with InMemoryStore providing
  unified async CRUD interface for tasks, risks, suppliers, alerts
- Abstraction layer ready for PostgreSQL migration (swap InMemoryStore
  for SQLAlchemy-backed implementation)
- Seed default suppliers via repository

Beats: Interos (i-Score across 7 dimensions), Everstream (multi-factor)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2.1 — Multi-Tier Supplier Graph:
- Add migration 005 with supplier_relationships, components,
  supplier_components tables and supplier hierarchy columns
- Create Discovery Agent (services/discovery/) for LLM-powered
  sub-tier supplier identification with knowledge base fallback
  (pre-built sub-tier data for all 5 seed suppliers)
- Add POST /discover-subtiers endpoint through coordinator + gateway
- Discovery service on port 8007

Phase 2.2 — Event-to-Impact Linking:
- Add risk_events and event_impacts tables in migration 005
- Create impact_propagation.py with BFS graph traversal engine
  that cascades disruption through supplier relationships with
  tier-based attenuation (60% per tier, stops at 10% threshold)
- POST /events creates event + auto-propagates impact + generates
  alerts for critical/high impacts
- GET /events lists events, GET /events/:id/impacts shows cascade
- New EventsPage with split-panel: event timeline (left) + impact
  analysis with financial estimates (right)
- Events added to sidebar navigation

Beats: Interos (Tier-N mapping), Exiger (event-to-impact linking),
       Everstream (event monitoring)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 3.1 — Real-Time Data Ingestion:
- Create Ingestion Service (port 8008) with collectors for news,
  weather, regulatory, and financial feeds
- 10 built-in intelligence documents covering semiconductors, EU
  regulations, hurricanes, FDA/DSCSA, raw materials, Red Sea shipping,
  EMA GMP, monsoon season, credit downgrades, and cyber breaches
- POST /intelligence/ingest triggers manual collection cycle
- GET /intelligence/feed with source filtering and time-based queries
- IntelligenceFeedPage with source filter pills and Refresh button
- Added to sidebar as 'Intel Feed' with newspaper icon

Phase 3.2 — Natural Language Chat:
- Create Chat Agent (port 8009) with intent classification engine
  routing queries to existing coordinator endpoints
- 8 intent handlers: risk_summary, supplier_info, high_risk,
  predictions, alerts, score_supplier, recommendations, events
- LLM fallback for general/free-form questions
- Floating ChatPanel component on every page — slide-out panel with
  message bubbles, typing indicator, auto-scroll
- POST /api/v1/chat endpoint through gateway

Beats: Resilinc (100M+ sources + agentic chat), Everstream (24/7
monitoring), Dataiku (NL query), Kinaxis (conversational planning)

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

Phase 4.1 — Digital Twin Simulation Engine:
- Create Simulator service (port 8010) with Monte Carlo engine
  running configurable N simulations (default 1000)
- Models supplier network with risk scores, revenue share, alternatives,
  lead times, and regional data
- Randomized parameters per iteration (normal distribution) with
  cascade probability modeling
- Returns P5/P50/P95/max financial impact + recovery day distributions
- Histogram data for D3 visualization
- Auto-generates mitigation recommendations per scenario
- SimulatorPage with visual scenario builder (checkbox suppliers,
  severity dropdown, duration slider) and results dashboard

Phase 4.2 — Autonomous Procurement Agent:
- Create Procurement service (port 8011) with 3 modes:
  advisory / semi_auto / auto
- Evaluates suppliers against risk threshold, identifies alternatives
  from built-in database (13 alternative suppliers across all 5 primaries)
- Selects best alternative by combined risk + cost optimization
- Auto-executes in auto mode when risk reduction > 20 points
- ProcurementPage with evaluate button, pending proposals, action history
- Migration 006 for procurement_actions table

Beats: Microsoft (digital twin), Kinaxis (scenario testing),
       GEP/Blue Yonder (autonomous procurement), C3 AI

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

Phase 5.1 — Component-Level Risk Tracking:
- Create Component Tracker service (port 8012) with 8 pharma components
  and 3 products (CardioSafe Tablet, ImmunoBoost Injection, DermaCare Patch)
- BOM hierarchy with parent-child relationships and criticality
- Impact analysis: which products break if a component is unavailable
- Migration 007 for component_bom table
- ComponentsPage with product cards, BOM detail table, component catalog
- API: /components, /products, /products/:id/bom, /components/:id/impact

Phase 5.2 — Industry Vertical Templates:
- Create libs/common/verticals/ with 5 industry modules:
  pharma, automotive, electronics, food_beverage, energy
- Each vertical: compliance rules, mandatory certifications, risk weights,
  risk thresholds, KPIs, recommendation templates
- get_vertical() dynamically loads config by Organization.industry

Phase 5.3 — DAG-Based Multi-Agent Orchestration:
- Create libs/common/orchestrator.py with AgentNode, DAGExecutor
- Agents run in parallel via asyncio.gather when dependencies are met
- BFS dependency resolution with deadlock detection
- get_execution_plan() previews parallel batch order
- Planner + Researcher run in parallel (no dependency)
- Executor waits for both, Reviewer waits for executor

All 5 competitive improvement phases complete. 11 microservices.

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

1. Dark Mode:
   - ThemeContext with localStorage persistence + system preference detection
   - Tailwind darkMode: 'class' with CSS overrides for cards, text, borders
   - Moon/sun toggle icon in sidebar header
   - Smooth transition between themes

2. Global Search (⌘K):
   - Searchable command palette with all pages + supplier names
   - Keyboard shortcut: Cmd+K to open, Escape to close
   - Fuzzy matching across labels and keywords
   - Navigate directly to any page from search

3. Grouped Sidebar Navigation:
   - 4 sections: Overview, Supply Chain, Intelligence, Operations
   - Section labels with uppercase tracking
   - Compact nav items (13px font, tighter spacing)
   - Reduces cognitive overload from 14 flat items

4. Breadcrumbs:
   - Auto-generated from route segments
   - Shows on all detail/sub-pages (hidden on top-level)
   - Home icon + chevron separators
   - Dark mode compatible

5. Notification Bell:
   - Real-time alert count badge (polls every 30s)
   - Dropdown with latest 5 alerts
   - Click to navigate to Alerts page
   - Red badge shows unread count (9+ cap)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply dark: Tailwind variants to every text-gray, bg-white, bg-gray,
border-gray, and hover:bg-gray class across all frontend files:
- 15 page files (Dashboard through Signup)
- 4 component files (Pagination, SeverityBadge, EntityForm, ChatPanel)
- MetricCard with dark icon backgrounds
- Removed global CSS overrides in favor of component-level dark: classes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
alikahwaji and others added 25 commits April 14, 2026 22:45
- Create shared theme.ts with getThemeColors() returning theme-aware
  color palette (text, textMuted, textLight, stroke, grid)
- Fix DonutChart: filter out zero-value items (fixes invisible slivers),
  use inline fill attrs instead of Tailwind fill-* classes
- Fix all 7 D3 components: AnimatedBars, ScatterQuadrant, RiskHeatmap,
  RadarChart, ForceGraph, SupplyChainFlow — replace fill-gray-* classes
  with colors.text/textMuted/textLight inline fill attributes
- Center "14" number and "Total Risks" label now white in dark mode
- Grid lines, axis labels, legends all theme-aware

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
D3 charts call getThemeColors() once at mount inside useEffect.
When user toggles dark/light mode, the charts don't re-render
because their data dependencies haven't changed. Fix by adding
key={theme} prop which forces React to unmount/remount the
component, triggering a fresh D3 render with correct colors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problems fixed:
- 28 individual risk nodes stacked on top of each other → now
  aggregated by category (regulatory, quality, logistics, etc.)
  showing count inside each bubble
- Duplicate organization nodes → deduplicated with Map
- Truncated overlapping labels → clean category names with counts
- Risk bubble size scales with count (min 18px, max 36px)
- Link thickness from org→risk scales with risk count
- Severity color on aggregated bubbles shows worst severity
- Category label + severity label below each bubble
- Proper spacing with readable text at all sizes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Calculate minimum spacing per node (100px for circle + name + sublabel)
- Expand SVG height dynamically if content exceeds container
- Increase default chart height from 520 to 620px
- Labels now have room below each circle without overlapping next node

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Labels placed at x=-(radius+10) with text-anchor 'end' so they sit
to the left of each risk bubble. Severity shown below category name.
Risk column shifted right to 92% to make room for labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create 3 layers: linkLayer (background), nodeLayer (middle),
labelLayer (foreground). Links can no longer obscure node labels
because nodes and their labels are in a higher SVG group.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Labels below bubbles work now because 130px spacing gives 70px gap
between bottom of bubble and top of next. Reduced max radius from
36 to 30px. Combined severity + count in one label line.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all supplier, org, and risk category labels to labelLayer
which renders ABOVE nodeLayer. This ensures no circle from the
next node can cover a label from the previous node. Also shift
risk column to 80% and suppliers to 10% for balanced layout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Should-Have (6-10):
6. Cross-page contextual actions — "Simulate" and "Alternatives"
   links on supplier rows and risk cards
7. Auto-refresh dashboard every 30 seconds via useAutoRefresh hook,
   pauses when tab is not visible
8. Onboarding wizard — 3-step first-login flow: select industry,
   quick tour, get started. Stored in localStorage, skip option
9. Loading skeletons — SkeletonCard, SkeletonTable, SkeletonChart
   with shimmer animation replacing "Loading..." text
10. Toast notifications — ToastProvider with auto-dismiss (5s),
    slide-in animation, 4 types (info/success/warning/error).
    Dashboard toasts when new risks are detected

Nice-to-Have (11-13):
11. Role-based dashboard — admin sees quick action panel, viewer
    hides action buttons, analyst sees risk-focused layout
12. Keyboard shortcuts — D=dashboard, R=risks, S=suppliers,
    A=alerts, N=new assessment, ?=help. Disabled in inputs
13. Admin quick actions panel replaces drag-and-drop widget
    customization (more practical for MVP)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scrollbar Fix:
- Custom thin scrollbars (6px) that appear only on hover
- Transparent by default, gray-300 on hover — unobtrusive
- Works in both webkit and Firefox

User Settings Page (/settings):
- Profile section (name, email, roles)
- Appearance toggle (dark mode switch)
- Language selector (12 languages, grid layout)
- Notification preferences (email, Slack, critical-only toggles)
- Change password form with validation
- Data export section (CSV/JSON downloads)

Password Reset:
- /forgot-password page with email form + success state
- POST /api/v1/auth/forgot-password endpoint
- POST /api/v1/auth/reset-password endpoint (token-based)
- POST /api/v1/auth/change-password endpoint (authenticated)
- "Forgot password?" link on login page

PDF/Excel Report Export:
- GET /api/v1/export/risks?format=csv — CSV download
- GET /api/v1/export/suppliers?format=csv — CSV download
- GET /api/v1/export/report — full JSON report with all data
- Export buttons in Settings page

Email Notifications:
- send_email_alert() in alerting.py via SMTP
- HTML formatted emails with severity color header
- "View in SCIRM" button linking to alerts page
- Added to dispatch_alert() alongside PagerDuty/Slack/webhook
- SMTP config in .env.example

Navigation:
- "Settings" link added to sidebar user section
- "Forgot password?" link on login page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: global CSS rule 'button { min-height: 2.75rem }' for
WCAG touch targets was inflating toggle button height to 44px,
distorting the 24px-tall toggle track and causing the thumb to
overflow.

Fix:
- Create proper Toggle component with role='switch', aria-checked,
  fixed h-6 w-11 dimensions, and inline min-height:unset override
- Exempt button[role='switch'] from global min-height rule in CSS
- Replace all inline toggle buttons in SettingsPage with Toggle
  component (appearance toggle + 3 notification toggles)
- Toggle has proper transition animation, focus ring, dark mode colors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Both buttons now on same row with equal flex widths
- Added | separator between them
- Added hover backgrounds (gray-800) for clear interactivity
- Sign out turns red on hover for visual distinction
- Override min-height for these footer links
- Increased font size from 10px to xs (12px) for readability
- Added margin below email for spacing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: global CSS 'a { min-height: 2.75rem }' was inflating
the NavLink and button to 44px each, causing them to stack vertically
instead of sitting on the same row.

Fix: add [data-compact] attribute exemption to the global min-height
rule. Apply data-compact to Settings link and Sign out button.
Both now render as compact inline elements on the same row with
a | separator, proper hover states, and equal flex widths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GuestRoute:
- New component that redirects authenticated users away from
  /login, /signup, /forgot-password to /dashboard
- Prevents logged-in users from seeing auth pages

ProtectedRoute:
- Now saves the attempted URL in location.state
- After login, redirects back to where the user was going

Login Rate Limiting:
- Frontend tracks failed attempts (max 5)
- After 5 failures, locks login for 60 seconds with countdown
- Shows remaining attempts on each failure

Token Expiry:
- decodeToken() now checks JWT exp claim against current time
- Expired tokens are cleared from localStorage on app load
- Prevents stale sessions from persisting

404 Page:
- NotFoundPage with links to Dashboard and Sign In
- Catches all unmatched routes via Route path='*'

Password Strength:
- Visual 4-bar strength indicator on signup
- Checks: length, uppercase, numbers, special chars
- Labels: Too short / Weak / Medium / Strong

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: i18n/index.ts was never imported so i18next was never
initialized. Settings page stored language in localStorage but
never called i18n.changeLanguage(). Pages used hardcoded English
text instead of t() translation calls.

Fix:
- Import './i18n' in main.tsx to initialize i18next on app load
- Settings page now calls i18n.changeLanguage(code) on selection
- Sidebar nav items use t(tKey, fallback) for all 13 nav labels
- Dashboard uses t() for title, subtitle, metric labels, chart
  headings, and section titles
- Added missing nav keys to en.json (components, events, intelFeed,
  simulator, procurement)
- Added matching nav keys to es.json (Componentes, Eventos de
  Riesgo, Inteligencia, Simulador, Adquisiciones)

When user selects Spanish, sidebar now shows: Panel, Riesgos,
Proveedores, Componentes, Mapa de Red, Predicciones, etc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 of i18n plan: migrated every page and component to use
react-i18next useTranslation() hook with t('key', 'fallback').

170+ translation keys across 17 namespaces now externalized:
- auth (28 keys): login, signup, forgot password, validation
- dashboard (16 keys): metrics, charts, sections
- risks (20 keys): list, detail, table headers
- assessment (18 keys): form labels, results
- suppliers (16 keys): table, filters, radar modal
- alerts (7 keys): list, status filters
- predictions (7 keys): chart, cards
- events (10 keys): timeline, impact panel
- intelligence (7 keys): feed, sources
- simulator (14 keys): scenario builder, results
- procurement (10 keys): evaluate, actions
- components (14 keys): BOM, catalog
- settings (24 keys): profile, toggles, password, export
- chat (7 keys): panel, greeting
- onboarding (16 keys): wizard steps
- common (18 keys): loading, pagination, notifications
- supplyChain (5 keys): map page
- recommendations (9 keys): matrix, stats

All t() calls include English fallback for graceful degradation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 3: Professional translations for all 11 non-English languages
with 292 keys each covering all 19 namespaces. All 23 page and
component files now use t() with proper fallbacks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ort, playbooks

Complete implementation of the Form/Workflow Builder system:

P0 - CRUD Operations:
  - Suppliers: Add/Edit/Delete with modal forms, CSV bulk import
  - Risks: Add/Edit with severity, probability, impact, category, entities
  - Components: Add with form + CSV bulk import
  - 14 reusable UI components (Modal, SlideOver, ConfirmDialog, FormField,
    TextInput, Select, TextArea, NumberInput, DatePicker, MultiSelect,
    TagInput, Slider, DateRangePicker + barrel export)
  - useForm hook with built-in validation (required, min/max, pattern, email)

P1 - Interactive Dashboard:
  - DateRangePicker on dashboard for historical filtering
  - KPI MetricCards click-through to filtered pages (/risks?severity=critical)
  - RiskListPage reads ?severity= URL params to pre-populate filter

P2 - Action Workflows:
  - Alert acknowledge button + notes SlideOver with localStorage persistence
  - Risk status workflow (Open → Investigating → Mitigating → Resolved → Accepted)
  - Risk owner assignment dropdown (5 team members)
  - Comments panel on risk detail page (localStorage-backed)
  - Procurement approve/reject buttons on proposed actions

P3 - Custom Alert Rules:
  - Severity score threshold slider (0-100%)
  - Probability threshold slider (0-100%)
  - 7-dimension risk scoring weight sliders with total percentage display

P4 - Data Import/Export:
  - CSV upload wizard with drag-and-drop, column validation, preview table
  - Bulk import for both Suppliers and Components pages

P5 - Incident Playbooks:
  - 4 playbook templates (Supplier Disruption, Cyber Incident, Regulatory
    Change, Natural Disaster)
  - Step-by-step checklist with progress bar, assignees, due times
  - "Run Playbook" button on Risk Detail page

Backend:
  - 5 new API gateway proxy endpoints (POST/PUT risks, POST/PUT suppliers,
    POST alerts acknowledge)
  - Risk CRUD endpoints on coordinator (POST /risks, PUT /risks/{id})
  - 6 new frontend API mutation methods

i18n: 327 keys across 12 languages, severity badges translated, supply
chain flow SVG text translated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…v-based credentials

- Expanded .gitignore: added Python (__pycache__, venv, .pytest_cache),
  IDE (.idea, .vscode), OS (.DS_Store), .claude/, Kubernetes secrets,
  deployment local overrides, frontend build artifacts
- Untracked infra/k8s/staging/secrets.yml → replaced with secrets.example.yml
- deploy-staging.sh: replaced hardcoded staging_password and Grafana admin
  password with Kubernetes secretKeyRef references
- api-gateway: DEV_PASSWORD now loaded from env var with fallback
- LoginPage: dev credentials only shown in development mode (import.meta.env.DEV)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…arning, clean up scripts

- Removed hardcoded dev password (scirm-dev-2026) from all 12 locale JSON
  files — replaced with generic "Dev mode" message
- database.py: DATABASE_URL now emits a warning if not set via env var
  instead of silently using dev default
- Removed one-time translation helper scripts (update-translations*.js)
  from tracked files — these are build-time utilities, not production code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant