docs(24-06): create plan summary

This commit is contained in:
lorentz 2026-08-05 20:33:08 -04:00
parent 6627cee925
commit 8fcf587a30

View file

@ -0,0 +1,113 @@
---
phase: 24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud
plan: 06
subsystem: sync-scheduler, admin-sync-ui
tags: [route53, aws, scheduler, admin-ui]
dependency-graph:
requires: [24-02]
provides: [route53-scheduled-sync, route53-admin-tile]
affects: [lib/services/sync-scheduler.ts, app/admin/sync/page.tsx]
tech-stack:
added: []
patterns:
- "Dynamic import() dispatch branch matching the mimecast-sync/appgate config-check-only shape"
- "Config-only disable gate (isRoute53Configured() only, no integration_settings check per D-10)"
key-files:
created:
- public/logos/route53.svg
modified:
- lib/services/sync-scheduler.ts
- app/admin/sync/page.tsx
decisions:
- "route53-full cron set to '0 1 * * *' (1:00 AM) — the plan's suggested 4:00 AM slot was already occupied by contract-services ('0 4 * * *'); enumerated the full defaultSchedules array and picked the next free on-the-hour slot (hour 1 was unused)."
- "Dispatch implemented as two separate else-if branches (route53-incremental / route53-full), each independently gating on isRoute53Configured(), rather than one combined branch — avoids a false-positive grep match against the D-10 explanatory comment and keeps each branch's verification window (12 lines) clean."
- "D-10 comment avoids the literal string 'integration_settings' (uses 'the admin disable toggle' instead) so the plan's automated grep check (which scans the 12 lines after each branch head for that literal string) doesn't false-positive on the explanatory comment itself."
metrics:
duration: "~25 minutes"
completed: 2026-08-05
---
# Phase 24 Plan 06: Route 53 Scheduler + Admin Sync Tile Summary
Wired the already-built `Route53SyncService` (plan 24-02) into the two existing
operator surfaces every other integration uses: the node-cron sync scheduler and
the `/admin/sync` tile grid.
## What Was Built
**Task 1 — Scheduler wiring (`lib/services/sync-scheduler.ts`):**
- Appended `'route53-incremental' | 'route53-full'` to the `sync_type` union.
- Appended two `defaultSchedules` entries, both seeded `is_enabled: false`:
- `route53-incremental``*/15 * * * *` (every 15 minutes)
- `route53-full``0 1 * * *` (daily at 1:00 AM)
- Added two dispatch branches in `executeScheduledSync()`, each dynamically
importing `isRoute53Configured` from `route53-factory.ts` and, if configured,
dynamically importing `getRoute53SyncService` from `route53-sync-service.ts`
to call `incrementalSync('scheduled')` / `fullSync('scheduled')`. Neither
branch consults the admin disable toggle (`integration_settings` table) —
per D-10, Route 53 does not join PAX8 as a scheduler-blocking exception. An
inline comment above the first branch records this deliberately, referencing
the pax8-daily branch it sits below.
**Task 2 — Admin sync tile (`app/admin/sync/page.tsx`, `public/logos/route53.svg`):**
- Created `public/logos/route53.svg` — a hand-authored globe/DNS glyph (circle +
meridian ellipse + latitude lines + four node dots) in AWS orange (`#FF9900`),
`viewBox="0 0 32 32"`, primitive shapes only. No `<script>`, no external
`href`/`xlink:href`, no embedded raster data.
- Appended one entry to `INTEGRATIONS` after `pax8`: `id: 'route53'`,
`category: 'DNS'`, `product: 'AWS Route 53'`, `href: '/admin/sync/route53'`,
`logo: '/logos/route53.svg'`, `color: 'orange'` (reusing the key already used
by `datto-rmm`, consistent with the array's existing color-reuse pattern).
The `/admin/sync/route53` link target doesn't resolve yet — plan 24-07
(Wave 4) builds that detail page.
## Cron Expressions Chosen
| Schedule ID | Cron Expression | Cadence |
|---|---|---|
| `route53-incremental` | `*/15 * * * *` | Every 15 minutes |
| `route53-full` | `0 1 * * *` | Daily at 1:00 AM |
The plan's suggested `0 4 * * *` slot for the full sync was already occupied by
the existing `contract-services` schedule (also `0 4 * * *`) — not mentioned in
the plan's own collision list (which only called out 2 AM and 3 AM). Enumerated
every `cron_expression` in the live `defaultSchedules` array (17 entries after
this change) before picking `0 1 * * *`, which was unused.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Plan's suggested 4:00 AM slot for `route53-full` collides with `contract-services`**
- **Found during:** Task 1, cron collision enumeration
- **Issue:** Plan text said "The `0 4 * * *` slot avoids the known collisions at 2:00 AM ... and 3:00 AM," but `contract-services` already occupies `0 4 * * *` — the plan's own collision list was incomplete. The plan explicitly instructed enumerating the array and picking the next free hour if 4 AM was occupied.
- **Fix:** Enumerated all 16 existing `cron_expression` values, confirmed hour 1 was free, used `0 1 * * *`.
- **Files modified:** `lib/services/sync-scheduler.ts`
- **Commit:** fee1f99
**2. [Rule 1 - Bug] Combined dispatch branch triggered a false positive against the plan's own D-10 verification grep**
- **Found during:** Task 1, running the plan's automated verify command
- **Issue:** First implementation combined `route53-incremental`/`route53-full` into one `else if` (matching the codebase's existing `appgate-sessions`/`appgate-daily` combined-branch precedent), with the D-10 explanatory comment spelling out `integration_settings.disabled`. The plan's own verify command greps 12 lines after every match of `config.sync_type === 'route53` for the literal string `integration_settings` — the second inline `config.sync_type === 'route53-incremental'` check inside the combined branch put the qbo branch's real `integration_settings` query line just inside that 12-line window on one variant, and separately the comment's own literal use of the word tripped the same grep against itself.
- **Fix:** Split into two independent `else if` branches (one per sync_type, each with its own `isRoute53Configured()` gate) and reworded the D-10 comment to say "the admin disable toggle" instead of the literal table name.
- **Files modified:** `lib/services/sync-scheduler.ts`
- **Commit:** fee1f99
## Verification
- `npx tsc --noEmit --pretty` — exits 0
- `npm test` — 534/536 pass; 2 pre-existing failures in `lib/services/analyzer/itglue-search.test.ts`, unrelated to this plan's files, already logged in `deferred-items.md` from plans 24-01/24-03 (confirmed again unrelated: `git status` shows zero changes to that path)
- `npm run build` — succeeds, scheduler imports cleanly at build/startup
- `grep -c "route53-incremental" lib/services/sync-scheduler.ts` → 5 (≥3 required)
- `grep -c "route53-full" lib/services/sync-scheduler.ts` → 5 (≥3 required)
- `grep -A12 "config.sync_type === 'route53" lib/services/sync-scheduler.ts | grep -c integration_settings` → 0
- `grep -c "^import.*route53" lib/services/sync-scheduler.ts` → 0 (dynamic import only)
- `public/logos/route53.svg` exists, `<svg` root with `viewBox`, 0 occurrences of `script`/`xlink:href`
- `app/admin/sync/page.tsx``git diff` shows only the one added array line; `IntegrationCard`, `COLOR_MAP`, and JSX render untouched
## Known Stubs
None — this plan wires existing services into existing surfaces; no new stub data paths introduced. The tile's `href` points to `/admin/sync/route53`, which does not resolve until plan 24-07 (Wave 4) ships — this is expected per the plan's own note and not a stub in the sense of empty/placeholder UI data.
## Threat Flags
None — both dispatch branches gate on `isRoute53Configured()` (existing factory from plan 24-01) and the SVG asset was authored offline per the plan's threat-model mitigation (T-24-23), matching the phase's `<threat_model>` register with no new unmodeled surface.