Repository navigation
Pin domain registration to the audit and print it in the client report - #56
Merged
Merged
Conversation
Adds a nullable domain_expiration_json column to audits (migration 0040, ALREADY APPLIED to prod D1 ahead of this code -- additive and nullable, so the running build ignores it). Populated by an explicit click, NOT during the crawl. Resolving bills 5 APIVerve credits, and an audit's consent covers crawling; running a third-party lookup the user never asked for on every audit is exactly the auto-spend this codebase keeps getting bitten by. Only the ABSOLUTE dates are stored. Every day count is recomputed against the reader's clock, which is what lets a report opened three months later say what is true then rather than what was true on audit day -- there is a test that advances the clock thirty days over one stored row and asserts the sentence changes from 40 days to 10. The report sentence has three registers, because a client reads it: expired and near-expiry prompt an action, everything else is context. It prints nothing at all when the lookup was never run or the stored value cannot be trusted -- a deliverable should stay silent rather than guess about something the reader may act on.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
flyrocketseo | b0d047e | Aug 20 2026, 02:58 PM |
Runs against the offline backlinks seed, whose referring domains are synthetic (source-01.com ...). Looking those up would burn about 145 APIVerve credits to learn nothing, so the spec deliberately stops short of clicking: it proves the wiring, the billable-count arithmetic and that the cost is quoted BEFORE any click, and asserts zero metered requests fire from opening the menu. The fetch itself is already covered by the live spec and by unit tests. Needs no API key and no guard, so it runs on every CI run.
Proves the property that makes storing absolute dates worthwhile: a stored registration renders with ZERO metered requests, and the day counts and status are derived against the current clock rather than read back from the row. Seeded directly into local D1 rather than produced by a real crawl -- no audit run, no credits. Guarded behind AUDIT_EXPIRY_SEEDED=1 because CI has no such row; verified that it skips without the flag and passes with it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The "proper" version of audit domain expiry: stored on the run, so it reaches the client report PDF.
Migration is already applied to prod
drizzle/0040_plain_saracen.sql—ALTER TABLE audits ADD domain_expiration_json text.Applied to prod D1 before this code exists, per the deploy trap where Workers Builds ships on a push to
mainand never runsdb:migrate:prod. Verified: the column is present on remote, andmigrations list --remotereports nothing pending. Additive and nullable, so the currently-running build ignores it — this is safe to sit ahead of the merge indefinitely.Also mirrored into the hand-written Postgres schema, which the parity test enforces.
It is a click, not part of the crawl
Resolving bills 5 APIVerve credits. An audit's consent covers crawling — firing a third-party lookup the user never asked for, on every audit, is exactly the auto-spend pattern this codebase keeps getting bitten by. So the results page shows a card with an explicit "Check domain registration" and the cost stated up front.
Once stored, re-opening the audit renders it with no request at all.
Absolute dates only, recomputed on read
The row stores
{ domain, expirationDate, createdDate, lastUpdatedDate }and nothing derived. Day counts are computed against the reader's clock, so a report opened three months after the audit states what is true then rather than what was true on audit day. There is a test that advances the clock 30 days over one stored row and asserts the sentence changes from "40 days" to "10 days".The report sentence
Three registers, because a client reads it — expired and near-expiry prompt an action, everything else is context:
It prints nothing when the lookup was never run or the stored value cannot be trusted. A deliverable should stay silent rather than guess about something the reader may act on.
Verification
pnpm ci:checkclean;pnpm testgreen — 307 files, 3098 tests.Not verified
The rendered card and the printed report line are not browser-verified — proving them end to end needs a completed audit plus a real 5-credit lookup.
🤖 Generated with Claude Code