Skip to content

Architecture

Ed Mozley edited this page May 17, 2026 · 10 revisions

Architecture

FreeITSM is a classic LAMP-style web application: PHP server-side with vanilla JS/HTML/CSS on the client. No frameworks, no build step. All 18 modules share a common chrome (waffle menu, header, user account dropdown) but each module is self-contained under its own folder.

Technology Stack

Component Technology
Backend PHP 7.4–8.4
Database MySQL 8.0+ via PDO MySQL
Frontend Vanilla JavaScript, HTML5, CSS3
Rich text editing TinyMCE 6+
Email integration Microsoft Graph API + Gmail API (OAuth 2.0)
Encryption at rest AES-256-GCM for sensitive values
AI features Anthropic Claude API (per-feature keys) + OpenAI embeddings (Knowledge)
Web server Apache (WAMP/XAMPP/LAMP) or any PHP server

Directory Layout

freeitsm/
β”œβ”€β”€ config.php                  # References external db_config.php
β”œβ”€β”€ index.php                   # Module selection grid (landing page)
β”œβ”€β”€ login.php                   # Analyst login
β”œβ”€β”€ api/                        # ~140 REST endpoints, one folder per module
β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ css/                    # Shared stylesheets
β”‚   β”œβ”€β”€ js/                     # Shared scripts + TinyMCE library
β”‚   └── images/
β”œβ”€β”€ includes/                   # Shared PHP components
β”‚   β”œβ”€β”€ functions.php           # connectToDatabase() + analyst module helpers
β”‚   β”œβ”€β”€ waffle-menu.php         # Cross-module nav + user account menu
β”‚   β”œβ”€β”€ encryption.php          # AES-256-GCM helpers
β”‚   β”œβ”€β”€ totp.php                # Pure-PHP TOTP / HOTP (RFC 6238 / 4226)
β”‚   └── module-colors.php       # Module colour definitions
β”œβ”€β”€ database/
β”‚   └── freeitsm.sql            # Schema bootstrap
β”œβ”€β”€ docs/                       # Design docs (e.g. cmdb.md)
└── <module-folders>/           # tickets/, contracts/, cmdb/, ...

Each module folder typically contains:

  • index.php β€” landing page
  • settings/index.php β€” module config
  • help.php β€” in-app guided help page (scroll-spy sidebar, sectioned content)
  • includes/header.php β€” module's header bar with its colour gradient and nav tabs

Shared Components

Waffle Menu (includes/waffle-menu.php)

A Microsoft 365-style app launcher in the header of every module page. Each module is registered with a name, path, icon SVG, and colour gradient. Respects $_SESSION['allowed_modules'] to filter visible modules per analyst.

Also contains the user account menu β€” an initials avatar circle in the top-right of every page. Clicking opens a dropdown with:

  • Change Password (validates current, min 8 chars)
  • Multi-Factor Authentication (TOTP setup/disable with QR code)
  • Logout (with confirmation)

To add a new module, add an entry to the $modules array and matching CSS.

TOTP (includes/totp.php)

Pure-PHP implementation of RFC 6238 (TOTP) and RFC 4226 (HOTP). No external dependencies β€” uses PHP's built-in hash_hmac() and random_bytes().

  • Secret generation: 20 random bytes β†’ Base32 (32-char string)
  • Code generation: HMAC-SHA1, 30-second time step, dynamic truncation β†’ 6-digit code
  • Verification: Β±1 time window (90-second tolerance), hash_equals() for timing-safe compare
  • URI format: otpauth://totp/FreeITSM:{username}?secret={base32}&issuer=FreeITSM

Secrets are encrypted at rest with AES-256-GCM before being stored in analysts.totp_secret.

Encryption (includes/encryption.php)

AES-256-GCM authenticated encryption for sensitive database values.

  • Key file: C:\wamp64\encryption_keys\sdtickets.key (outside web root)
  • Format: ENC: + base64(IV + auth tag + ciphertext)
  • Migration-safe: Values without ENC: prefix pass through unchanged
$encrypted = encryptValue($plaintext);
$plaintext = decryptValue($encrypted);
$mailbox = decryptMailboxRow($mailbox);

Encrypted columns include:

  • system_settings: vcenter_*, knowledge_ai_api_key, knowledge_openai_api_key, intune_*
  • target_mailboxes: azure_tenant_id, azure_client_id, azure_client_secret, oauth_redirect_uri, imap_server, target_mailbox
  • analysts.totp_secret

