# Blasts Kit Sample - "Sign in with the Blasts Deals app" inside a Chrome / Edge extension

A complete, load-unpacked MV3 extension that signs a PC in to a Blasts account with the
user's phone. It has **no backend and no secrets**: the partner id is public, the browser
supplies the extension origin, and the server does the rest. It uses the vendored
`@blasts/kit-ext` (`vendor/blasts-kit-ext.js`, verify with `SHA256SUMS`).

## Run it (10 minutes) - the console walks you through the same 4 steps with a live tracker

**Step 0 - the phone app comes first.** Install **Blasts Deals** on your phone
([Google Play](https://play.google.com/store/apps/details?id=com.tipsmarketing.blastsdeals); iPhone: [App
Store](https://apps.apple.com/us/app/blasts-deals/id6794013531)), register in it with your *work e-mail*, and turn on *Settings -> Sign-In Approvals*. Every sign-in
below is approved on that phone. Then sign in to the developer console **with that same e-mail** - a
sandbox partner can ring only that phone, and the console's step 1 checks this for you and says so.

**What to expect when you click Sign in:** the first click on a new account only asks your phone for
permission (allow it under Settings -> Sign-In Approvals - not the Approvals tab). Click again: the
6-digit code appears in the popup after a few seconds (up to ~10 the first time while the server
wakes up); the request shows under the phone's **Approvals** tab - open it and type the code into it (the code is never sent to the phone).

1. **Console step 1-2.** Open the [Blasts developer console](https://api.blasts.app/dev/console) -> sign
   in (that e-mail) -> the **"Set up an extension in 4 steps"** card -> *Create my sandbox* (one click).
2. **Load this folder.** `chrome://extensions` -> Developer mode ON -> *Load unpacked* -> pick this folder
   (Edge: `edge://extensions`). Open the popup: click the **puzzle-piece Extensions icon** to the right of
   the address bar, then click **Blasts Kit Sample** in the list (pin it there once for a one-click button).
   Its first-run checklist shows **this copy's 32-letter id with a Copy button**.
3. **Console step 3.** Paste that id into the wizard's *Register* box -> Register. The step turns green.
4. **Settings here.** Popup -> *Open Settings* -> enter the partner id the console shows (ends in
   `-test`) and your product's name -> Save. Back in the popup, the sign-in card first checks with the
   server that this extension is registered ("Ready" in green; or "Step 3 is not done" with the id to copy).
5. **Sign in.** Type **the same e-mail** -> a 6-digit code appears -> phone: **Blasts Deals ->
   Approvals -> open the request -> type that code into it**. The popup turns to "This PC is signed in", and the
   console's step 4 flips to green by itself.
6. **Plan card.** Free-tier counter (the phone's pool once signed in); the paid-plan **license code**
   field appears only after sign-in - nobody needs a code for the free tier. Mint codes in the console
   ("Mint license codes"), paste one, *Activate*; *Release* frees the seat. **Start over** in the console's
   partner row wipes the sandbox and everything under it when you want a clean run.
A **sandbox** partner rings only the phone of the console account that created it (the server
answers `sandbox_owner_only` for anyone else). Request live keys in the console to serve other people.

## What is in the folder

| File | Role |
|---|---|
| `manifest.json` | MV3; `storage` permission; `host_permissions` for the Blasts API only; strict CSP (no remote code). |
| `vendor/blasts-kit-ext.js` | The kit, vendored byte-for-byte from `@blasts/kit-ext` `dist/`. |
| `popup.html` / `popup.js` | The four states: set up -> sign in (e-mail) -> check your phone (code) -> signed in; plus the plan card (free counter + license code) via `kit.trial` / `kit.license`. |
| `options.html` / `options.js` | Public settings (partner id, product name) + this copy's extension id. |
| `settings.js` | The one storage key both pages read. |
| `sample.css` | Styling only. |
| `scripts/sample_ext.test.mjs` | Pins: MV3 shape, no remote code, vendored kit byte-equal to the dist, no secret-shaped strings, the four views wired. |

## Reuse in your own extension

Copy `vendor/blasts-kit-ext.js`, add `"storage"` + the API `host_permissions` to your manifest, then:

```js
import { createBlastsExt } from './vendor/blasts-kit-ext.js';
const kit = createBlastsExt({ partnerId: 'acme-test', productName: 'Acme Leads' });

const res = await kit.signIn.start(email);          // -> { state:'ceremony', challenge, request_id, poll_secret, expires_at }
showCode(res.challenge);                            // 6 digits, shown here only - the user types them into the request on the phone
const done = await kit.signIn.waitForApproval(res); // -> { status:'approved', link } | denied | expired | failed
const st = await kit.link.status();                 // -> { linked, reason?, message?, config? }
```

Everything the kit can hand you (`res.error`, `done.status`, `st.reason`) has a plain-English line
in `kit.copy` with your product name filled in. The kit refuses `apiKey` / `signingSecret` / `sk_*`
values at construction: an extension is a public client and must never hold partner credentials.
