# Conversion Report

_generated 2026-09-28T03:39:28Z_

| Status | Tasks |
|---|---|
| done | 36 |
| skipped | 1 |

## Gate A findings — 346

- `_reversa_sdd/artisan-migrate/contracts.md:15` (unit:artisan-migrate) — unresolved confidence marker: - **CSRF:** not applicable — it is a `GET`, so no CSRF token is required or checked. This is itself a risk (a safe verb performs a side effect). 🔴 (`routes/web.
- `_reversa_sdd/artisan-migrate/contracts.md:24` (unit:artisan-migrate) — unresolved confidence marker: - **Response — a migration throws:** no try/catch here → the exception propagates as `500` (framework default). 🟡 (`routes/web.php:32-36`)
- `_reversa_sdd/artisan-migrate/contracts.md:48` (unit:artisan-migrate) — unresolved confidence marker: | **Producer** | operators (human) | the sole caller is an operator hitting the URL to apply migrations; there is no programmatic client in the codebase. 🟡 |
- `_reversa_sdd/artisan-migrate/contracts.md:59` (unit:artisan-migrate) — unresolved confidence marker: - **No observability:** no log/metric/audit of who triggered the migration or its result. 🔴 (`routes/web.php:32-36`, absence)
- `_reversa_sdd/artisan-migrate/design.md:35` (unit:artisan-migrate) — unresolved confidence marker: - **A migration throws (SQL error, bad migration):** the exception is **not** caught in the closure, so it propagates to the framework handler as an HTTP `500`.
- `_reversa_sdd/artisan-migrate/design.md:36` (unit:artisan-migrate) — unresolved confidence marker: - **Non-zero exit without exception:** the migrator returns a non-zero code but does not throw; the response still reports `"Migrating completed<br>"`, masking 
- `_reversa_sdd/artisan-migrate/design.md:41` (unit:artisan-migrate) — unresolved confidence marker: - **`database/migrations/`** — the set of migration classes actually executed. 🟡 (applied by the call)
- `_reversa_sdd/artisan-migrate/design.md:43` (unit:artisan-migrate) — unresolved confidence marker: - **Database connection** — the migrator applies DDL against the configured connection; a misconfigured connection fails the call. 🟡 (`config/database.php`)
- `_reversa_sdd/artisan-migrate/design.md:49` (unit:artisan-migrate) — unresolved confidence marker: | Migrations are triggerable over HTTP as a deployment convenience (no shell access assumed) | `routes/web.php:31-37` | 🟡 |
- `_reversa_sdd/artisan-migrate/design.md:53` (unit:artisan-migrate) — unresolved confidence marker: | Placed behind the admin auth group only — no dedicated permission/role | `routes/web.php:23-31`, `config/admin.php:29` | 🟡 |
- `_reversa_sdd/artisan-migrate/design.md:61` (unit:artisan-migrate) — unresolved confidence marker: None. The exit code is captured but discarded (`//dd($exitCode);` is commented out), and there is no log, metric, audit entry, or trace recording **who** trigge
- `_reversa_sdd/artisan-migrate/design.md:67` (unit:artisan-migrate) — unresolved confidence marker: - 🟡 **No transaction / partial-migration risk.** The route does not wrap the run; a failure mid-set can leave the schema half-migrated with no automatic rollbac
- `_reversa_sdd/artisan-migrate/design.md:69` (unit:artisan-migrate) — unresolved confidence marker: - 🟡 **Closure route consequences.** A closure route cannot be serialized by `route:cache`, and the migration-trigger logic is not isolated for unit testing. 🟡 (
- `_reversa_sdd/artisan-migrate/design.md:70` (unit:artisan-migrate) — unresolved confidence marker: - 🟡 **`--force` in production is intentional but removes the safety prompt** — acceptable for a web trigger, but it means an accidental hit runs immediately wit
- `_reversa_sdd/artisan-migrate/requirements.md:12` (unit:artisan-migrate) — unresolved confidence marker: It is a deployment/operations convenience: it lets an operator apply pending schema migrations from a browser, without shell/CLI access to the host — `--force` 
- `_reversa_sdd/artisan-migrate/requirements.md:38` (unit:artisan-migrate) — unresolved confidence marker: | RF-05 | Surface a broken migration | Could | A migration that throws propagates as an HTTP `500` (no try/catch here). 🟡 |
- `_reversa_sdd/artisan-migrate/requirements.md:47` (unit:artisan-migrate) — unresolved confidence marker: | Availability | Long-running/failed migrations block the request thread and can leave the schema partially migrated with no rollback here | `routes/web.php:32-
- `_reversa_sdd/artisan-migrate/requirements.md:49` (unit:artisan-migrate) — unresolved confidence marker: | Maintainability | Closure route — cannot be serialized by `route:cache`, and is not unit-testable as an isolated controller action | `routes/web.php:31-37` | 
- `_reversa_sdd/artisan-migrate/requirements.md:82` (unit:artisan-migrate) — unresolved confidence marker: | Audit / authorization of who ran it (gap) | Won't (as built) | Absent in the legacy; flagged as a 🔴 gap, not current behaviour |
- `_reversa_sdd/artisan-migrate/requirements.md:94` (unit:artisan-migrate) — unresolved confidence marker: | `database/migrations/` | Migration set applied by the call | 🟡 |
- `_reversa_sdd/artisan-migrate/tasks.md:44` (unit:artisan-migrate) — unresolved confidence marker: - Confidence: 🔴 (design decision)
- `_reversa_sdd/artisan-migrate/tasks.md:49` (unit:artisan-migrate) — unresolved confidence marker: - Confidence: 🔴 (design decision)
- `_reversa_sdd/artisan-migrate/tasks.md:54` (unit:artisan-migrate) — unresolved confidence marker: - Confidence: 🔴 (design decision)
- `_reversa_sdd/artisan-migrate/tasks.md:77` (unit:artisan-migrate) — unresolved confidence marker: ## Accepted Risk (was Pending Gaps 🔴)
- `_reversa_sdd/auth/contracts.md:46` (unit:auth) — unresolved confidence marker: - **Note:** logout is a `GET` (not `POST`) in the legacy — CSRF-unprotected by design of the package. 🟡
- `_reversa_sdd/auth/contracts.md:73` (unit:auth) — unresolved confidence marker: - `302 Found` → back with validation error bag on failure. 🟡
- `_reversa_sdd/auth/contracts.md:83` (unit:auth) — unresolved confidence marker: - **Content type:** all responses are `text/html` or `3xx` redirects — there is no JSON contract. A modernized API would need to define its own token/response s
- `_reversa_sdd/auth/design.md:22` (unit:auth) — unresolved confidence marker: ¹ Validation failures use Laravel's redirect-back-with-errors pattern (HTTP 302 to the form), not a JSON 422; the `422` marks *semantic* validation failure. 🟡
- `_reversa_sdd/auth/design.md:104` (unit:auth) — unresolved confidence marker: - 🟡 The `422` status in the interface table is a semantic label; the legacy actually redirects (302) back to the form with a Laravel error bag. A REST reimpleme
- `_reversa_sdd/auth/design.md:106` (unit:auth) — unresolved confidence marker: - 🟡 HTTPS enforcement depends on `ADMIN_SECURE` (default `true`); the effective value in each environment is not in the repo. Validate with ops.
- `_reversa_sdd/auth/requirements.md:61` (unit:auth) — unresolved confidence marker: | Availability | Session driver only (no external auth provider); auth is available whenever the app + DB are up. | `config/admin.php:53-57` (driver `session`) 
- `_reversa_sdd/auth/tasks.md:99` (unit:auth) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/auth/tasks.md:102` (unit:auth) — unresolved confidence marker: - 🔴 Whether login validation errors should stay redirect-based (302 + error bag) or become JSON `422` in a modernized API — human/architecture decision.
- `_reversa_sdd/brands/contracts.md:20` (unit:brands) — unresolved confidence marker: | GET | `settings/brand/{id}` (show) · GET `settings/brand/create` · DELETE `settings/brand/{id}` (destroy) | Framework defaults | Not surfaced in the UI: no cr
- `_reversa_sdd/brands/contracts.md:33` (unit:brands) — unresolved confidence marker: - **UI locks (not enforced server-side):** the id-1 row has no edit action; every row has delete disabled and there is no create button. These are grid-display 
- `_reversa_sdd/brands/contracts.md:62` (unit:brands) — unresolved confidence marker: - **No observability:** brand mutations emit no telemetry. 🔴 (`BrandController.php`, absence)
- `_reversa_sdd/brands/design.md:40` (unit:brands) — unresolved confidence marker: - **Unknown id on edit/update:** framework `findOrFail` → `404`. 🟡 (`ModelForm` default)
- `_reversa_sdd/brands/design.md:58` (unit:brands) — unresolved confidence marker: | Unpaginated/unfiltered grid (small catalogue assumption) | `disableFilter()`, `disablePagination()` | 🟡 (`:62-63`) |
- `_reversa_sdd/brands/design.md:66` (unit:brands) — unresolved confidence marker: None. The scaffolded CRUD emits no domain-level log/metric/trace; only framework-default behaviour. 🔴 (`BrandController.php`, absence)
- `_reversa_sdd/brands/design.md:70` (unit:brands) — unresolved confidence marker: - 🟡 **Default-brand lock is id-based.** The edit lock keys off literal id `1`; if the default brand is ever re-seeded with a different id, the lock silently pro
- `_reversa_sdd/brands/design.md:71` (unit:brands) — unresolved confidence marker: - 🟡 **Unpaginated grid.** `disablePagination()` renders all brands at once; fine for a short list, but unbounded as the catalogue grows. (`:63`)
- `_reversa_sdd/brands/design.md:73` (unit:brands) — unresolved confidence marker: - 🔴 **No observability** on brand mutations (see above).
- `_reversa_sdd/brands/requirements.md:29` (unit:brands) — unresolved confidence marker: - **Grid is unpaginated / unfiltered.** Export, row selector, filter, and pagination are all disabled — the brand list is expected to be short. 🟡 (`:60-63`)
- `_reversa_sdd/brands/requirements.md:48` (unit:brands) — unresolved confidence marker: | Usability | Unpaginated single-screen grid — assumes a small brand catalogue | `BrandController.php:60-63` | 🟡 |
- `_reversa_sdd/brands/requirements.md:49` (unit:brands) — unresolved confidence marker: | Observability | None — framework CRUD emits no domain log/metric | `BrandController.php` (absence) | 🔴 |
- `_reversa_sdd/brands/tasks.md:48` (unit:brands) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/brands/tasks.md:53` (unit:brands) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/brands/tasks.md:75` (unit:brands) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/categories/contracts.md:20` (unit:categories) — unresolved confidence marker: | GET `settings/categories/{id}` (show) · GET `settings/categories/create` · DELETE `settings/categories/{id}` | Framework defaults | Not surfaced: no create bu
- `_reversa_sdd/categories/contracts.md:30` (unit:categories) — unresolved confidence marker: | `parent_id` | integer | — | **Not exposed** by the form — cannot be set via the UI; stays null on create. 🔴 (`CategoryController.php` absence) |
- `_reversa_sdd/categories/contracts.md:33` (unit:categories) — unresolved confidence marker: - **UI locks (not enforced server-side):** delete disabled on all rows; there is no create button. Every row is editable (the id-1 edit lock is commented out). 
- `_reversa_sdd/categories/contracts.md:63` (unit:categories) — unresolved confidence marker: - **Two-level hierarchy, UI-blind:** `parent_id` defines groups/children but is not settable through the UI — the module's central gap. 🔴 (`CategoryController.p
- `_reversa_sdd/categories/contracts.md:66` (unit:categories) — unresolved confidence marker: - **No observability:** category mutations emit no telemetry. 🔴 (`CategoryController.php`, absence)
- `_reversa_sdd/categories/design.md:39` (unit:categories) — unresolved confidence marker: - **Unknown id on edit/update:** framework `findOrFail` → `404`. 🟡 (`ModelForm` default)
- `_reversa_sdd/categories/design.md:46` (unit:categories) — unresolved confidence marker: `categories.parent_id` (nullable, self-FK) defines the hierarchy: null = top-level group, non-null = child/leaf. Only children are assignable to products. The U
- `_reversa_sdd/categories/design.md:73` (unit:categories) — unresolved confidence marker: None. The scaffolded CRUD emits no domain-level log/metric/trace. 🔴 (`CategoryController.php`, absence)
- `_reversa_sdd/categories/design.md:78` (unit:categories) — unresolved confidence marker: - 🟡 **Hard-coded statistics ids.** `category_milk_id = 1` and `category_medicine_id = 8` (id 8 marked a placeholder) couple category identity to statistics; a r
- `_reversa_sdd/categories/design.md:79` (unit:categories) — unresolved confidence marker: - 🟡 **No edit lock at all.** Any category — including the statistics-special ids 1/8 — is freely editable/renamable, and the id-1 protection is commented out. R
- `_reversa_sdd/categories/design.md:80` (unit:categories) — unresolved confidence marker: - 🟡 **Unpaginated grid.** `disablePagination()` renders all categories at once. (`:64`)
- `_reversa_sdd/categories/design.md:82` (unit:categories) — unresolved confidence marker: - 🔴 **No observability** on category mutations (see above).
- `_reversa_sdd/categories/requirements.md:51` (unit:categories) — unresolved confidence marker: | Usability | Unpaginated single-screen grid — assumes a small category set | `CategoryController.php:61-64` | 🟡 |
- `_reversa_sdd/categories/requirements.md:52` (unit:categories) — unresolved confidence marker: | Observability | None — framework CRUD emits no domain log/metric | `CategoryController.php` (absence) | 🔴 |
- `_reversa_sdd/categories/tasks.md:48` (unit:categories) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/categories/tasks.md:53` (unit:categories) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/categories/tasks.md:58` (unit:categories) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/categories/tasks.md:81` (unit:categories) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/customers-crud/contracts.md:43` (unit:customers-crud) — unresolved confidence marker: | `birthday` | string | ❌ | `nullable\|string\|regex d/m/yyyy`; parsed to `birthday2` (`Y-m-d`); parse failure → `birthday` nulled 🟡 |
- `_reversa_sdd/customers-crud/contracts.md:68` (unit:customers-crud) — unresolved confidence marker: | `phone` | string | ✅ | `required\|string\|unique:customers,phone,{id},id,deleted_at,NULL` (live-only, excludes self; `string` not `numeric` — differs from cre
- `_reversa_sdd/customers-crud/contracts.md:71` (unit:customers-crud) — unresolved confidence marker: | `gender` | string | ❌* | `string\|in:male,female,other` (no `nullable`: an empty string fails; an absent field passes) 🟡 |
- `_reversa_sdd/customers-crud/contracts.md:72` (unit:customers-crud) — unresolved confidence marker: | `birthday` | string | ❌ | `nullable\|string` — **not** re-parsed into `birthday2` on update 🟡 |
- `_reversa_sdd/customers-crud/contracts.md:76` (unit:customers-crud) — unresolved confidence marker: - **Behavior:** `findOrFail`, `fill($valided)`, `save()`. `birthday2` is not recomputed. 🟡
- `_reversa_sdd/customers-crud/design.md:29` (unit:customers-crud) — unresolved confidence marker: | `phone` | `required\|numeric\|unique:customers,phone,NULL,id,deleted_at,NULL` | `required\|string\|unique:customers,phone,{id},id,deleted_at,NULL` | live-only
- `_reversa_sdd/customers-crud/design.md:32` (unit:customers-crud) — unresolved confidence marker: | `gender` | `nullable\|string\|in:male,female,other` | `string\|in:male,female,other` | update rule lacks `nullable` 🟡 (`:81,153`) |
- `_reversa_sdd/customers-crud/design.md:61` (unit:customers-crud) — unresolved confidence marker: 1. Set header ("Thêm khách hàng"); the breadcrumb parent crumb is mislabeled `__("Sản phẩm")` ("Product"). 🟡 (`:58-62`)
- `_reversa_sdd/customers-crud/design.md:67` (unit:customers-crud) — unresolved confidence marker: 2. `try` to parse `birthday` (`Carbon::createFromFormat('d/m/Y', birthday)->format('Y-m-d')`) into `$valided['birthday2']`; on `Exception` set `$valided['birthd
- `_reversa_sdd/customers-crud/design.md:80` (unit:customers-crud) — unresolved confidence marker: 1. Validate the update ruleset (`phone` string+live-unique-except-id, `type nullable|in:…`, `gender string|in:…` without `nullable`; no `birthday2` re-parse). 🟡
- `_reversa_sdd/customers-crud/design.md:81` (unit:customers-crud) — unresolved confidence marker: 2. `Customer::findOrFail($id)` (assigned to a variable named `$product` — a copy-paste artifact). 🟡 (`:159`)
- `_reversa_sdd/customers-crud/design.md:93` (unit:customers-crud) — unresolved confidence marker: - **Invalid `birthday` on create:** if `Carbon` cannot parse `birthday`, `birthday` is set to `null`, the customer is still created, and `birthday2` is not pers
- `_reversa_sdd/customers-crud/design.md:121` (unit:customers-crud) — unresolved confidence marker: No logging, metrics or tracing is emitted by any `CustomerController` CRUD action. Writes surface to the user only through `admin_toastr` flash messages and val
- `_reversa_sdd/customers-crud/design.md:127` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`update` never recomputes `birthday2`.** Editing `birthday` leaves the queryable `birthday2` stale. (`:146-160`)
- `_reversa_sdd/customers-crud/design.md:128` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`phone` rule mismatch (`numeric` on create, `string` on update)** — a value editable may be un-creatable, and vice versa. (`:78,150`)
- `_reversa_sdd/customers-crud/design.md:129` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`update` `gender` lacks `nullable`** — an empty `gender` string fails the `in` rule on edit. (`:153`)
- `_reversa_sdd/customers-crud/design.md:130` (unit:customers-crud) — unresolved confidence marker: - 🟡 **Silent `birthday` drop on parse failure** — invalid dates are nulled with no user feedback. (`:86-90`)
- `_reversa_sdd/customers-crud/design.md:131` (unit:customers-crud) — unresolved confidence marker: - 🟡 **No per-record authorization** — any authenticated admin can edit/delete any customer (`permissions.md`). (`routes/web.php:24-28`)
- `_reversa_sdd/customers-crud/requirements.md:27` (unit:customers-crud) — unresolved confidence marker: - **`birthday` is a display string; `birthday2` is the parsed date.** `birthday` is validated against the regex `d/m/yyyy` and stored as typed; `store` parses i
- `_reversa_sdd/customers-crud/requirements.md:28` (unit:customers-crud) — unresolved confidence marker: - **`update` does not recompute `birthday2`.** Only `store` derives `birthday2`; editing `birthday` on `update` leaves `birthday2` stale unless it is submitted 
- `_reversa_sdd/customers-crud/requirements.md:54` (unit:customers-crud) — unresolved confidence marker: | Performance | Listing is bounded by `paginate(30)`; `phone` and `fullname` are indexed, but the `fullname LIKE %q%` leading wildcard cannot use the index | `C
- `_reversa_sdd/customers-crud/requirements.md:112` (unit:customers-crud) — unresolved confidence marker: ## Identified Gaps (🔴 / 🟡)
- `_reversa_sdd/customers-crud/requirements.md:115` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`update` does not recompute `birthday2` from `birthday`.** Editing the display `birthday` on `update` leaves the stored `birthday2` date stale (the month 
- `_reversa_sdd/customers-crud/requirements.md:117` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`phone` validation is inconsistent between create and update.** `store` uses `numeric`, `update` uses `string`; a value accepted on edit could be rejected
- `_reversa_sdd/customers-crud/requirements.md:118` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`update` `gender` rule lacks `nullable`.** It is `string|in:male,female,other` (no `nullable`), so submitting an empty `gender` string fails validation, t
- `_reversa_sdd/customers-crud/requirements.md:119` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`store` parse-failure silently nulls `birthday`.** On a `birthday` that `Carbon` cannot parse, the catch sets `birthday = null` (and `birthday2` is never 
- `_reversa_sdd/customers-crud/requirements.md:120` (unit:customers-crud) — unresolved confidence marker: - 🟡 **`create` breadcrumb label is mislabeled.** The parent crumb reads `__("Sản phẩm")` ("Product") instead of "Customer" — a copy-paste artifact, cosmetic onl
- `_reversa_sdd/customers-crud/tasks.md:54` (unit:customers-crud) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/customers-crud/tasks.md:74` (unit:customers-crud) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/customers-crud/tasks.md:107` (unit:customers-crud) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/customers-debt-actions/contracts.md:117` (unit:customers-debt-actions) — unresolved confidence marker: - **Idempotency:** the writes are **not** idempotent — each successful POST appends a new ledger entry and shifts the balance; there is no client-supplied dedup
- `_reversa_sdd/customers-debt-actions/contracts.md:119` (unit:customers-debt-actions) — unresolved confidence marker: - **Validation floor vs storage:** `amount ≥ 0.01` but `decimal(15,1)` storage rounds sub-0.1 values — a legal input can record a `0.0` entry. 🟡 (`:382,404`, `m
- `_reversa_sdd/customers-debt-actions/contracts.md:122` (unit:customers-debt-actions) — unresolved confidence marker: - **No observability:** none of the three routes emit telemetry; the only audit is the persisted `balance_after` + `created_by` on each row. 🔴 (`:263-425`, abse
- `_reversa_sdd/customers-debt-actions/design.md:95` (unit:customers-debt-actions) — unresolved confidence marker: | Provenance via a bare `created_by` integer (admin id), no FK to `admin_users` | `migration:20`, `:394,417` | 🟡 |
- `_reversa_sdd/customers-debt-actions/design.md:104` (unit:customers-debt-actions) — unresolved confidence marker: None. Neither the ledger page nor the two balance-mutating writes emit any log, metric, or trace. A rejected repayment, a successful manual debt, and a failed t
- `_reversa_sdd/customers-debt-actions/design.md:108` (unit:customers-debt-actions) — unresolved confidence marker: - 🟡 **`amount` floor vs storage precision.** Validation allows `amount ≥ 0.01`, but `customer_debts.amount` and `balance_after` are `decimal(15,1)` (one decimal
- `_reversa_sdd/customers-debt-actions/design.md:111` (unit:customers-debt-actions) — unresolved confidence marker: - 🟡 **Manual debt has no upper bound.** `manual_debt` only validates `min:0.01`; a mistyped large amount inflates the balance with no confirmation step (only a 
- `_reversa_sdd/customers-debt-actions/design.md:112` (unit:customers-debt-actions) — unresolved confidence marker: - 🔴 **No observability** on a money-mutating path — no audit log beyond the ledger row itself, no alerting on rejected repayments or transaction failures.
- `_reversa_sdd/customers-debt-actions/requirements.md:28` (unit:customers-debt-actions) — unresolved confidence marker: - **The acting admin is captured as `created_by`.** Both writes pass `Admin::user() ? Admin::user()->id : null` for provenance; the column is a plain `unsignedI
- `_reversa_sdd/customers-debt-actions/requirements.md:56` (unit:customers-debt-actions) — unresolved confidence marker: | Observability | None — no log/metric/trace on either the read page or the two balance-mutating writes | `CustomerController.php:263-425` (absence) | 🔴 |
- `_reversa_sdd/customers-debt-actions/tasks.md:74` (unit:customers-debt-actions) — unresolved confidence marker: - [ ] TM-01, Preserve existing `customer_debts` rows and each customer's `debt_total` exactly on reimplementation — the balance is denormalised and must stay eq
- `_reversa_sdd/customers-debt-actions/tasks.md:83` (unit:customers-debt-actions) — unresolved confidence marker: ## Lacunas Pendentes (🔴)
- `_reversa_sdd/customers-debt-actions/tasks.md:85` (unit:customers-debt-actions) — unresolved confidence marker: - 🟡 **Amount minimum vs decimal(15,1) precision** (T-04/T-05/T-06) — `min:0.01` admits sub-0.1 amounts that round to `0.0` on storage; confirm the intended mone
- `_reversa_sdd/customers-debt-actions/tasks.md:86` (unit:customers-debt-actions) — unresolved confidence marker: - 🟡 **Manual debt has no upper bound / no confirmation** (T-05) — a mistyped large `manual_debt` inflates the balance irreversibly except via a repayment/`debt_
- `_reversa_sdd/customers-debt-actions/tasks.md:87` (unit:customers-debt-actions) — unresolved confidence marker: - 🟡 **`created_by` is an unconstrained integer** (T-05/T-06) — no FK to `admin_users`; decide whether to constrain it or accept the loose audit link.
- `_reversa_sdd/customers-debt-actions/tasks.md:89` (unit:customers-debt-actions) — unresolved confidence marker: - 🔴 **Observability absent** — no logging/metrics/audit beyond the ledger row on a money-mutating path; decide whether to add an audit log and alerting on rejec
- `_reversa_sdd/customers-loyalty/contracts.md:40` (unit:customers-loyalty) — unresolved confidence marker: - **Auth:** required; anonymous → `302 auth/login`. **CSRF:** required (web `Form::open` token). 🟡 (`customer-statis.blade.php`)
- `_reversa_sdd/customers-loyalty/contracts.md:60` (unit:customers-loyalty) — unresolved confidence marker: - **Idempotency:** **not** idempotent — each successful POST appends a pivot row and shifts `points`/`used`; no client dedup key. 🟡
- `_reversa_sdd/customers-loyalty/contracts.md:109` (unit:customers-loyalty) — unresolved confidence marker: | **Consumer** | `gifts-scan` | the redemption UI's gift picker uses `settings/gifts/scan`; `gift_id` fed here comes from that lookup. 🟡 |
- `_reversa_sdd/customers-loyalty/contracts.md:122` (unit:customers-loyalty) — unresolved confidence marker: - **No observability:** none of the three routes emit telemetry; rolled-back redemptions and the two 🔴 failure modes are invisible to operations. 🔴 (`:296-377`,
- `_reversa_sdd/customers-loyalty/design.md:88` (unit:customers-loyalty) — unresolved confidence marker: | Out-of-stock test is strict `=== 0` on the computed `quantity_available` (a negative available slips through). | `Customer.php:66`, `Gift.php:25-27` | 🟡 |
- `_reversa_sdd/customers-loyalty/design.md:100` (unit:customers-loyalty) — unresolved confidence marker: None. No log lines, metrics, or audit events are emitted by any of the three actions; a rolled-back redemption, a rejected availability check, and the `check-gi
- `_reversa_sdd/customers-loyalty/design.md:107` (unit:customers-loyalty) — unresolved confidence marker: - 🟡 **Out-of-stock uses strict `=== 0`** — a gift whose `used` exceeds `quantity` (negative `quantity_available`) is not caught by `checkGiftAvailable`; confirm
- `_reversa_sdd/customers-loyalty/design.md:108` (unit:customers-loyalty) — unresolved confidence marker: - 🟡 **`check-gift` gate can drift from the redeem outcome** — advisory only; a `true` verdict can still be rejected at redemption if stock/points change in betw
- `_reversa_sdd/customers-loyalty/design.md:110` (unit:customers-loyalty) — unresolved confidence marker: - 🟡 **Pivot has no `withTimestamps()`** — `customer_gift.created_at/updated_at` are not maintained by `attach`; the received-list view shows the *gift's* `creat
- `_reversa_sdd/customers-loyalty/requirements.md:51` (unit:customers-loyalty) — unresolved confidence marker: | Security | `redeem-points` is a CSRF-protected web `POST` (`Form::open` token); `check-gift`/`gift-received` are `GET`. | `customer-statis.blade.php`, `:296` 
- `_reversa_sdd/customers-loyalty/requirements.md:54` (unit:customers-loyalty) — unresolved confidence marker: | Observability | No logging/metrics on any of the three routes; a rolled-back redemption or a rejected availability check leaves no trace beyond the flashed me
- `_reversa_sdd/customers-loyalty/tasks.md:79` (unit:customers-loyalty) — unresolved confidence marker: 4. Apply the T-06 and T-07 fixes only after confirming the 🔴 gaps with the team.
- `_reversa_sdd/customers-loyalty/tasks.md:81` (unit:customers-loyalty) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/customers-purchase-history/contracts.md:76` (unit:customers-purchase-history) — unresolved confidence marker: - **No observability:** the page emits no telemetry. 🔴 (`:192-213`, absence)
- `_reversa_sdd/customers-purchase-history/design.md:68` (unit:customers-purchase-history) — unresolved confidence marker: None. The action emits no logs, metrics, or traces. The category filter and lifetime total run additional queries per request with no timing or count instrument
- `_reversa_sdd/customers-purchase-history/design.md:74` (unit:customers-purchase-history) — unresolved confidence marker: - 🟡 **Per-row `debt_locked` N+1.** Each rendered order's appended `debt_locked` runs `debts()->where('type','pos_debt')->exists()` — up to 20 extra queries per 
- `_reversa_sdd/customers-purchase-history/design.md:76` (unit:customers-purchase-history) — unresolved confidence marker: - 🔴 **No observability** on a report that runs a `whereHas` `EXISTS` and an aggregate per request.
- `_reversa_sdd/customers-purchase-history/requirements.md:50` (unit:customers-purchase-history) — unresolved confidence marker: | Performance | Category filter uses an `EXISTS` subquery over `order_product`/`products`; benefits from indexes on `order_product.product_id` and `products.cat
- `_reversa_sdd/customers-purchase-history/requirements.md:51` (unit:customers-purchase-history) — unresolved confidence marker: | Performance | Rendering each order's appended `debt_locked` runs a `debts()->exists()` query per row → up to 20 extra queries per page if the view reads it | 
- `_reversa_sdd/customers-purchase-history/requirements.md:52` (unit:customers-purchase-history) — unresolved confidence marker: | Observability | None — the action emits no log, metric, or trace | `CustomerController.php:192-213` (absence) | 🔴 |
- `_reversa_sdd/customers-purchase-history/tasks.md:14` (unit:customers-purchase-history) — unresolved confidence marker: - [ ] A `pages.customer-orders` view exists to render `item`, `amountTotal`, `orders`, `categories`. 🟡
- `_reversa_sdd/customers-purchase-history/tasks.md:89` (unit:customers-purchase-history) — unresolved confidence marker: ## Lacunas Pendentes (🔴)
- `_reversa_sdd/customers-purchase-history/tasks.md:91` (unit:customers-purchase-history) — unresolved confidence marker: - 🔴 **Observability absent** — no logging/metrics on a screen that runs a `whereHas` `EXISTS` plus an aggregate per request; decide whether to add instrumentati
- `_reversa_sdd/customers-purchase-history/tasks.md:94` (unit:customers-purchase-history) — unresolved confidence marker: - 🟡 **Per-row `debt_locked` N+1** — if the view renders `debt_locked` per order, decide whether to eager-load/precompute to avoid ~20 queries/page.
- `_reversa_sdd/customers-scan/contracts.md:21` (unit:customers-scan) — unresolved confidence marker: | `q` | string | ❌ | Search token. Matched as `phone LIKE %q%` **OR** `fullname LIKE %q%` (both substring). Bound as a parameter (no injection), but `%`/`_` in 
- `_reversa_sdd/customers-scan/contracts.md:84` (unit:customers-scan) — unresolved confidence marker: - **No observability:** the endpoint emits no telemetry despite per-keystroke traffic. 🔴 (`:283-294`, absence)
- `_reversa_sdd/customers-scan/design.md:35` (unit:customers-scan) — unresolved confidence marker: - **Missing / empty `q`:** the pattern becomes `LIKE '%%'`, which matches every live row; the endpoint returns the first 10 customers in default order. Whether 
- `_reversa_sdd/customers-scan/design.md:36` (unit:customers-scan) — unresolved confidence marker: - **`q` contains `%` or `_`:** these are interpreted as `LIKE` wildcards, not literals. Bound as a parameter, so there is no SQL-injection risk, but the match s
- `_reversa_sdd/customers-scan/design.md:62` (unit:customers-scan) — unresolved confidence marker: None. The action emits no logs, metrics, or traces, even though the POS client calls it on every keystroke of the customer search box. Adding at least a debug-l
- `_reversa_sdd/customers-scan/design.md:66` (unit:customers-scan) — unresolved confidence marker: - 🔴 **Empty-`q` behavior is incidental.** A blank/missing `q` returns the first 10 customers rather than `[]`; confirm whether the client ever sends an empty qu
- `_reversa_sdd/customers-scan/design.md:68` (unit:customers-scan) — unresolved confidence marker: - 🟡 **Leading-wildcard `LIKE`** on `phone`/`fullname` cannot use an index; per-keystroke calls do a full scan and degrade as the customer base grows.
- `_reversa_sdd/customers-scan/design.md:69` (unit:customers-scan) — unresolved confidence marker: - 🟡 **User `%`/`_` widen the match.** Bound-parameter safe (no injection) but semantically surprising; escape them if literal matching is desired.
- `_reversa_sdd/customers-scan/design.md:70` (unit:customers-scan) — unresolved confidence marker: - 🟡 **Identity key assumption.** The POS client keys the selected customer by `phone`; confirm no two live customers can share a phone (the live-only unique ind
- `_reversa_sdd/customers-scan/requirements.md:25` (unit:customers-scan) — unresolved confidence marker: - **`q` is used as an SQL `LIKE` pattern.** The value is bound as a parameter (no SQL injection), but user-typed `%` and `_` act as `LIKE` wildcards rather than
- `_reversa_sdd/customers-scan/requirements.md:44` (unit:customers-scan) — unresolved confidence marker: | Performance | Leading-wildcard `LIKE %q%` on `phone`/`fullname` cannot use a B-tree index → full scan that degrades as the customer table grows | `CustomerCon
- `_reversa_sdd/customers-scan/requirements.md:45` (unit:customers-scan) — unresolved confidence marker: | Observability | None — the action emits no log, metric, or trace despite being called on every keystroke | `CustomerController.php:283-294` (absence) | 🔴 |
- `_reversa_sdd/customers-scan/tasks.md:57` (unit:customers-scan) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/customers-scan/tasks.md:62` (unit:customers-scan) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/customers-scan/tasks.md:86` (unit:customers-scan) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/customers-statistics/contracts.md:85` (unit:customers-statistics) — unresolved confidence marker: - 🔴 No response signal distinguishes "summary not yet computed" from "genuinely zero" — a consumer/observer cannot tell a broken nightly job from a new customer
- `_reversa_sdd/customers-statistics/design.md:123` (unit:customers-statistics) — unresolved confidence marker: None. The action emits no logs, metrics, or traces. A missing summary row and a stale/failed nightly rebuild are both invisible from this screen — the only in-p
- `_reversa_sdd/customers-statistics/design.md:129` (unit:customers-statistics) — unresolved confidence marker: - 🟡 **Staleness window up to ~24 h.** Numbers reflect the last `->daily()` run, not the current moment; acceptable for a "statistics" view but must be communica
- `_reversa_sdd/customers-statistics/requirements.md:60` (unit:customers-statistics) — unresolved confidence marker: | Observability | No logging/metrics on this read path; a failed/absent nightly rebuild is invisible here | `CustomerController.php:215-261` (no logger calls) |
- `_reversa_sdd/customers-statistics/tasks.md:77` (unit:customers-statistics) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/customers-statistics/tasks.md:102` (unit:customers-statistics) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/customers-statistics/tasks.md:104` (unit:customers-statistics) — unresolved confidence marker: - 🔴 Decide whether "summary not yet computed" (`summary === null`) should be visually distinct from a genuine all-zero customer, so a broken nightly rebuild is 
- `_reversa_sdd/dashboard/contracts.md:56` (unit:dashboard) — unresolved confidence marker: - **Content type:** `text/html` (or a `3xx` redirect); there is **no JSON contract**. A modernized API exposing this data would need to define its own response 
- `_reversa_sdd/dashboard/design.md:91` (unit:dashboard) — unresolved confidence marker: - 🔴 No slow-query instrumentation despite the non-SARGable `DATE(created_at)=CURDATE()` KPI and full-table chart scans — a reimplementation should add timing/me
- `_reversa_sdd/dashboard/design.md:98` (unit:dashboard) — unresolved confidence marker: - 🟡 **Chart semantics are order counts.** Stakeholders may expect revenue or units sold; confirm the chart's intended metric before re-labelling. (`:102`)
- `_reversa_sdd/dashboard/tasks.md:97` (unit:dashboard) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/dashboard/tasks.md:101` (unit:dashboard) — unresolved confidence marker: - 🟡 **Month-boundary spillover (T-06, not yet fixed).** For a non-6-multiple month length, the last window can spill a few days into the next calendar month (e.
- `_reversa_sdd/dashboard/tasks.md:102` (unit:dashboard) — unresolved confidence marker: - 🔴 **Chart metric confirmation.** Confirm whether the sales chart should remain an order **count** or become revenue / units sold before porting (see `design.m
- `_reversa_sdd/dashboard/tasks.md:103` (unit:dashboard) — unresolved confidence marker: - 🔴 **Dashboard latency at scale.** No cache and a non-SARGable today-KPI predicate; confirm acceptable load time / whether caching or precomputation is needed 
- `_reversa_sdd/debts/contracts.md:64` (unit:debts) — unresolved confidence marker: - **Picker breadth:** the modal picker is not restricted to debtors; a repayment for a non-debtor is rejected by `storeRepayment` downstream (over-balance throw
- `_reversa_sdd/debts/contracts.md:66` (unit:debts) — unresolved confidence marker: - **No observability:** the page emits no telemetry. 🔴 (`:10-29`, absence)
- `_reversa_sdd/debts/design.md:42` (unit:debts) — unresolved confidence marker: - **Out-of-range `page`:** Laravel's paginator returns an empty result set for a page beyond the last; the empty-state row renders. 🟡 (standard paginator behavi
- `_reversa_sdd/debts/design.md:68` (unit:debts) — unresolved confidence marker: None. The action emits no log, metric, or trace; a slow or empty debtor list produces no signal. 🔴 (`DebtController.php:10-29`, absence)
- `_reversa_sdd/debts/design.md:72` (unit:debts) — unresolved confidence marker: - 🟡 **Un-indexable search.** `phone LIKE '%q%'` / `fullname LIKE '%q%'` use a leading wildcard, so no index applies; the search does a full scan and degrades as
- `_reversa_sdd/debts/design.md:73` (unit:debts) — unresolved confidence marker: - 🟡 **LIKE metacharacter leak.** A user-typed `%` or `_` in `q` is interpreted as a LIKE wildcard (not escaped). Values are parameter-bound, so there is no SQL 
- `_reversa_sdd/debts/design.md:74` (unit:debts) — unresolved confidence marker: - 🟡 **Picker not scoped to debtors.** The modal select2 sources any live customer from `/customers/scan`; a repayment started for a non-debtor is rejected downs
- `_reversa_sdd/debts/design.md:76` (unit:debts) — unresolved confidence marker: - 🔴 **No observability** on a screen that surfaces money owed (see above).
- `_reversa_sdd/debts/requirements.md:29` (unit:debts) — unresolved confidence marker: - **The customer picker is not restricted to debtors.** The modals fetch candidates from `GET /customers/scan` (any live customer, min 3 chars), so a repayment 
- `_reversa_sdd/debts/requirements.md:49` (unit:debts) — unresolved confidence marker: | Performance | Leading-wildcard `LIKE '%q%'` on `phone`/`fullname` cannot use a column index → full scan that degrades as the customer base grows | `DebtContro
- `_reversa_sdd/debts/requirements.md:50` (unit:debts) — unresolved confidence marker: | Observability | None — the action emits no log, metric, or trace | `DebtController.php:10-29` (absence) | 🔴 |
- `_reversa_sdd/debts/tasks.md:57` (unit:debts) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/debts/tasks.md:78` (unit:debts) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/gifts-crud/contracts.md:21` (unit:gifts-crud) — unresolved confidence marker: | GET | `settings/gifts/{id}` (show) · GET `settings/gifts/create` | Framework defaults | Not surfaced in the UI (no create button; creation via inline widget).
- `_reversa_sdd/gifts-crud/contracts.md:81` (unit:gifts-crud) — unresolved confidence marker: - **Stock semantics:** `quantity` = stock, `used` = redeemed, `quantity_available` = derived; the out-of-stock decision (strict `=== 0`) is made by the redempti
- `_reversa_sdd/gifts-crud/contracts.md:83` (unit:gifts-crud) — unresolved confidence marker: - **No observability:** gift mutations and image resizing emit no telemetry. 🔴 (`GiftController.php`, absence)
- `_reversa_sdd/gifts-crud/design.md:44` (unit:gifts-crud) — unresolved confidence marker: - **Unknown id on edit/update/delete:** framework `findOrFail` → `404`. 🟡 (`ModelForm` default)
- `_reversa_sdd/gifts-crud/design.md:67` (unit:gifts-crud) — unresolved confidence marker: | Unpaginated/unfiltered grid (small catalogue assumption) | `disableFilter()`, `disablePagination()` | 🟡 (`:70-71`) |
- `_reversa_sdd/gifts-crud/design.md:75` (unit:gifts-crud) — unresolved confidence marker: None. The scaffolded CRUD and the image-resize hook emit no domain-level log/metric/trace. 🔴 (`GiftController.php`, absence)
- `_reversa_sdd/gifts-crud/design.md:79` (unit:gifts-crud) — unresolved confidence marker: - 🟡 **Inline create widget vs `form()` divergence.** The inline `Widgets\Form` declares `points`/`limit`/`quantity` as `text()` with no rules and `active` defau
- `_reversa_sdd/gifts-crud/design.md:80` (unit:gifts-crud) — unresolved confidence marker: - 🟡 **Image path coupling.** The `saved` hook reads `storage_path('app/public/'.$form->model()->getOriginal('image'))`; it assumes the raw stored path and the `
- `_reversa_sdd/gifts-crud/design.md:81` (unit:gifts-crud) — unresolved confidence marker: - 🟡 **Out-of-stock uses strict `=== 0`** (in the consuming redemption gate) so a negative `quantity_available` would slip through; this unit does not clamp `use
- `_reversa_sdd/gifts-crud/design.md:83` (unit:gifts-crud) — unresolved confidence marker: - 🔴 **No observability** on gift mutations or the image-resize step (see above).
- `_reversa_sdd/gifts-crud/requirements.md:31` (unit:gifts-crud) — unresolved confidence marker: - **`quantity_available = quantity − used`** is a computed, appended attribute (never stored). The out-of-stock test (strict `=== 0`) lives in the redemption ga
- `_reversa_sdd/gifts-crud/requirements.md:57` (unit:gifts-crud) — unresolved confidence marker: | Integrity | Soft delete preserves redemption history (`customer_gift` pivot rows) even after a gift is removed | `Gift.php:10-14` | 🟡 |
- `_reversa_sdd/gifts-crud/requirements.md:59` (unit:gifts-crud) — unresolved confidence marker: | Usability | Unpaginated single-screen grid — assumes a small gift catalogue | `GiftController.php:67-71` | 🟡 |
- `_reversa_sdd/gifts-crud/requirements.md:60` (unit:gifts-crud) — unresolved confidence marker: | Observability | None — framework CRUD emits no domain log/metric | `GiftController.php` (absence) | 🔴 |
- `_reversa_sdd/gifts-crud/tasks.md:69` (unit:gifts-crud) — unresolved confidence marker: - Confidence: 🔴
- `_reversa_sdd/gifts-crud/tasks.md:74` (unit:gifts-crud) — unresolved confidence marker: - Confidence: 🟡
- `_reversa_sdd/gifts-crud/tasks.md:97` (unit:gifts-crud) — unresolved confidence marker: ## Pending Gaps (🔴)
- `_reversa_sdd/gifts-scan/contracts.md:20` (unit:gifts-scan) — unresolved confidence marker: | Errors | No explicit error branch; invalid input is ignored (no validation) 🟡 |
- `_reversa_sdd/gifts-scan/contracts.md:26` (unit:gifts-scan) — unresolved confidence marker: | `q` | string | ❌ | Substring matched as `name LIKE %q%`; no validation/default. Empty/missing → `LIKE '%%'` (returns first 10). 🔴 (`:117-118`) |
- `_reversa_sdd/gifts-scan/contracts.md:54` (unit:gifts-scan) — unresolved confidence marker: - Envelope shape is `{data:[…]}` — **different** from `customers-scan` (bare array) and `pos-scan` (`{is_barcode, data}` union). Consumers must read `.data`. 🟡
- `_reversa_sdd/gifts-scan/contracts.md:84` (unit:gifts-scan) — unresolved confidence marker: - **No observability:** the lookup emits no telemetry. 🔴 (`GiftController.php:115-126`, absence)
- `_reversa_sdd/gifts-scan/design.md:43` (unit:gifts-scan) — unresolved confidence marker: - **Empty / missing `q`:** `LIKE '%%'` matches everything → the first 10 live gifts are returned (not `[]`). Contract for the empty query is incidental, unconfi

_… 146 more_