A subset of "true secrets" listed in MASKED_SETTING_KEYS are also masked to ****<last4> in API responses, with a save-time convention that blank or asterisk-prefixed submissions mean "leave unchanged" so the user can save the form without re-typing.

Module Header Pattern

Each module's includes/header.php:

  1. Checks session auth (redirects to login if missing)
  2. Sets $current_module for waffle-menu highlighting
  3. Renders the header bar with the module's colour gradient
  4. Includes the waffle button, module nav tabs, and user account avatar

Toast Notifications (assets/js/toast.js)

Global notification system. Four types: success (green), error (red), warning (amber), info (blue). 9 configurable screen positions via visual grid picker in System Settings β†’ General. Position persisted per-browser in localStorage. Slide-in animations, auto-dismiss after 4s, manual close button.

i18n (includes/i18n.php, assets/js/i18n.js, lang/)

Native multi-language support with a t('namespace.path.to.key') call pattern in both PHP and JavaScript. The first dot-separated segment of the key maps to a file (lang/<locale>/<namespace>.php); everything after walks a nested PHP array inside that file.

return [
    'toolbar' => [
        'process'  => 'Prozess',
        'decision' => 'Entscheidung',
    ],
];

Fallback is per key, not per file. If lang/de/tickets.php has 80% of keys translated, you get 80% in German and the missing 20% in English. Last-resort behaviour returns the key itself so unfilled strings are visible during development.

Locale resolution chain: logged-in analyst's interface_language user preference β†’ browser Accept-Language header (with primary-subtag matching β€” pt resolves to pt-BR) β†’ 'en' default. Selectable in System β†’ Preferences; on change, persists to user_preferences and reloads the page.

JS bridge: each page declares the namespaces it needs ($translationNamespaces = ['common', 'process-mapper']) and PHP renders window.translations with English fallback already merged into the active locale per key. The JS t() helper does a flat dotted walk β€” no fallback logic on the client.

Supported locales (20 as of May 2026): en, af, fr, de, es, pt-BR, nl, it, pl, ru, id, hi, bn, ta, te, mr, kn, ml, gu, pa. BCP 47 codes match the HTML lang attribute. Spans Europe (en/fr/de/es/pt-BR/nl/it/pl/ru), Africa (af β€” Afrikaans, South Africa), South Asia (the nine Indian languages), and Southeast Asia (id β€” Bahasa Indonesia). Adding a new language is a 2-step code change: add to I18n::SUPPORTED_LOCALES (with native-script display name), and drop .php translation files into lang/<code>/. The System β†’ Preferences dropdown picks the new locale up automatically.

Pilot module: Process Mapper is fully translated end-to-end across all 20 locales. Other modules will follow in phased sweeps β€” the infrastructure is the hard part and it's done.

Database Conventions

  • MySQL 8.0+ with AUTO_INCREMENT for primary keys
  • $conn->lastInsertId() to retrieve new IDs after INSERT
  • Foreign keys with cascading where ownership is real (e.g. cmdb_objects.parent_id cascade-deletes descendants)
  • Soft delete via is_active flags rather than physical deletion for user-facing records
  • Datetime columns: created_datetime, last_modified_datetime, etc. (PHP-side defaults)

API Pattern

All endpoints live under api/<module>/ and return JSON. Every endpoint starts with:

session_start();
require_once '../../config.php';
require_once '../../includes/functions.php';

header('Content-Type: application/json');

if (!isset($_SESSION['analyst_id'])) {
    echo json_encode(['success' => false, 'error' => 'Not authenticated']);
    exit;
}

See API Reference for a per-module endpoint summary.

AI Integration Pattern

Several modules integrate Anthropic Claude with per-feature API keys (separate from each other for granular billing visibility on the Anthropic dashboard):

Feature Settings location
Knowledge AI chat Knowledge β†’ Settings β†’ AI
Reply Cleanup Tickets β†’ Settings β†’ Reply Cleanup
RFP Builder Contracts β†’ Settings β†’ RFP AI
Form generation Reuses RFP AI key
CMDB AI summary + Suggest Properties CMDB β†’ Settings β†’ AI Integration

All keys are encrypted at rest. Most AI features stream output via SSE (claude.ai-style live tokens) for long-running calls.

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally