
RVNL Bilingual CMS · Rail Vikas Nigam Limited
A ground-up rebuild of the public website and content operations for Rail Vikas Nigam Limited, an Indian railway PSU. Every piece of content is fully bilingual (English / हिन्दी) and moves through a governed maker-checker workflow before it can go live — with role-based access, append-only audit trails, and a separate vigilance / grievance case system for citizen complaints and formal investigations. Built on Node.js + Express + Sequelize + MySQL with a React (Vite) frontend.
Bilingual content workflow Maker-checker · Per-language state machine
A publishing pipeline where authors, moderators, and approvers each hold a distinct role, and English and Hindi advance independently through the same state machine.
- Modelled a parent + per-language translation schema (e.g.
articles+article_translations) so each language carries its own workflow state — an English article can be published while its Hindi translation is still in approval. - Built a maker-checker state machine — draft → in moderation → in approval → approved → published, plus request-changes, reject, schedule, unpublish, and archive — with every transition recorded in a
workflow_transitionstable. - Supported scheduled publishing and resubmit loops, tracking each review cycle by
request_idand a per-item round counter so reviewers see the full back-and-forth history. - Integrated a machine-translation helper (Azure translator) to seed EN ↔ HI drafts, keeping a human approver in the loop before anything publishes.
Access control & audit RBAC · Section scoping · Append-only history
Fine-grained, section-scoped permissions backed by a tamper-evident record of who changed what, when, and why.
- Designed a slug-based RBAC system (
roles,permissions,role_permissions) with roles assigned globally and per section / subsection — so a tenders moderator and a careers moderator carry different reach. - Kept a field-level audit log storing
old_data/new_dataJSON snapshots on every change, plus an append-only content-history ledger that preserves actor label, role, and designation even after a user is deleted. - Secured auth with JWT access + refresh tokens, bcrypt password hashing, and token-version invalidation on logout / password change to kill stale sessions.
Vigilance & grievance system Public complaints · Case tracking
A separate governance surface for citizen grievances and formal vigilance investigations, with its own entry points, roles, and case log.
- Built two public streams — grievance (citizen complaints) and vigilance (formal investigations) — each with reference numbers, source taxonomy, assignee tracking, and a per-case action log (
complaint_logs). - Added dedicated staff shells for CVO, vigilance-author, and verification-officer roles, plus DPDP data-processing consent capture on public forms.
- Hardened public forms with CAPTCHA challenges, per-route rate limiting, and strict complaint-attachment validation (PDF/PNG/JPEG, size-capped, rejected loudly rather than dropped silently).
Platform hardening Validation · Security headers · Uploads
- Zod-validated request bodies on every write endpoint with structured
422field-error responses, plus SQL-injection-prevention middleware and request-size caps. - A media library (
media_assets) with sanitized filenames, per-asset metadata, and soft deletes so nothing referenced by live content is ever hard-lost. - Locked down the surface with CSP, HSTS, X-Frame-Options, Referrer-Policy, a non-wildcard CORS allowlist, and tiered rate limits (auth vs API vs public forms).
- Extended the CMS to RTI hubs, CSR initiatives, annual reports / investor KPIs, tenders, careers, and announcements — all sharing the same bilingual workflow and audit spine.