Admin controls.
| Name | Role | Status | Last login |
|---|
Pending requests trigger an admin Slack notification. After approving, run on your laptop:
python -m scraper.cli --request-id <ID>
| When | User | Type | Details | Status |
|---|
| Saved at | User | Ad | Page | Expires | Media |
|---|
Pending winner nominations submitted by users. Approving promotes the ad to a permanent winner; rejecting clears the nomination metadata.
| Nominated | By | Ad | Page | Days | Apps |
|---|
Per-user spend
| User | Calls | Cost (USD) | Input tokens | Output tokens | Images | Audio (s) |
|---|
Breakdown by provider · model · operation
| Provider | Model | Operation | Calls | Cost (USD) |
|---|
Remote control for the 24/7 scrape worker. Changes apply within ~1 minute — no rebuild, no touching the machine. User scrape requests are always on and always have priority; these are the background tasks.
Re-reads every ad and sets its vertical from the ad's own words — headline, body, video script, landing domain — instead of the keyword that found it. Runs automatically after every scrape; this is the manual sweep for the ads that came in before it did. Operator verticals (Cognitive Pixel, GUNS) are never touched.
Meta signs its CDN links and they expire in about a day, so a card that worked when it was scraped goes blank soon after. This checks them and sorts the results: ok still loads · recoverable link expired but the ad is still running, so re-scraping or mirroring brings it back · dead link gone, ad stopped, never mirrored — the actual clutter. Ads already mirrored to S3 are skipped; we hold the file, so they cannot go blank.
Transcripts are recorded per video, but the feed, the search and SPYFILE read the copy held on the ad itself. Only the first was being filled, so scripts existed that no search could reach. This copies them across.
| Role | Permissions | System |
|---|
| When | User | Action | Resource | IP |
|---|