# C4 — Containers (Level 2) — TinyPOS (`tnx-pos`)

> Produced by the Reversa **Architect** (phase: interpretation) · doc_level: `complete`
> Generated on 2026-09-18

**Confidence scale:** 🟢 CONFIRMED · 🟡 INFERRED · 🔴 GAP

The container view opens the TinyPOS box. It is a **monolith**, so "containers" here are the runtime/deployable units and the one significant client-side runtime (the injected POS cart engine), rather than a microservice fleet.

---

## Containers

| Container | Technology | Responsibility | Confidence |
|-----------|-----------|----------------|------------|
| **Web Application** | Laravel 5.6.39 · PHP 7.4.33 · Apache + mod_php (`www-data`); Encore\Admin shell | HTTP routing, session auth, Blade rendering, all business logic (controllers + Eloquent models). Single deployable. | 🟢 |
| **POS Cart Client** | In-browser JS injected via `Admin::script()` (Vue 2 / jQuery / Bootstrap 4, built by Laravel Mix) | Builds & de-dupes the cart client-side, re-prices lines on customer change, enforces client-side debt rules, submits the order to `/orders`. No standalone build artefact — emitted inline by `PosController`. | 🟢 |
| **Scheduler / Cron** | `php artisan schedule:run` (system cron, every minute) → `App\Console\Kernel` | Runs the **daily** `Order::summaryLogging()` rollup into `customer_order_summary`; also the `CustomerOrderSummaryLogging` artisan command. | 🟢 |
| **Database** | MariaDB 10.11.13 (Eloquent, `mysql` driver) | Persistent store for all entities incl. the append-only debt ledger and the RBAC tables. | 🟢 |
| **Local File Storage** | Laravel `public` disk; `intervention/image` | Stores & resizes product / gift images (`fit(300,300)`); served as public assets. | 🟢 |

> Deployment topology (Docker/Apache/Nginx configs, cron install) is **not** expanded into a `deployment.md` here — that artifact is produced only at `doc_level: detailed`. The current level is `complete`.

---

## Diagram

```mermaid
flowchart TB
    admin["👤 Store Administrator"]
    scanner["🔌 Barcode scanner"]
    printer["🖨️ Receipt printer"]
    cronsys["⏱️ System cron"]

    subgraph tinypos [TinyPOS]
        direction TB
        web["🟦 <b>Web Application</b><br/>Laravel 5.6 · PHP 7.4 · Apache/mod_php<br/>Encore\\Admin shell<br/><i>controllers + Eloquent models,<br/>all business logic</i>"]
        client["🟩 <b>POS Cart Client</b><br/>injected JS (Vue2/jQuery/Bootstrap)<br/><i>client-side cart, live re-pricing,<br/>debt rules, submit</i>"]
        sched["🟧 <b>Scheduler / Cron</b><br/>artisan schedule:run → Kernel<br/><i>daily Order::summaryLogging()</i>"]
        db[("🗄️ <b>Database</b><br/>MariaDB 10.11<br/><i>all entities + debt ledger + RBAC</i>")]
        files["📁 <b>Local File Storage</b><br/>public disk · intervention/image<br/><i>product & gift images</i>"]
    end

    admin -->|"HTTPS, session (admin guard)"| web
    web -->|"serves page + injects cart JS"| client
    client -->|"AJAX get-price / scan;<br/>POST /orders (submit)"| web
    scanner -->|"codes → scan endpoints"| client
    web -->|"render print view"| printer
    cronsys -->|"every minute"| sched
    sched -->|"batch rollup writes"| db
    web -->|"Eloquent read/write"| db
    web -->|"read/write/resize images"| files

    classDef person fill:#08427b,stroke:#052e56,color:#fff
    classDef cont fill:#1168bd,stroke:#0b4884,color:#fff
    classDef store fill:#2e7d32,stroke:#1b4d20,color:#fff
    classDef ext fill:#999,stroke:#6b6b6b,color:#fff
    class admin person
    class web,client,sched cont
    class db,files store
    class scanner,printer,cronsys ext
```

---

## Container interactions of note

- **Web ↔ POS Cart Client is a chatty, synchronous coupling.** The client fetches prices *synchronously* per line via `GET /products/get-price` and looks products up via `GET /pos/scan`. Order submission is a single `POST /orders` (or `PUT /orders/{id}` when rehydrating a draft). The server is the pricing source of truth (`Product::getPriceByCustomerType`); the client mirrors the debt rules for UX but the server re-enforces them. 🟢
- **Scheduler is decoupled and eventually-consistent.** Statistics reads (`CustomerController::statis`) are only as fresh as the last nightly run; same-day sales are invisible until the rollup (ADR-0005). 🟢
- **Single database, no cache/queue container.** `config/cache.php` and `config/queue.php` exist but no Redis/queue worker is deployed; work is synchronous request-time or the nightly cron. 🟡 (no queue worker found)
- **File storage is local, not object storage.** Image cleanup on product update targets the wrong root (`app/public2`) and silently fails — see GAP-P1 / architecture §8. 🔴

Component-level decomposition of the Web Application is in `c4-components.md`.
</content>
