## ADDED Requirements

### Requirement: Scheduler is triggered every minute on the dev server
The dev server SHALL invoke `php artisan schedule:run` from the deployed project root (`/var/www/html/tnx_pos_2026/dev/pos/src`) once every minute via a system cron entry, so that tasks defined in `App\Console\Kernel::schedule` execute when due.

#### Scenario: Due task executes
- **WHEN** a task in `Kernel::schedule` becomes due (e.g. `daily()` at 00:00 Asia/Ho_Chi_Minh)
- **THEN** it is executed within that minute by the cron-triggered `schedule:run`, without any manual invocation

#### Scenario: No task is due
- **WHEN** cron invokes `schedule:run` in a minute where no task is due
- **THEN** the command exits successfully without running any task and without producing persistent output

### Requirement: Scheduler runs as the web server user
The cron entry SHALL execute `schedule:run` as `www-data`, the same OS user as Apache/mod_php.

#### Scenario: Files created by the scheduler remain writable by the web server
- **WHEN** the scheduler is the first process to create a file under `storage/` on a given day (e.g. `storage/logs/laravel-YYYY-MM-DD.log`)
- **THEN** the file is owned by `www-data` and subsequent HTTP requests can write to it without permission errors

#### Scenario: Manual invocation under the cron user succeeds
- **WHEN** an operator runs `sudo -u www-data /usr/bin/php artisan schedule:run` in the project root
- **THEN** the command completes without permission or configuration errors and prints either the executed task or "No scheduled commands are ready to run."

### Requirement: Cron definition is versioned in the repository
The cron entry SHALL be stored in the repository at `deploy/cron.d/tnx-pos-dev` as a complete `/etc/cron.d`-format file (with user column), with LF line endings and a trailing newline, and its content SHALL be byte-identical to what is installed on the server.

#### Scenario: Repo file is a valid cron.d entry
- **WHEN** `deploy/cron.d/tnx-pos-dev` is read
- **THEN** it contains exactly one job line `* * * * * www-data cd /var/www/html/tnx_pos_2026/dev/pos/src && /usr/bin/php artisan schedule:run >> /dev/null 2>&1`, uses LF line endings, and ends with a newline

#### Scenario: Line endings cannot regress on Windows checkouts
- **WHEN** the file is committed from a Windows working copy
- **THEN** `.gitattributes` forces `deploy/cron.d/*` to `eol=lf` so the committed and checked-out content stays LF

### Requirement: CI installs the cron entry on every dev deploy
The `pos-dev` GitLab CI job SHALL install `deploy/cron.d/tnx-pos-dev` to `/etc/cron.d/tnx-pos-dev` with owner `root:root` and mode `0644` on every deploy, using a single `sudo install` command, so the server never drifts from the repository.

#### Scenario: Fresh deploy installs the entry
- **WHEN** the `pos-dev` job runs on a server where `/etc/cron.d/tnx-pos-dev` does not exist
- **THEN** after the job, `/etc/cron.d/tnx-pos-dev` exists, is owned by `root:root`, has mode `0644`, and matches the repo file

#### Scenario: Re-deploy overwrites a drifted entry
- **WHEN** `/etc/cron.d/tnx-pos-dev` on the server differs from the repo file and the `pos-dev` job runs
- **THEN** the server file is replaced with the repo content

#### Scenario: Missing sudo grant fails the deploy visibly
- **WHEN** `gitlab-runner` is not permitted to run the `install` command via sudo
- **THEN** the `pos-dev` job fails at that step with a sudo error rather than silently skipping cron installation

### Requirement: Scheduler setup is documented
`README.md` SHALL document how the dev scheduler is driven (cron → `schedule:run`), the required sudoers rule for `gitlab-runner`, and the verification commands.

#### Scenario: Operator can verify the scheduler
- **WHEN** an operator follows the README verification steps on the dev server
- **THEN** they can confirm the installed cron file, observe `(www-data) CMD (...)` entries in the cron log, and run `schedule:run` manually as `www-data`
