# Scheduling port — integration verification

**Status: lean-core implementation and local acceptance complete, verified 2026-09-07.** Current targeted independent reviews pass; all 11 real-API/browser cases pass together on unchanged source. The baseline-aware regression gate has no new failing test identities or PHPStan diagnostics. This is not a production-readiness or bug-free attestation: production database concurrency remains unverified and external Typesense tests remain baseline-red. Both repositories contain uncommitted work. No commit, push, deployment, or production database reset was performed.

## Scope and authority

- API: `alqove-api`, base `64643511ee99f3e51048aaf41a1329f25e833d54`.
- Web: `alqove-web`, base `8e831d8477889035395002efcc3af8e6e41d996a`.
- Intent: Port 00 selected-store/staff prerequisites and Port 01 lean core, Phases 0–4.
- BuyerKiosk source was read-only. See the Scheduling/Payroll module READMEs for preserved algorithms, intentional safety changes, and source-checkout differences.
- Deferred: availability, swaps/offers/time off, claiming, templates/recurrence, policy-driven breaks, kiosk/geofencing, AI scheduling, realtime/push, statutory holidays, and external payroll submission.

## Final executed verification

These results include the final recipient-email authorization remediation. Machine-readable evidence is retained in [regression comparison](scheduling-api-regression.json), [browser verification](scheduling-browser-verification.json), and [current independent remediation reviews](scheduling-remediation-reviews.json).

| Check | Result / scope |
|---|---|
| API Team + Scheduling + Payroll | 206 passed, 0 failed/skipped, 1,425 JUnit assertions, extracted from the final full-suite run. `/tmp/alqove-api-post-recipient.xml`. |
| Full API repository regression | 1,938 total: 1,898 passed, 23 errors + 7 failures, 10 skipped. The exact 30 failing identities match the isolated Typesense baseline; no newly failing identity. Exit 2, not a whole-repository green claim. |
| Full Web test suite | 740 passed, 1 skipped, 0 failed across 134 files. `/tmp/alqove-web-current-tests.json`. Other workspaces define no test script. |
| Pay-rate append integration | Observed RED on approved-history mutation and missing pending recalculation; subsequent focused Team run passed 7 tests / 21 assertions. Guard and recalculation execute inside the append transaction through a Team event and Payroll listener. |
| Contract merge | Three fragments merged into canonical API contract, copied to Web, generated TypeScript successfully. All 27 new HTTP operations matched actual Laravel routes and expected capability/membership middleware. |
| Web static types | Web `tsc --noEmit` and all workspace typechecks passed. |
| Production Web build | `npm run build:web` exited 0, including all new seller/staff routes. The supplied `ALQOVE_NEXT_DIST_DIR` variable is not consumed by current Next config; no custom build-directory isolation is claimed. Metadata-base warnings remain. |
| Full Web lint | `npm run lint` exited 0: 0 errors, 9 image-optimization warnings. `/tmp/alqove-web-current-lint.log`. |
| Changed API formatting | Pint `--test` passed all 102 changed/new PHP files. Only EventServiceProvider import formatting needed parent correction; its pay-rate/shift regression passed 14 tests / 143 assertions. |
| Full PHPStan baseline comparison | 928 diagnostics versus baseline 930; zero new relative-file + identifier + message entries. Whole analyzer still exits 1 for existing diagnostics. |
| Harness safety | Eight Python tests passed after adding configuration/contract freshness checks. Standalone harness TypeScript check passed. |
| Real API / Chromium E2E | Unfiltered `python3 e2e-scheduling-real/run.py`: all 11 passed, no skip/retry/flaky result, exit 0; 39.7 seconds. Source hashes unchanged and exact private cleanup independently read back. |
| Independent current frontend remediation gate | PASS; 72 focused tests plus 14 supplemental lifecycle controls. Original exported-editor and same-credential invitation reproductions pass. Parent checked current hashes of the six inspected source files. |
| Independent current API remediation gate | PASS; 86 targeted tests / 729 assertions. Recipient race and previous migration/payroll findings closed within tested scope; all 187 bound files matched on parent readback. |

## Baseline-aware regression

The initial widespread SQLite nested-transaction failures originated in an unavailable PhpRedis extension: a Redis call prevented the usual test teardown rollback. No application transaction workaround or Composer platform bypass was applied.

For broad regression, PhpRedis 6.3.0 was compiled under `/tmp/alqove-scheduling-phpredis-build` and loaded only into the test process. A separate empty Redis instance on `127.0.0.1:6385` kept `flushdb` tests away from existing local Redis data. Installed dependencies require PHP >=8.4; the verified executable is `/opt/homebrew/bin/php` (8.5).

The owned test Redis process was stopped after final regression. Independent final socket checks found no listeners on the owned test ports 6385, 8105 or 3100; the final source fingerprint still matched browser evidence after documentation updates.

