On a firm site, the extension draws a small corner chip with this machine's person's authenticator code for that site, a countdown, and a Copy button. It can be minimised to a "2FA" pill for the tab's session. - /api/autobuyer/otp?host= relays to the master's /api/otp?person=<instance_id>&host=, which matches the host to a firm's Site link and the person's assigned codes. No master link, a master that can't be reached, or no match all come back as no codes. An answer without scope: 'person' is refused: an older master ignores ?person= and would return every stored code. - The chip lives in a shadow root, counts down on its own, refetches when a code expires, and stays hidden for a minute after the runner last located something, so automated clicks never land on it. Copy uses execCommand inside the click, since the async Clipboard API can stall on a permission prompt, and leaves focus in the site's code field. - Apex (*.apextraderfunding.com) joins host_permissions, which also brings it into capture like the other firm sites. Version 0.16.0. - CatalogFirm mirrors the master's new optional siteUrl. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
4.3 KiB
Markdown
92 lines
4.3 KiB
Markdown
# AutoFirmer Capture (Chromium extension)
|
|
|
|
Scrapes the firm tab you are looking at and posts its HTML back to the
|
|
dashboard. There is no on/off switch for that — see **Scope** below for what
|
|
limits it instead.
|
|
|
|
## Install (unpacked)
|
|
|
|
1. Start the dashboard (`npm run dev`) so `http://localhost:3000` is up.
|
|
2. Open `chrome://extensions`, enable **Developer mode** (top right).
|
|
3. **Load unpacked** → select this `extension/` folder.
|
|
4. Click the extension icon to open the popup and set:
|
|
- **Dashboard URL** — default `http://localhost:3000`. Use the VPS IP if the
|
|
dashboard runs elsewhere.
|
|
- **Poll interval** — seconds between status checks (default 3).
|
|
- **Element selector** — optional CSS selector; matching elements get their
|
|
on-screen position measured alongside the HTML.
|
|
|
|
The badge shows `!` (red) if the dashboard is unreachable, and nothing otherwise
|
|
— blank is the working state. Open the popup for what the last tick actually did.
|
|
|
|
## Flow
|
|
|
|
```
|
|
extension --GET /api/autobuyer/status--> { pendingLocate }
|
|
extension --POST /api/autobuyer/capture-> html + viewport + element rects
|
|
AutoBuyer page --GET /api/autobuyer/capture-> renders the HTML
|
|
```
|
|
|
|
Nothing in that loop is switchable. Every tick serves any queued clicks and then
|
|
captures the tab you are on.
|
|
|
|
## Scope
|
|
|
|
Capture has no switch, so scope is what keeps it honest. Three limits, all
|
|
enforced by Chrome rather than by this code:
|
|
|
|
1. **`host_permissions` is deliberately narrow** — the firm sites plus localhost
|
|
for the dashboard. The extension is *technically incapable* of reading any
|
|
other site, so an accidental capture of your bank or mail tab cannot happen
|
|
however the logic here is changed.
|
|
2. **Only the tab you are on.** `pickTab()` asks for the active tab of the
|
|
last-focused window *and* a host_permissions match. A firm tab sitting in the
|
|
background is not captured, and neither is anything else. Switch away and
|
|
capture simply stops until you switch back.
|
|
3. **One content script, same hosts.** `captcha-hook.js` runs at document_start
|
|
on the firm sites only. It wraps `turnstile.render` / `grecaptcha.render` /
|
|
`hcaptcha.render` and remembers what the page passed them — the sitekey, and
|
|
above all the callback a solved token has to be handed to, which a
|
|
programmatically rendered widget puts nowhere else. It reads nothing else and
|
|
sends nothing anywhere; the remembered arguments stay in the page's own world
|
|
until a `solveCaptcha` step comes to collect them.
|
|
|
|
To automate a different broker, add its pattern to `host_permissions` in
|
|
`manifest.json` and reload the extension — that alone scopes capture to it. Avoid
|
|
going back to `<all_urls>`: it would put every tab you visit in reach, and limit
|
|
1 is the only thing standing between this and scraping your whole browser. A new
|
|
firm needs its host in *both* lists — `host_permissions` and the `content_scripts`
|
|
matches — or captchas on that site will have no callback to fire.
|
|
|
|
## 2FA codes
|
|
|
|
On a firm site, the extension shows the machine's person's authenticator code
|
|
for that site in a small chip in the bottom-right corner, with a Copy button
|
|
(minimise it to a "2FA" pill; that sticks for the tab's session).
|
|
|
|
```
|
|
extension --GET /api/autobuyer/otp?host=<tab host>--> dashboard
|
|
dashboard --GET <master>/api/otp?person=<instance_id>&host=<tab host>--> master
|
|
```
|
|
|
|
The master holds the secrets and matches the host against each firm's **Site**
|
|
link (Firms page), then returns the codes assigned to this person and that firm
|
|
(Codes page). The chip only needs a code to be assigned — it doesn't wait for a
|
|
code field. It stays hidden for a minute after the runner last located
|
|
something, so automated clicks never land on it.
|
|
|
|
A new 2FA site needs its host in `host_permissions` (not the captcha
|
|
`content_scripts` list), a Site link on its firm on the master, and its codes
|
|
assigned on the master's Codes page.
|
|
|
|
## Notes
|
|
|
|
- The extension never captures the dashboard's own pages — otherwise it would
|
|
just mirror its own output back.
|
|
- `chrome://`, `about:` and Web Store pages cannot be scripted by any extension;
|
|
they're skipped.
|
|
- MV3 service workers are torn down when idle. Each poll makes an extension API
|
|
call, which keeps the worker alive; a 30-second alarm revives it if Chrome
|
|
kills it anyway. So worst-case cadence is 30s, normal cadence is the poll
|
|
interval.
|