Executive summary
This case study documents a private enterprise operations portal developed from a help-desk foundation and expanded into a modular internal platform.
The system began with HESK-based support workflows. Over time, the organization needed the same authenticated environment to handle additional operational domains: asset inventory, maintenance requests, marketing work, vehicle and travel scheduling, service orders, dashboards, and integrations with internal infrastructure services.
A complete rewrite would have delayed useful improvements and increased migration risk. The chosen strategy was incremental modernization: preserve the proven ticketing core, create explicit module boundaries, centralize shared concerns, and introduce APIs, migrations, automated deployment, and observability where they produced concrete operational value.
The source code, company identity, real addresses, user information, credentials, database names, and topology are intentionally excluded. The architecture and engineering decisions are described at a level that remains technically useful without exposing the operating environment.
Context
The portal supports workflows owned by different departments and used by people with different permissions. Some areas are broadly accessible to authenticated users, while others are limited to specific roles or trusted network locations.
The platform also combines different execution models:
- PHP pages served through Apache;
- HESK sessions and administration conventions;
- JavaScript-enhanced interfaces;
- multiple MySQL databases and schemas;
- Python services for APIs, collectors, and operational integrations;
- persistent attachments and local configuration that must survive deployments;
- scheduled jobs and external service calls;
- a self-hosted deployment runner on the production environment.
The result is not a single isolated application. It is an operational surface connecting people, databases, background services, infrastructure evidence, and business processes.
Problem
As new requirements were added independently, the main risk was fragmentation.
Without a shared architecture, each workflow could have become another disconnected application with its own login, visual language, deployment procedure, permissions, reporting logic, and operational documentation. That would increase support effort and make cross-module improvements harder.
The portal needed to provide:
- one recognizable entry point;
- reusable authentication and authorization behavior;
- clear boundaries between modules;
- safe evolution of more than one database;
- controlled access from different network contexts;
- repeatable deployment and rollback;
- integrations without exposing database credentials to browsers;
- dashboards without repeatedly executing expensive aggregation queries;
- logs and health evidence sufficient for troubleshooting.
Constraints
The implementation had to work within several practical constraints.
Existing production behavior could not be discarded
The ticketing foundation already contained operational history, attachments, users, categories, permissions, and department-specific processes. Replacing it all at once would create more risk than value.
Modules evolved at different speeds
Support, assets, maintenance, marketing, scheduling, and reporting do not share the same release cycle. The architecture had to permit one area to change without requiring a redesign of every other area.
Persistence was not uniform
Some modules extended HESK data. Others used separate schemas or databases. Attachments, generated files, configuration, and cached outputs also had different lifecycle requirements.
Production deployment had to minimize interruption
The PHP layer could usually be updated without restarting Apache. Python services required controlled restarts. Persistent directories could not be replaced blindly by a source checkout.
Internal did not mean unrestricted
Some portal areas could be exposed through more than one network path, but sensitive modules still required tighter server-side controls. Access decisions could not depend only on hidden navigation links.
Sanitized architecture
The following diagram intentionally omits real hosts, addresses, database names, credentials, and network boundaries.
The architecture treats the PHP portal as the interaction layer, not as the only execution environment. Background collection and integration tasks are delegated to Python services where a long-running process or API boundary is more appropriate.
Modules
The public description groups the private modules into functional categories rather than exposing internal names.
Support and request management
The original ticketing workflow remains the operational foundation. Categories, assignment, status, history, attachments, and user communication are retained while the surrounding portal provides a broader navigation and integration layer.
Asset management
The asset module models computers, components, users or responsible parties, departments, monitors, printers, and compatibility relationships. It adds structured inventory behavior without forcing the ticketing tables to become a complete asset-management schema.
Departmental service workflows
Dedicated modules support areas such as maintenance, marketing, general services, and service orders. Each module applies its own required fields and permissions while reusing the shared application shell.
Scheduling and reservations
Reservation and travel-related workflows introduce date-based validation, availability, and operational planning. These processes require different rules from ticket management but benefit from the same authenticated portal.
Dashboards and reporting
Operational dashboards consolidate ticket statistics, departmental workload, backup state, remote-access events, and other infrastructure evidence. They are designed to summarize source systems rather than become the authoritative source for those systems.
Authentication and authorization
The portal reuses established HESK authentication and session behavior where appropriate, then adds explicit permission checks for custom modules and actions.
Authorization is applied at multiple levels:
- whether a module appears in navigation;
- whether its route can be accessed directly;
- whether the current administrator or user has the required capability;
- whether a create, update, delete, export, or administrative action is permitted;
- whether the request originates from an approved network context when the module requires it.
Network-aware exposure is a secondary control, not a replacement for identity and permission checks. A hidden menu item or an internal IP address alone is not treated as authorization.
Multi-database strategy
The platform does not force every operational domain into one database.
This decision reflects the way the system evolved: some modules extend the help-desk data model, while others own distinct entities and release cycles. A shared bootstrap and configuration layer resolves the appropriate connection for each module.
The main principles are:
- a module should own the tables it changes;
- cross-module reads should be explicit;
- business transactions should avoid depending on distributed writes across databases;
- reporting may aggregate from multiple sources, but the source systems remain authoritative;
- credentials and environment-specific connection values remain outside the public repository and outside browser-delivered code.
The tradeoff is additional operational discipline. Schema versions, backup coverage, deployment order, and rollback procedures must account for more than one persistence boundary.
Migrations and rollback
Database changes are versioned alongside the module that requires them. Production changes are not expected to be applied through undocumented manual edits.
The deployment process distinguishes three concerns:
- application files that may be replaced from version control;
- persistent files that must be preserved;
- schema changes that require an explicit migration step.
For HESK upgrades, the process also separates the vendor updater from custom structural changes. The target schema is validated after the official upgrade, and only the required structural delta is applied to custom tables or fields.
Rollback is planned before deployment. Depending on the change, it may include:
- redeploying the previous application revision;
- restoring preserved configuration or generated assets;
- reversing a migration when a safe down operation exists;
- restoring a database backup when reversal would be ambiguous or destructive;
- restarting the affected Python service without restarting unrelated web components.
Not every database change is safely reversible. The runbook therefore treats backup and restore capability as part of migration design rather than as an afterthought.
Integrations and APIs
Python and FastAPI provide a boundary for tasks that should not be implemented as synchronous PHP page logic.
Examples include:
- collecting or normalizing operational events;
- exposing internal metrics to dashboards;
- reading generated backup or inventory evidence;
- receiving authenticated events from infrastructure systems;
- providing stable data contracts to multiple portal views;
- performing scheduled aggregation outside an interactive request.
These services use narrow endpoints and dedicated authentication mechanisms. They do not expose arbitrary database access or client-selected filesystem paths.
The portal consumes the results and formats them for users, while each integration remains responsible for its own collection and validation logic.
Deployment model
Changes are delivered through GitHub Actions to a self-hosted runner in the production environment.
The deployment workflow is intentionally selective:
- source-controlled application files are updated from the approved branch;
- persistent attachments and local configuration are preserved;
- dependency handling is performed only where required;
- database migrations are executed as explicit deployment steps;
- the Python backend is restarted in a controlled manner;
- Apache is left running when the PHP update does not require a restart;
- deployment logs provide evidence of the revision and operations applied.
This replaced an error-prone model based on editing production files directly and manually remembering which services needed attention.
Observability
The platform records evidence at several layers:
- PHP and web-server errors;
- Python service logs;
- integration-specific logs;
- deployment output;
- task and service status;
- generated operational reports;
- dashboard data freshness;
- health endpoints for supporting services.
Expensive reporting queries can be isolated behind cached or precomputed outputs. The cache is treated as disposable: it can be regenerated from authoritative sources and is not used as the only record of an operational event.
This distinction prevents a dashboard optimization from becoming an accidental data store.
Security decisions
The system applies defense in depth within the limits of an incremental modernization project.
Key decisions include:
- reusing authenticated sessions instead of creating parallel identity silos;
- enforcing permissions on routes and actions, not only in navigation;
- limiting selected modules by network context in addition to role checks;
- storing secrets and production-specific configuration outside version control;
- separating browser-facing PHP from service credentials and collectors;
- protecting persistent files during deployment;
- restricting integrations to explicit contracts;
- retaining logs without writing credentials or tokens into them;
- sanitizing screenshots, exports, and documentation before external publication;
- keeping the private source and real topology unpublished.
The system is internal, but internal traffic and authenticated users are not assumed to be automatically authorized for every operation.
Results
The project produced qualitative operational improvements without requiring a disruptive rewrite.
A single operational entry point
Users can reach multiple workflows through a consistent portal instead of learning unrelated applications and addresses.
Reusable controls
Authentication, permissions, navigation, shared assets, configuration loading, logging conventions, and deployment behavior are reused across modules.
Independent evolution
New modules can be added or changed without forcing every existing workflow into the same schema or release cycle.
Better deployment discipline
Version-controlled delivery, explicit migrations, preserved runtime data, and service-specific restart behavior reduce dependence on manual production edits.
More accessible operational evidence
Dashboards and APIs make logs, statistics, backup state, and infrastructure events easier to review while preserving the authority of their source systems.
No performance percentage, cost reduction, ticket-volume improvement, or availability figure is claimed here because those measurements have not been prepared for public release.
Lessons learned
Incremental modernization can be the safer architecture
A rewrite is not automatically cleaner when the existing system contains years of operational behavior. Clear boundaries and controlled replacement can deliver value earlier while reducing migration risk.
Shared infrastructure needs explicit ownership
A common portal shell is useful, but each module still needs ownership of its schema, permissions, integrations, and rollback behavior.
Deployment and database design are connected
A schema change is not complete until its deployment order, compatibility window, backup, and recovery path are defined.
Internal systems still need trust boundaries
Network location, authenticated identity, module permissions, and service credentials answer different security questions. None of them should silently substitute for the others.
Observability must identify the authoritative source
Dashboards and caches improve access to information, but they should clearly distinguish fresh source data from derived or delayed summaries.
Limitations
The system still carries constraints inherited from its history.
- Some modules follow HESK conventions that were not designed for a broader application platform.
- Multiple databases increase migration and backup coordination.
- The production stack remains coupled to a Windows-hosted Apache/PHP environment and a self-hosted deployment runner.
- Automated tests do not yet cover every module and integration path.
- Some reporting data may be intentionally delayed by caching or scheduled aggregation.
- The portal is a modular platform, not a fully isolated microservice architecture.
These limitations are documented because hiding them would make the case study less useful and the operational model less safe.
Next steps
The long-term direction is continued separation of concerns rather than a single large rewrite.
Priorities include:
- expanding automated tests around permissions, migrations, and API contracts;
- standardizing module-level health and audit events;
- validating schema drift automatically before deployment;
- improving rollback automation and recovery exercises;
- further isolating long-running services from the web frontend;
- centralizing observability without centralizing every operational database;
- continuing to replace legacy coupling when a module has a clear migration path.
Confidentiality statement
This case study intentionally uses a generic identity and sanitized architecture. It contains no restricted HESK customization, proprietary source code, credentials, real hostnames, internal addresses, user records, database names, sensitive metrics, or production topology.