Skip to content

Latest commit

 

History

History
93 lines (75 loc) · 6.79 KB

File metadata and controls

93 lines (75 loc) · 6.79 KB

Tech Stack

Server-Side

Component Version Purpose
PHP 8.x Application language — procedural style with classes for DB, Session, and Media
MariaDB 10.x Relational database — 17 tables, InnoDB engine, foreign key constraints with CASCADE
Apache 2.x Web server with .htaccess directory protection and PHP module

Frontend (all bundled locally — zero CDN dependencies)

Component Version Location Purpose
Bootstrap 5.x libs/bootstrap/ CSS framework for responsive layout, forms, tables, alerts, modals
Bootstrap Icons 1.x libs/icons/ SVG icon sprite — referenced via <use href="...bi.svg#icon-name">
jQuery 3.x libs/js/jquery.min.js DOM manipulation, AJAX for product/customer autocomplete search
Datepicker 1.x libs/datepicker/ Bootstrap Datepicker for sales report date-range selection
Main CSS libs/css/main.css Custom application styles (sidebar, header, page layout)

Offline-First Design

  • All CSS, JS, fonts, and icons are bundled in the repository
  • No external CDN URLs in any <link> or <script> tag
  • Works on fully air-gapped networks — no internet required
  • jQuery (minified) is the only JavaScript framework; the rest is vanilla JS

Security Features

Feature Implementation File
Password hashing password_hash(PASSWORD_BCRYPT) with auto-upgrade of legacy SHA1 on login; password_needs_rehash() on every login includes/sql.php (authenticate())
SQL injection prevention prepare_query() / prepare_select() with bound ? parameters throughout includes/database.php
CSRF protection (POST) Per-session token via random_bytes(32), verified with hash_equals() in verify_csrf() includes/functions.php
CSRF protection (GET deletes) csrf_url_param() on delete links; verify_get_csrf() in handler includes/functions.php
Session hardening httponly, samesite=Lax, strict_mode, secure when is_secure_context() is true — set before session_start() includes/session.php
Session fixation session_regenerate_id(true) on every login includes/session.php
Session idle timeout check_session_timeout() destroys idle sessions after SESSION_TIMEOUT_MINUTES (default 30) includes/session.php, .env
XSS prevention h() (htmlspecialchars ENT_QUOTES wrapper) on all dynamic output includes/functions.php
Output sanitization remove_junk() pipeline: nl2br → trim → stripslashes → strip_tags → htmlspecialchars includes/functions.php
Input sanitization sanitize_input($str, $max_length=2000) for POST values: trim + strip tags + length cap includes/functions.php
CSP headers default-src 'self', script-src 'self', style-src 'self', frame-ancestors 'none' — no unsafe-inline/eval; emitted on every authenticated response layouts/header.php
Security headers X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy (camera/mic/geo off) layouts/header.php
Login rate limiting 5 attempts per IP per 15-min window via failed_logins table; auto-cleared on success includes/sql.php, users/auth.php
Password complexity validate_password(): min 8 chars, requires letter + digit, common-password denylist includes/functions.php
Password reset (self-service) Token-based: 64-char random, bcrypt-hashed in password_resets, 1-hour expiry, single-use (atomic consume) includes/sql_password_reset.php, migration 022
Per-module permissions (RBAC) can($module, $action) / require_permission() — Admin bypass, then permissions table override, then role defaults includes/sql.php, migration 024
Audit log audit($module, $action, $record_id, $summary) records CRUD + login/logout to audit_log with user/IP includes/sql.php, migration 023, users/audit.php (viewer)
Soft-delete Reversible delete on 5 tables; hard DELETE requires explicit purge by Admin includes/sql.php, migrations 005–009
Multi-tenant isolation All queries scoped to $_SESSION['active_org_id']; join_product_table() / find_all() auto-filter by org_id; HARNESS_ORG used in tests includes/sql.php, migrations 010–021
Directory listing .htaccess blocks indexing in includes/, uploads/, and project root .htaccess files
Activity logging All page requests logged with user_id, IP, action, timestamp includes/sql.php (logAction())

Dev Tooling

Tool Version Purpose Config
Composer 2.x PHP dependency manager — dev dependencies only (not used at runtime) composer.json
PHPUnit 11.x Unit and integration test runner tests/ — invoked via tests/run.sh or vendor/bin/phpunit

CI / Quality Tools

Tool Purpose Config
GitHub Actions php -l lint + full test suite on push/PR .github/workflows/ci.yml
Pre-commit hook php -l on staged PHP files, blocks commit on syntax error .githooks/pre-commit (opt-in: bash scripts/install-hooks.sh)
Test suite Two runners: legacy harness (test() / check(), 7 suites via tests/run.sh) + PHPUnit (CSRF, Session, PasswordReset, Permissions, Health, Backup, LogRotate, InfraSmoke). Playwright UI tests run separately. All use HARNESS_ data isolation. tests/run.sh, phpunit.xml

Deployment Target

  • Primary: Raspberry Pi 5 running Apache + MariaDB (Raspberry Pi OS)
  • Also compatible: Any Debian/Ubuntu LAMP stack
  • Memory: Minimal — typical PHP memory_limit of 128M is sufficient
  • Storage: Proportional to product images and sales history; database starts under 1MB

Configuration

Configuration is via .env file in the project root (parsed by includes/config.php):

DB_HOST=localhost
DB_USER=root
DB_PASS=
DB_NAME=inventory
APP_SECRET=<random 64-char hex>
SESSION_TIMEOUT_MINUTES=30
  • APP_SECRET — used for CSRF token derivation (generate with openssl rand -hex 32)
  • SESSION_TIMEOUT_MINUTES — idle timeout enforced by check_session_timeout() (default 30; set to 0 to disable for dev)
  • .env is git-ignored; .env.example is the committed template
  • Constants defined: DB_HOST, DB_USER, DB_PASS, DB_NAME, APP_SECRET, SESSION_TIMEOUT
  • Currency code is stored in the settings DB table (key: currency_code, default USD). Change it in the app via Settings (Admin-only). LOGIN_MAX_ATTEMPTS and LOGIN_WINDOW_SECONDS can be overridden by defining them before sql.php loads.