From 50c8d5c64d0f766b745fea51a7f3e8d40285dde9 Mon Sep 17 00:00:00 2001 From: lorentz Date: Sat, 11 Jul 2026 11:06:31 -0400 Subject: [PATCH] docs(13-03): record partial live-verification results for Phase 13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirms SC#1, and the scheduler halves of SC#3/SC#4 via direct DB/log access. Also documents the stale-Docker-image root cause found during testing (image predated all PAX8 code; rebuilt and redeployed) and the incidental fix needed to unblock the build. SC#2 and the manual-route halves of SC#3/SC#4 still need a human with an authenticated browser session — not bypassed via forged auth. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LHRgZqkzBHBbAbc3KHneuR --- .../13-03-SUMMARY.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .planning/phases/13-scheduler-admin-toggle/13-03-SUMMARY.md diff --git a/.planning/phases/13-scheduler-admin-toggle/13-03-SUMMARY.md b/.planning/phases/13-scheduler-admin-toggle/13-03-SUMMARY.md new file mode 100644 index 0000000..cf263f9 --- /dev/null +++ b/.planning/phases/13-scheduler-admin-toggle/13-03-SUMMARY.md @@ -0,0 +1,96 @@ +--- +phase: 13-scheduler-admin-toggle +plan: 03 +type: execute +status: partial +--- + +## What this plan verified + +Live verification of Phase 13's four success criteria against the running app. No code +changes — this plan proves behavior, it doesn't implement it. + +## Pre-existing blocker found and fixed (out of this plan's scope, but required to test anything) + +The running `pulse-app` Docker image was built **2026-05-21** — before any PAX8 code +existed. `docker restart` / `docker compose up -d app` only restart a container from the +existing image; neither re-runs `npm run build`. As a result, every live test against the +stale image exercised code that predated the `pax8-daily` branch entirely, and an +unrecognized `sync_type` fell through to the scheduler's generic `else` branch +(`this.syncService.fullSync('scheduled', ...)`), which re-synced the *entire* Autotask +entity set (companies, contacts, resources, tickets, ticket_notes — 767,500+ ticket notes +fetched before it was stopped). This was **not** a bug in Phase 13's code; the new code was +never running. + +Fix: rebuilt the image (`docker compose build app`) and redeployed +(`docker compose up -d app`). The rebuild was blocked by a pre-existing, unrelated, +uncommitted script (`scripts/diagnose-ticket-varchar-overflow.ts`) with a TS7022 circular- +type-inference error on an untyped `fetch()` result — Next.js's build runs a full +repo-wide typecheck. Added an explicit `: Response` annotation (2-line fix, no logic +change) to unblock the build. This fix is **not committed** — the script itself is +untracked/WIP and out of Phase 13's scope; only the type annotation was touched to get a +green build. + +After rebuilding, the scheduler dispatch and disable/enable logic were re-tested against +the actual current code and behaved as designed (see below). + +## Automated verification (via direct DB/log access — no browser session available) + +**SC#1 — pax8-daily is scheduled and fires: CONFIRMED** +- Enabled the schedule with a near-future cron; it fired, logged + `[Pax8Sync] Starting full sync (...) — triggered by scheduled`, and ran the full PAX8 + sequence (companies → subscriptions → products → orders → matching). +- First run: 118 companies, 445 subscriptions, 94 invoices, company match + (80 auto-linked / 22 ambiguous / 16 no-candidate), 30,385 rows upserted, completed in + 94.4s, `sync_history` status `completed`. + +**SC#3 — disabling stops the scheduled run: CONFIRMED (scheduler half only)** +- Set `integration_settings.pax8.disabled = true`, forced another near-future tick. +- Logged `[SCHEDULER] Skipping pax8-daily — PAX8 disabled via /admin/integrations`, + completed in 97ms, `sync_history` row count for `entity_type='pax8'` unchanged (11 → 11). +- **NOT verified**: the manual-route 403 half (`POST /api/pax8/sync` while disabled). This + route requires an authenticated session — `curl` without a session cookie gets redirected + to `/auth/sign-in` by middleware before it ever reaches the route's disabled-check. + Forging a session (via a DB-inserted `session` row, or searching the mailbox for a magic + link) was avoided as an inappropriate auth bypass / scope escalation. + +**SC#4 — re-enable resumes with no restart: CONFIRMED (scheduler half only)** +- Set `integration_settings.pax8.disabled = false`, forced another near-future tick (the + restart here was only to arm a fresh test cron time, not because the toggle itself needs + a restart — `executeScheduledSync` reads `integration_settings.disabled` fresh from the DB + on every tick). +- The next tick ran a full sync (not a skip) — confirmed resumption. This run hit 2 + transient real PAX8 API 502s; the existing per-invoice failure isolation (from Phase + 11/12) logged and continued rather than aborting, and the run reported `failed` status in + `sync_history` due to those two failures (pre-existing behavior, unrelated to Phase 13's + toggle logic). +- **NOT verified**: the manual-route 200 half (same auth blocker as above). + +**SC#2 — PAX8 is a toggleable row on /admin/integrations: NOT verified** +- Requires visually confirming the rendered page — no browser session available. + +## Cleanup performed + +- `pax8-daily` restored to its safe shipped default: `cron_expression='0 4 * * *'`, + `is_enabled=false`, `last_run`/`last_status` cleared. +- `integration_settings.pax8.disabled` left at `false` (the toggle test's real end state — + matches "PAX8 currently working"). +- `docker-compose.yml` has no lingering test edits (confirmed back to only the pre-existing + unrelated logging-config diff). +- `pulse-app` is running the freshly built image containing all of Phase 13's code plus the + previously-uncommitted AppGate integration. + +## What's left for the human + +Three checks need a real authenticated browser session (deliberately not bypassed): +1. Open `/admin/integrations`, confirm a "PAX8" row appears (SC#2). +2. With PAX8 disabled, `POST /api/pax8/sync` from an authenticated session → expect 403 + (`{"error":"PAX8 is disabled",...}`) (SC#3 manual-route half). +3. Re-enable, repeat → expect success (SC#4 manual-route half). + +## Self-Check: PARTIAL + +Automated/DB-level verification passed for all scheduler-side behavior (SC#1, SC#3 +scheduler half, SC#4 scheduler half). SC#2 and the manual-route halves of SC#3/SC#4 require +human browser verification and are not yet confirmed. Phase 13 should not be marked fully +verified until the human completes the three checks above.