diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b919835
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.claude/
+.mcp.json
+TODO.md
+*.min.css
+*.min.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..1e0448f
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,20 @@
+
+
+# Changelog
+
+## [Unreleased]
+
+### Added
+- **Repository** -- initial repo creation with scaffolding
+- **System Plugin** -- Extension class, service provider
+- **SQL Schema** -- 8 tables
+- **Admin Component** -- 6 views: Dashboard, Shipments, Routes, Carriers, Warehouses, Packages
+- **Webservices Plugin** -- 6 API routes
+- **Configuration** -- basic settings fieldset
+- **Access Control** -- core permissions
+- **Language Files** -- en-GB translations
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..eaf695b
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,30 @@
+# MokoSuiteLogistics
+
+Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management
+
+## Quick Reference
+
+| Field | Value |
+|---|---|
+| **Package** | `pkg_mokosuitelogistics` |
+| **Layer** | 2 (requires: Client, CRM) |
+| **Language** | PHP 8.3+ |
+| **Branch** | develop on `dev`, merge to `main` (protected) |
+
+## Architecture
+
+Joomla **package** -- Layer 2 add-on. CRM contacts as shippers/consignees, shipment tracking with multi-stop routes, warehouse zone management.
+
+## Rules
+
+- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, `*.min.css`/`*.min.js`
+- **Attribution**: `Authored-by: Moko Consulting`
+- **Workflow directory**: `.mokogitea/`
+- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoCLI/wiki)
+- **Changelog**: `[Unreleased]` only -- release system assigns versions
+
+## Coding Standards
+
+- PHP 8.3+ / Joomla 6 patterns
+- `$this->getDatabase()` in models, `Factory::getContainer()->get(DatabaseInterface::class)` in helpers
+- `Factory::getApplication()->getIdentity()` for user
diff --git a/source/packages/com_mokosuitelogistics/admin/access.xml b/source/packages/com_mokosuitelogistics/admin/access.xml
new file mode 100644
index 0000000..98f1236
--- /dev/null
+++ b/source/packages/com_mokosuitelogistics/admin/access.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/source/packages/com_mokosuitelogistics/admin/config.xml b/source/packages/com_mokosuitelogistics/admin/config.xml
new file mode 100644
index 0000000..ddda8e7
--- /dev/null
+++ b/source/packages/com_mokosuitelogistics/admin/config.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/source/packages/com_mokosuitelogistics/admin/services/provider.php b/source/packages/com_mokosuitelogistics/admin/services/provider.php
new file mode 100644
index 0000000..a7e02a6
--- /dev/null
+++ b/source/packages/com_mokosuitelogistics/admin/services/provider.php
@@ -0,0 +1,30 @@
+set(
+ ComponentInterface::class,
+ function (Container $container) {
+ $component = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class));
+ $component->setMVCFactory($container->get(MVCFactoryInterface::class));
+ return $component;
+ }
+ );
+ }
+};
diff --git a/source/packages/com_mokosuitelogistics/mokosuitelogistics.xml b/source/packages/com_mokosuitelogistics/mokosuitelogistics.xml
new file mode 100644
index 0000000..0179e6e
--- /dev/null
+++ b/source/packages/com_mokosuitelogistics/mokosuitelogistics.xml
@@ -0,0 +1,32 @@
+
+
+ com_mokosuitelogistics
+ 0.0.0
+ 2026-06
+ Moko Consulting
+ hello@mokoconsulting.tech
+ https://mokoconsulting.tech
+ (C) 2026 Moko Consulting
+ GPL-3.0-or-later
+ Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management
+ MokoConsulting\Component\MokoSuiteLogistics
+
+
+ services
+ src
+ tmpl
+ language
+ access.xml
+ config.xml
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.ini b/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.ini
new file mode 100644
index 0000000..d8af8a0
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.ini
@@ -0,0 +1,3 @@
+PLG_SYSTEM_MOKOSUITELOGISTICS="Logistics"
+PLG_SYSTEM_MOKOSUITELOGISTICS_DESCRIPTION="MokoSuiteLogistics system plugin"
+PLG_SYSTEM_MOKOSUITELOGISTICS_ENABLED="Enable MokoSuiteLogistics"
diff --git a/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.sys.ini b/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.sys.ini
new file mode 100644
index 0000000..d8af8a0
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/language/en-GB/plg_system_mokosuitelogistics.sys.ini
@@ -0,0 +1,3 @@
+PLG_SYSTEM_MOKOSUITELOGISTICS="Logistics"
+PLG_SYSTEM_MOKOSUITELOGISTICS_DESCRIPTION="MokoSuiteLogistics system plugin"
+PLG_SYSTEM_MOKOSUITELOGISTICS_ENABLED="Enable MokoSuiteLogistics"
diff --git a/source/packages/plg_system_mokosuitelogistics/mokosuitelogistics.xml b/source/packages/plg_system_mokosuitelogistics/mokosuitelogistics.xml
new file mode 100644
index 0000000..7b93a00
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/mokosuitelogistics.xml
@@ -0,0 +1,43 @@
+
+
+ plg_system_mokosuitelogistics
+ 0.0.0
+ 2026-06
+ Moko Consulting
+ hello@mokoconsulting.tech
+ https://mokoconsulting.tech
+ (C) 2026 Moko Consulting
+ GPL-3.0-or-later
+ MokoSuiteLogistics system plugin -- schema owner and bootstrap
+ MokoConsulting\Plugin\System\MokoSuiteLogistics
+
+ src
+ services
+ sql
+ language
+
+
+
+ sql/install.mysql.sql
+
+
+
+
+ sql/uninstall.mysql.sql
+
+
+
+ en-GB/plg_system_mokosuitelogistics.ini
+ en-GB/plg_system_mokosuitelogistics.sys.ini
+
+
+
+
+
+
+
diff --git a/source/packages/plg_system_mokosuitelogistics/services/provider.php b/source/packages/plg_system_mokosuitelogistics/services/provider.php
new file mode 100644
index 0000000..281d8e8
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/services/provider.php
@@ -0,0 +1,31 @@
+set(
+ PluginInterface::class,
+ function (Container $container) {
+ $dispatcher = $container->get(DispatcherInterface::class);
+ $plugin = new Logistics($dispatcher, (array) PluginHelper::getPlugin('system', 'mokosuitelogistics'));
+ $plugin->setApplication(Factory::getApplication());
+ return $plugin;
+ }
+ );
+ }
+};
diff --git a/source/packages/plg_system_mokosuitelogistics/sql/install.mysql.sql b/source/packages/plg_system_mokosuitelogistics/sql/install.mysql.sql
new file mode 100644
index 0000000..7043444
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/sql/install.mysql.sql
@@ -0,0 +1,172 @@
+-- MokoSuiteLogistics Schema
+-- Copyright (C) 2026 Moko Consulting
+-- SPDX-License-Identifier: GPL-3.0-or-later
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_carriers` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
+ `name` VARCHAR(255) NOT NULL,
+ `code` VARCHAR(50) NOT NULL,
+ `carrier_type` ENUM('ground','air','sea','rail','courier') NOT NULL DEFAULT 'ground',
+ `tracking_url_template` VARCHAR(500) NULL,
+ `phone` VARCHAR(50) NULL,
+ `email` VARCHAR(255) NULL,
+ `status` ENUM('active','inactive','suspended') NOT NULL DEFAULT 'active',
+ `notes` TEXT NULL,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_code` (`code`),
+ KEY `idx_status` (`status`),
+ KEY `idx_contact` (`contact_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_warehouses` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(255) NOT NULL,
+ `code` VARCHAR(50) NOT NULL,
+ `address` TEXT NULL,
+ `city` VARCHAR(100) NULL,
+ `state` VARCHAR(100) NULL,
+ `postal_code` VARCHAR(20) NULL,
+ `country` VARCHAR(100) NULL,
+ `capacity_sqft` DECIMAL(12,2) NULL,
+ `manager_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
+ `status` ENUM('active','inactive','maintenance') NOT NULL DEFAULT 'active',
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_code` (`code`),
+ KEY `idx_status` (`status`),
+ KEY `idx_manager_contact` (`manager_contact_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_warehouse_zones` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `warehouse_id` INT UNSIGNED NOT NULL,
+ `name` VARCHAR(255) NOT NULL,
+ `zone_type` ENUM('receiving','storage','picking','packing','shipping','cold','hazmat') NOT NULL DEFAULT 'storage',
+ `capacity` INT UNSIGNED NULL,
+ `current_utilization` INT UNSIGNED NOT NULL DEFAULT 0,
+ `ordering` INT NOT NULL DEFAULT 0,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `idx_warehouse` (`warehouse_id`),
+ KEY `idx_zone_type` (`zone_type`),
+ CONSTRAINT `fk_zone_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `#__mokosuitelogistics_warehouses`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_shipments` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `shipment_number` VARCHAR(50) NOT NULL,
+ `shipper_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
+ `consignee_contact_id` INT UNSIGNED NULL COMMENT 'FK to CRM contacts',
+ `carrier_id` INT UNSIGNED NULL,
+ `warehouse_id` INT UNSIGNED NULL,
+ `origin_address` TEXT NULL,
+ `destination_address` TEXT NULL,
+ `shipment_type` ENUM('inbound','outbound','transfer','return') NOT NULL DEFAULT 'outbound',
+ `status` ENUM('draft','booked','picked_up','in_transit','out_for_delivery','delivered','cancelled','returned') NOT NULL DEFAULT 'draft',
+ `priority` ENUM('standard','express','overnight','freight') NOT NULL DEFAULT 'standard',
+ `weight_kg` DECIMAL(10,3) NULL,
+ `volume_cbm` DECIMAL(10,4) NULL,
+ `estimated_pickup` DATETIME NULL,
+ `estimated_delivery` DATETIME NULL,
+ `actual_pickup` DATETIME NULL,
+ `actual_delivery` DATETIME NULL,
+ `tracking_number` VARCHAR(255) NULL,
+ `shipping_cost` DECIMAL(10,2) NULL,
+ `insurance_value` DECIMAL(10,2) NULL,
+ `notes` TEXT NULL,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_shipment_number` (`shipment_number`),
+ KEY `idx_status` (`status`),
+ KEY `idx_shipper_contact` (`shipper_contact_id`),
+ KEY `idx_consignee_contact` (`consignee_contact_id`),
+ KEY `idx_carrier` (`carrier_id`),
+ KEY `idx_warehouse` (`warehouse_id`),
+ KEY `idx_estimated_delivery` (`estimated_delivery`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_routes` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(255) NOT NULL,
+ `carrier_id` INT UNSIGNED NULL,
+ `route_type` ENUM('scheduled','on_demand','dedicated') NOT NULL DEFAULT 'scheduled',
+ `status` ENUM('active','inactive','planned') NOT NULL DEFAULT 'planned',
+ `distance_km` DECIMAL(10,2) NULL,
+ `estimated_duration_hours` DECIMAL(6,2) NULL,
+ `notes` TEXT NULL,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `idx_carrier` (`carrier_id`),
+ KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_route_stops` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `route_id` INT UNSIGNED NOT NULL,
+ `stop_number` INT UNSIGNED NOT NULL,
+ `location_name` VARCHAR(255) NOT NULL,
+ `address` TEXT NULL,
+ `latitude` DECIMAL(10,7) NULL,
+ `longitude` DECIMAL(10,7) NULL,
+ `stop_type` ENUM('pickup','dropoff','waypoint','rest') NOT NULL DEFAULT 'dropoff',
+ `estimated_arrival` DATETIME NULL,
+ `estimated_departure` DATETIME NULL,
+ `actual_arrival` DATETIME NULL,
+ `actual_departure` DATETIME NULL,
+ `notes` TEXT NULL,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `idx_route` (`route_id`),
+ KEY `idx_stop_number` (`route_id`, `stop_number`),
+ CONSTRAINT `fk_stop_route` FOREIGN KEY (`route_id`) REFERENCES `#__mokosuitelogistics_routes`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_packages` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `shipment_id` INT UNSIGNED NOT NULL,
+ `package_number` VARCHAR(50) NOT NULL,
+ `description` VARCHAR(255) NULL,
+ `weight_kg` DECIMAL(10,3) NULL,
+ `length_cm` DECIMAL(8,2) NULL,
+ `width_cm` DECIMAL(8,2) NULL,
+ `height_cm` DECIMAL(8,2) NULL,
+ `declared_value` DECIMAL(10,2) NULL,
+ `is_fragile` TINYINT(1) NOT NULL DEFAULT 0,
+ `is_hazmat` TINYINT(1) NOT NULL DEFAULT 0,
+ `barcode` VARCHAR(255) NULL,
+ `status` ENUM('created','labeled','in_transit','delivered','damaged','lost') NOT NULL DEFAULT 'created',
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `modified` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_package_number` (`package_number`),
+ KEY `idx_shipment` (`shipment_id`),
+ KEY `idx_status` (`status`),
+ KEY `idx_barcode` (`barcode`),
+ CONSTRAINT `fk_package_shipment` FOREIGN KEY (`shipment_id`) REFERENCES `#__mokosuitelogistics_shipments`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__mokosuitelogistics_tracking_events` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `shipment_id` INT UNSIGNED NOT NULL,
+ `package_id` INT UNSIGNED NULL,
+ `event_type` ENUM('created','picked_up','in_transit','at_hub','out_for_delivery','delivered','exception','returned') NOT NULL,
+ `location` VARCHAR(255) NULL,
+ `latitude` DECIMAL(10,7) NULL,
+ `longitude` DECIMAL(10,7) NULL,
+ `description` TEXT NULL,
+ `event_time` DATETIME NOT NULL,
+ `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `idx_shipment` (`shipment_id`),
+ KEY `idx_package` (`package_id`),
+ KEY `idx_event_type` (`event_type`),
+ KEY `idx_event_time` (`event_time`),
+ CONSTRAINT `fk_tracking_shipment` FOREIGN KEY (`shipment_id`) REFERENCES `#__mokosuitelogistics_shipments`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/source/packages/plg_system_mokosuitelogistics/sql/uninstall.mysql.sql b/source/packages/plg_system_mokosuitelogistics/sql/uninstall.mysql.sql
new file mode 100644
index 0000000..0f24cf1
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/sql/uninstall.mysql.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `#__mokosuitelogistics_tracking_events`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_packages`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_route_stops`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_routes`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_shipments`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_warehouse_zones`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_warehouses`;
+DROP TABLE IF EXISTS `#__mokosuitelogistics_carriers`;
diff --git a/source/packages/plg_system_mokosuitelogistics/src/Extension/Logistics.php b/source/packages/plg_system_mokosuitelogistics/src/Extension/Logistics.php
new file mode 100644
index 0000000..44b061a
--- /dev/null
+++ b/source/packages/plg_system_mokosuitelogistics/src/Extension/Logistics.php
@@ -0,0 +1,20 @@
+
+
+ MokoSuiteLogistics
+ mokosuitelogistics
+ 0.0.0
+ 2026-06
+ Moko Consulting
+ hello@mokoconsulting.tech
+ https://mokoconsulting.tech
+ (C) 2026 Moko Consulting
+ GPL-3.0-or-later
+ Layer 2 — Fleet logistics, shipment tracking, route planning, warehouse management
+
+ plg_system_mokosuitelogistics.zip
+ com_mokosuitelogistics.zip
+ plg_webservices_mokosuitelogistics.zip
+
+
+ https://git.mokoconsulting.tech/api/packages/MokoConsulting/generic/updates/mokosuitelogistics/updates.xml
+
+