← back to Dw Unbuyable Recovery Pilot

tk11041-innovations-reconcile/rescrape/PORTAL-PULL-RUNBOOK.md

75 lines

# TK-11041 — Innovations portal price pull: ready-to-run the moment credentials land

## Why this is the only path
The price-list request was sent 2026-09-02 (`1a063182c1841f68`) and Hektor Martinez answered the same
day (`1a0633c9451e4658`): *"Pricing is available through our website using your login information.
Account # 58315."* There is no line sheet coming. Public pages carry **zero** price tokens (verified
across all 371 pattern pages), and no pattern-sibling price exists locally. So net price for the 39
live-pattern items comes from the logged-in portal or not at all.

## Credentials — already routed, just needs the paste
`routes.json` now carries `INNOVATIONS_USERNAME`, `INNOVATIONS_PASSWORD`, `INNOVATIONS_LOGIN_URL`
(added TK-11041, backup alongside). Paste them and the `secrets` skill fans them to the master `.env`
plus the shared import engine's `.env` / `.env.local`, matching the existing `DEDAR_*` / `OSBORNE_*`
trade-portal precedent. **Do not hand-edit the env files.**

## Verified recon (read-only, 2026-09-11)
| Fact | Value |
|---|---|
| Login URL | `https://www.innovationsusa.com/login` → **200**, password field, "Sign In", "Trade" |
| Stock Magento paths | `/customer/account/login/` and `/customer/account/` both **404** — not stock routing |
| Bot defence | **reCAPTCHA present on the login page** |
| Account | **58315**, and every DW sample request states **"Net Less 20%"** |

## Consequence: this needs a real browser, not curl
reCAPTCHA rules out a plain fetch login. The pull runs through the **`browserbase`** skill (cloud
Chromium). **Correction to the 2026-09-11 recon:** a separate 2captcha call is *not* needed —
Browserbase solves captchas natively via `browserSettings: { solveCaptchas: true }`, which is what
the script uses. Login is a **one-time session**; the 39 live items resolve to only **7 pattern
pages**, so one session covers the whole pull.

**Estimated cost:** one Browserbase session, a few cents. Actual to be logged to the cost ledger.
Everything in this ticket so far has been **$0**.

## The script — written and self-tested 2026-09-11, waiting only on the paste
`~/.claude/skills/browserbase/innovations-trade-pull.js` (copy committed here as
`innovations-trade-pull.js`), alongside `romo-trade-pull.js` / `koroseal-trade-portal.js` where the
deps and `.env` already live.

```
node innovations-trade-pull.js --selftest   # $0, no network — proves the extractor goes RED on a
                                            # real logged-out page. Run this first, always.
node innovations-trade-pull.js --probe      # login + auth proof + ONE pattern page
node innovations-trade-pull.js              # full pull, 7 live pattern pages
```

**Verified today, before any credential exists:**
- `--selftest` → **7/7 PASS**, including the two that matter: the real captured logged-out
  `/item/costine` page classifies `SESSION_FAILURE` and yields **no price**, and a `$0.00` token is
  rejected rather than recorded. Fixture: `fixtures/logged-out-costine.html`.
- `--probe` with no credentials → **exits 2, fails loud, opens no session, spends nothing.**

**The safety contract, in the code rather than in prose:**
1. Login is **positively proven** (an account marker present *and* "Sign In" absent) before any
   page is fetched. An error-free login is not a proven session.
2. Auth is re-asserted on **every** page — a portal can drop a session mid-run and keep serving 200s.
3. Three states, never two: `MEASURED` / `NOT_MEASURED` (authed, no price) / `SESSION_FAILURE`
   (auth unproven → **aborts the run** rather than record false absences). A page with no price is
   never a `$0` price — the `$0`-orderable lineage is exactly why.
4. `retail_computed: false` is written into the output with the reason, so the discount conflict
   cannot be skipped silently downstream.
5. No DB write, no Shopify write. Output is staged JSON in `data/portal-pull-<ts>.json`.
6. robots-compliant: `/item/<slug>/` is `Allow`; `/item/*/*` is `Disallow` (and 500s), so only the
   7 pattern pages are fetched — never per-colorway URLs.

## Still blocking the pull
1. **The credential paste** (`INNOVATIONS_USERNAME` / `INNOVATIONS_PASSWORD`) — Steve only.
2. **The discount** — registry says **10%**, every sample request says **Net Less 20%**. The script
   refuses to compute retail until this is settled; a 10-point cost-basis error propagates through
   `cost/0.65/0.85` to customers.

## The 12 Whistler items are NOT in this pull
They're discontinued and 404 on the vendor site; no logged-in page exists to price. Their answer comes
from the Whistler follow-up draft (`r-5469570474427181957`), which Hektor will almost certainly answer —
on 2026-09-10 he volunteered *"Chevron Cork has been discontinued. CRC-02 - 62LY in stock."* unprompted.