Skip to content

feat: add persisted Local SEO map grids - #245

Open
Dannydropz wants to merge 13 commits into
every-app:mainfrom
Dannydropz:codex/local-map-grid-scanning
Open

feat: add persisted Local SEO map grids#245
Dannydropz wants to merge 13 commits into
every-app:mainfrom
Dannydropz:codex/local-map-grid-scanning

Conversation

@Dannydropz

@Dannydropz Dannydropz commented Aug 25, 2026

Copy link
Copy Markdown

Overview

Adds persisted Local SEO map-grid tracking across SQLite and Postgres, including configuration management, deterministic grid generation, durable queued Google Maps scans, historical run results, and an interactive Leaflet map.

The collection workflow now keeps provider calls inside small durable steps so a 7×7 grid with multiple keywords cannot exhaust a Worker invocation's subrequest budget. Normal queued tasks are allowed 50 minutes to complete before being marked timed out, matching the provider's documented 45-minute target with a small buffer.

Safety, durability, and billing

  • Saving a grid never starts a scan; scans remain manual-only.
  • Billed task submission has no automatic HTTP or workflow retries.
  • Accepted provider task IDs are persisted separately from submission so database retries cannot duplicate paid work.
  • Result collection uses at most five provider requests per durable step.
  • Terminal workflow failures are recorded in a retryable durable database step.
  • Hosted scan execution remains gated until Autumn credit reservation/finalization is implemented; self-hosted manual scans remain available.
  • Stale pending runs are reconciled with workflow state and compare-and-set protection before another run can start.
  • The self-hosted production instance was deployed and its protected health endpoint responded after deployment.

How to review

  1. Review the normalized Local SEO data model and SQLite/Postgres migrations.
  2. Review scan creation, immutable task snapshots, and stale-run reconciliation.
  3. Review billed task submission and the bounded, 50-minute collection workflow.
  4. Review map rendering, keyword switching, result summaries, and point details.
  5. Review project scoping and the self-hosted Access service-token changes.

The highest-risk areas are billed-task durability, dialect parity, historical results after configuration edits, and recovery around workflow startup.

Verification

Verified at head 6fe6091:

  • 144 test files and 1,184 tests passed.
  • Production client and SSR builds passed.
  • TypeScript checks for both applications passed.
  • Prettier, Knip, and plugin-skill synchronization passed.
  • Oxlint reported zero warnings and zero errors across 841 files.
  • Independent reviews covered complexity, security, billing, project idioms, and stale cruft; every blocker/should-fix finding was verified and resolved.

Review notes

No unresolved blocker or should-fix findings remain.

Optional follow-ups: migrate the setup modal to TanStack Form, and include any rare provider cost attached to rejected task-post response entries in run-level reporting. Hosted scans must remain disabled until atomic Autumn reservation/finalization is implemented.

@Dannydropz

Copy link
Copy Markdown
Author

@bensenescu Would you review this Local SEO map-grid slice when you have a chance?

The branch is current with main, hosted scans remain disabled pending atomic credit reservation, and the latest commit adds workflow-aware recovery for orphaned pending runs. Local verification at ff70559 passed 1,178 tests, the client/SSR production build and TypeScript, Prettier, type-aware Oxlint, and Knip.

Suggested high-risk review areas are billed-task durability, SQLite/Postgres parity, immutable scan snapshots, and stale-run reconciliation around workflow startup.

Danny Keegan and others added 7 commits August 27, 2026 20:02
The map grid renders on Leaflet, but the dependency was never added to the
manifest — it only existed in the local node_modules, so a clean checkout of
the feature would not build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two gaps that together made a headless caller — a self-hosted agent, CI —
unable to reach a self-hosted instance at all, and made a hand-added custom
domain silently disappear.

Service tokens. `ACCESS_ALLOWED_EMAILS` is an interactive email one-time-code
gate that a machine cannot complete, and `oseo_` API keys exist only in hosted
mode, so a self-hoster had no way in. `ACCESS_SERVICE_TOKEN_IDS` adds a Service
Auth policy for the listed tokens. Access issues those tokens with an empty
`sub` and no `email`, which `resolveCloudflareAccessContext` rejected; it now
maps a token to a synthetic user in the shared workspace, keyed on
`common_name`. Reaching that branch already means an operator wrote a policy
admitting that exact token, so the token is the authorization.

Custom domains. `CUSTOM_DOMAIN` binds extra hostnames to the worker and adds
them to the Access application's destinations. Both are reconciled on every
deploy, so a Custom Domain added in the dashboard read as "no domain wanted"
and was torn down on the next deploy — taking the hostname off the Access app
on the way. Declaring it is what makes it survive. Gating matters as much as
routing here: a routed hostname missing from destinations reaches the worker
without an Access check.

Docs cover both, including that a service token reads and writes real projects
in the shared workspace and should be treated like a listed email.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Entry written by codex on 2026-08-25 and left uncommitted in the working tree.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant