pro-tree

System Architecture

Design only — no application code yet. High-level structure for the expanded system: tree management, visitor/scan tracking with GPS scan location, multilingual content with AI-assisted translation, an interactive map, and role-based access control. See the companion docs linked throughout for the detail behind each subsystem.

1. Subsystems

# Subsystem Covered in
1 Public Tree Information Website user-flow.md, page-flow.md
2 Programmer Management System rbac.md
3 Executive Dashboard rbac.md
4 Tree Admin Management System rbac.md, tree-identity-and-relationships.md
5 Tree QR Code System tree-identity-and-relationships.md §4
6 Visitor & Scan Tracking System visitor-identity.md
7 Scan Location Tracking System tree-identity-and-relationships.md §6
8 Map & Zone Management System map-system.md
9 Multilingual Content System multilingual-and-ai-translation.md
10 AI Translation System (Ollama) multilingual-and-ai-translation.md

All ten are one PHP + MySQL application, not separate services — “system” here means a functional area, not a deployable unit. Nothing in this design requires microservices; a single codebase with clear module boundaries (§3) is the right scale for this project.

2. Request-Level Architecture

                        ┌─────────────────────┐
                        │   Apache (XAMPP)     │
                        └──────────┬───────────┘
              ┌─────────────────────┼─────────────────────┐
              ▼                     ▼                     ▼
        public/*.php          admin/*.php             api/*.php
      (no auth — visitor    (admin session +      (JSON — public read
       cookie identity       role permission        endpoints, and
       only, see             check on every         session/role-gated
       visitor-identity.md)  request, see            staff endpoints,
                              rbac.md)                see rbac.md §7)
              │                     │                     │
              └─────────────────────┼─────────────────────┘
                                    ▼
                    includes/functions.php, includes/auth.php
                    (shared PDO-based business logic — the
                     single place DB access happens; controllers
                     never build SQL themselves)
                                    │
                                    ▼
                              MySQL (PDO, prepared statements only)

No framework, no ORM — this matches the existing codebase and keeps the project inside its stated PHP/MySQL constraint. The one architectural rule that matters most: public/, admin/, and api/ are the only three entry-point directories, and every file in admin//api/ starts with the auth+permission check from rbac.md §7 before doing anything else. There is no shared “God” controller — each script is small and single-purpose, following the existing tree_form.php-style pattern.

Extends the current layout additively — nothing existing moves.

pro tree/
├── config/
│   ├── config.php          # existing — add OLLAMA_URL, OLLAMA_MODEL, OLLAMA_VISION_MODEL
│   └── db.php
├── includes/
│   ├── auth.php            # requireAdmin(), requirePermission() — see rbac.md
│   ├── functions.php       # existing shared helpers
│   ├── lang.php            # existing i18n helpers
│   ├── translation.php     # NEW — Ollama client + translation_drafts CRUD (server-only)
│   ├── geo.php             # NEW — haversine/point-in-polygon helpers for scan-location + map (see map-system.md)
│   └── vendor/
├── public/                 # visitor-facing, no auth — unchanged in shape
│   ├── index.php
│   ├── tree.php
│   ├── interest.php
│   └── map.php             # NEW — interactive public map page (see map-system.md)
├── admin/                  # session + permission gated — unchanged in shape, new files added
│   ├── tree_form.php
│   ├── tree_relationships.php   # NEW — prev/next rewiring UI (see tree-identity-and-relationships.md)
│   ├── origins.php / origin_form.php   # NEW
│   ├── translations.php         # NEW — review/approve AI translation drafts
│   ├── map_admin.php            # NEW — zone boundary + tree marker editor
│   ├── users.php                # NEW — admin accounts + role assignment (Programmer only)
│   └── ... (existing files)
├── api/                     # NEW — JSON endpoints, see rbac.md §7 for the enforcement pattern
│   ├── bootstrap.php
│   ├── public/               # no auth: tree lookup, scan logging, interest submit
│   └── staff/                 # session + permission gated
├── storage/                  # NEW — kept outside public/ webroot
│   └── translation_cache/     # optional: cache AI responses
└── docs/

4. Scalability Notes

The current scale (pilot: low hundreds of trees, XAMPP/single-VPS deployment) does not need caching layers, queues, or horizontal scaling. Design choices that keep the door open without over-building now:

5. Security Considerations

Consolidates the security-relevant points spread across the other docs, so there’s one place to check before implementation:

Concern Handling Detail
Admin/role access control Deny-by-default RBAC, checked server-side on every request, never just hidden in the UI rbac.md §7–8
Ollama settings Server-only (includes/translation.php), never sent to the browser; gemini.config.manage permission restricted to Programmer multilingual-and-ai-translation.md §5
Visitor privacy / GPS Location permission is opt-in at the browser level; a denial must not block the scan; only coarse, purpose-limited data is stored tree-identity-and-relationships.md §6
Interest emails (PDPA-leaning) Consent implied by explicit form submission; visible only to roles with interest.view rbac.md §3–4
SQL injection PDO prepared statements only, no exceptions — already the existing convention in functions.php existing code
CSRF Existing admin forms have no CSRF token today (noted as a gap by prior research) — recommend adding a per-session token check on all state-changing admin/*.php/api/staff/*.php POSTs as part of this build, not deferred new work item
Session fixation Already handled — session_regenerate_id(true) on login (includes/auth.php) existing code
Direct URL/endpoint access Every admin/API script re-checks permissions itself; nothing is “secure” purely because no link points to it rbac.md §8