The final full API run has 30 failures/errors related to unavailable Typesense. The affected cases previously run against an isolated HEAD archive reproduce exactly the same 30 test identities; the post-recipient run introduces none. Evidence: `/tmp/alqove-api-post-recipient.xml`, `/tmp/alqove-typesense-baseline.xml`, and the JSON comparison linked above. This is a classified baseline limitation, **not a claim that the entire repository suite passed**. Console assertion count is 6,779; JUnit reports 6,774. Both are retained separately rather than silently conflated.

PHPStan baseline contains 930 diagnostics, current 928. Comparison uses relative file + diagnostic identifier + message, ignoring shifted line numbers. Final comparison has no new entries; reports are `/tmp/alqove-store-scope-baseline-stan.json` and `/tmp/alqove-post-recipient-stan.json`.

## Review and remediation ledger

| Finding | Disposition / final verification |
|---|---|
| Invitation acceptance could race revocation/supersession | Parent-first transactional locks and current invitation/authority checks; current targeted API gate passes. |
| Acceptance used stale authenticated recipient email | Current recipient is reread under a user-row lock; changed unbound email and soft/hard deleted users reject without membership, acceptance or audit side effects. Bound account-ID behavior remains valid after email change. Seven new regression cases; current independent gate passes. |
| Queued commands survived same-user credential replacement or A→B→A | Monotonic command generations, immutable originating context, delayed-autosave cleanup, and provider teardown have passing deterministic regressions. Original queued scheduling reproduction dispatches zero stale requests. |
| Invitation continuation revived after identical-session replacement | Immutable authentication epoch guards acceptance, membership-discovery continuation and accepted-state retry without confusing store discovery with reauthentication. Current independent gate and real invitation browser flows pass. |
| Retained correction form remained active after export | Add/edit/delete forms hide for nonpending status; immediate dispatch checks exact current detail cache. Approved/exported/missing-cache transitions dispatch zero corrections. Current independent gate and legitimate browser correction/export flow pass. |
| Staff Schedule/Clock had no QueryClientProvider | Generation-keyed staff provider and real-hook regression added; both routes pass the final unfiltered browser run. |
| Interrupted multi-table/column migrations could not resume | Data-preserving restart and fail-closed malformed-schema checks; 39 restart cases pass under independent replay. See scheduling-migration-recovery.md. No destructive rollback is authorized as recovery. |
| Approving an obsolete week ID could approve a different row | HTTP 409 before recalculation, no silent retargeting or approval/audit side effects. Current independent gate passes. |
| Empty daily breakdown serialized as array instead of contract object | Real HTTP empty breakdown is `{}` while internal storage remains `[]`; populated manager response retains money omission. Current independent gate passes. |

## Browser evidence and isolation

Reproducible harness: `alqove-web/e2e-scheduling-real/`. Run from the Web repository:

```sh
python3 -m unittest discover -s e2e-scheduling-real -p test_isolation.py -v
npx tsc --noEmit --skipLibCheck --moduleResolution bundler --module esnext --target es2022 --allowImportingTsExtensions --esModuleInterop e2e-scheduling-real/*.ts
python3 e2e-scheduling-real/run.py
```

Runs use a unique `E2E-*` marker, synthetic `@example.test` accounts, private SQLite and credentials, explicit process environments without production service credentials, and owned local API/Next processes. Cleanup checks the exact marker and fixture identity/cardinality before removing only the private database/credential files. Traces can contain synthetic credentials and remain private, never committed.

Final evidence is `.cache/scheduling-qa/E2E-aefca6b2495572a7/` in the Web repository: `results.json`, authoritative API/SQL readbacks, `cleanup.json`, matching start/end source/configuration hashes, and no leftover owned listeners. Parent independently enumerated all 11 unique cases, verified single passed attempts, absent private files and closed ports 8105/3100. Source SHA256 is `07cd190233d13e5afc75eb797c4f381865a2cd5a1137273c8b64aaf72817866e`. Earlier source-changing passes remain historical/provisional and are superseded, not combined with this run.

## Remaining verification boundaries

Production MySQL/PostgreSQL concurrency and deployment are not exercised by the local SQLite suite. The two-process shift-assignment race is real SQLite evidence, not proof about other database engines. External Typesense integration remains baseline-red locally. No external payroll provider submission is part of this port.

Specifically, SQLite transaction-hook tests do not establish production `FOR UPDATE` blocking, cross-domain deadlock freedom, foreign-key-cascade lock ordering or contention liveness. Migration tests do not certify arbitrary out-of-band type/default corruption or production-engine partial DDL behavior. These are explicit deployment-validation boundaries, not waived by the local acceptance result.

The frontend reviewer suggested retaining its additional stale-rejection and in-flight-retry probes as repository tests; those probes passed and the suggestion is nonblocking. The live HTML overview write timed out; this Markdown audit and its JSON evidence are the verified status artifacts. Tests cannot prove bug-free software.
