Reference
Architecture reference
Core structure and extension boundaries for developers.
Includes the complete docs/ARCHITECTURE.md reference from this build. Application paths refer to your own installation.
On this page
VoltexaHub architecture#
Status: current release (the version is forum.version in config/forum.php). Product name: VoltexaHub. Goal: downloadable forum software with a stable core, replaceable public themes, and trusted PHP plugins. Laravel 13 / PHP 8.4 / MySQL. Server-rendered Blade and small Alpine interactions; no SPA requirement.
Boundaries#
app/Models: persistent identity, forum hierarchy, discussions, posts.app/Support: permissions, settings and safe Markdown rendering.app/Extensions: theme resolution, plugin lifecycle and extension contracts.app/Http: validation, authorization and HTTP workflows.themes/default: the shipped public interface.themes/aurora: a real inheriting child theme.plugins/announcements: the independent example plugin.resources/views/admin: recovery-capable administration, independent of public extensions.
Controllers validate and authorize before changing data. Thread creation and first-post insertion share a transaction. Replies lock their thread before checking the locked flag, avoiding a concurrent lock/reply race. A typed ThreadCreated event implements ShouldDispatchAfterCommit.
Authorization#
Users may have several groups. Guests use the guests group; signed-in users use their explicit memberships. Banned users fail all capabilities, including existing sessions. No implicit administrator bypass.
For a capability, walk the current forum, its ancestors, then global scope. At the first scope with an explicit rule, deny wins across memberships; otherwise allow wins. No rule means denied. Inherit removes a rule. Zero scope_id means global; positive values refer to forum nodes and are validated on write. Categories organize forums, and do not accept posts directly. A specifically allowed child can be accessed even when its parent is denied: this is intentional nearest-scope behavior.
Individual moderator assignments are stored by member and forum node. They grant only thread.moderate at that node and descendants. The nearest scope with an explicit group rule or assignment decides; a group deny wins over an assignment at the same scope, while a nearer child rule wins over an ancestor decision. Assignments never grant forum.view or admin.access. Moderation still requires both visibility and moderation permission, including for queue counts, writes, and move destinations. Bans override all grants. The admin inspector explains the winning group rule, assignment, inherited scope, or absence of a grant using the same resolver as authorization.
Every thread listing, profile activity listing, search, count and direct discussion/post URL uses visibility checks. Changing a button in a theme cannot grant a capability.
Data and content#
Migrations are the schema source of truth. Foreign keys protect ownership and forum structure. Indexes support sorted thread lists and ordered post pagination. Markdown source is stored verbatim; CommonMark strips HTML and disallows unsafe link schemes. Raw HTML is never accepted as a posting format. Future editor adapters must preserve source and explicitly version any new format. Images referenced in Markdown load from their remote origin; hosted attachments are a future milestone.
Delivery#
Railway runs a Docker image with FrankenPHP, a MySQL service on private networking, and database-backed sessions/cache. Credentials are environment variables. Migrations run before deployment. Public files are served only from public/. A web-service volume holds private uploads outside the release directory. Attachment metadata lives in MySQL; delivery always passes through current forum authorization. The shared uploads disk can also support future avatars and branding.
No Node runtime is needed to run the PHP release; frontend assets are compiled during release/build. Redis and an external search engine are not required. Production includes a worker service; notification delivery remains synchronous.
Release scope and limits#
The agreed 1.0 scope includes editor adapters, plugin uninstall, dependency version constraints and extension scaffolding. Polls, private conversations and an automated upgrade UI remain outside this release. Password resets require a configured mail transport. No MariaDB support claim is made until that database is tested.
Search#
MySQL uses native FULLTEXT indexes on threads.title and posts.body, natural-language matching, and a combined relevance score with double weight for title matches. A title match appears once at the opening post; body matches link to individual replies. Current visibility and soft-deletion restrictions apply before pagination and counts. Exact display-name author filtering does not expose emails or an unrestricted member directory. Post permalinks calculate the current page on access so deletion of earlier replies does not stale a saved search link.
MySQL's configured stopwords and token-length limits apply; very short/common terms may produce no results. SQLite development uses escaped literal substring matching with title weighting instead of MySQL tokenization. Native full-text indexes update with committed writes; MySQL search tests therefore use committed fixtures. No external search service or worker is required.
Discussion activity#
thread_user stores explicit watching state and a monotonic last-read post ID per member/discussion. Page reads advance through the last displayed post, not through unseen later pages. Read updates serialize on the member; watch changes and reply creation serialize on the thread. reply_notifications references posts and recipients, with one row per recipient/reply, and cascades with deleted posts or users. Notifications are inserted inside the reply transaction for authorized watchers other than the author. Public lists, counts, and actions filter by current visibility and ownership; no thread titles or excerpts are copied into notification rows. Delivery is synchronous and in-app; email subscriptions and queued fan-out are future work.