# Karma EDM — VS Code extension

Author, preflight and publish Karma email templates without leaving the editor.

Deliberately outside the pnpm workspace (`apps/*`, `packages/*`, `configs/*`), so
it keeps its own dependency lifecycle and never gets pulled into the console's
build or typecheck.

## Why

The console's upload wizard already handles zips. What it cannot do is tell you
about a broken image *while you are writing the template*. A relative
`<img src="images/hero.png">` with no file behind it is not a warning — it is a
hole in every inbox that receives the email — and today you find out only after
uploading. Here it is a red squiggle under the path, on save.

## Setup

```bash
cd tools/edm-vscode
npm install
npm run build
```

Then press <kbd>F5</kbd> in VS Code to launch an Extension Development Host, or
`npm run package` to produce a `.vsix` to share.

Two settings:

| Setting | Default | Meaning |
|---|---|---|
| `karmaEdm.coreUrl` | `http://localhost:3000` | console2 core base URL, no trailing slash |
| `karmaEdm.preflightOnSave` | `true` | re-run preflight on every `.html` save |

## Authentication — read this

Run **Karma EDM: Set console session** and paste your admin console `Cookie`
header (DevTools → Network → any request → Request Headers → Cookie). It is
stored in VS Code SecretStorage, which is your OS keychain — never in settings
or a workspace file where it would get committed.

This is clunky, and the clunkiness is chosen on purpose. The alternative was
shipping `INTERNAL_SERVER_API_KEY` to every developer's laptop. That key is a
full-trust, org-wide shared secret with no per-user revocation: putting it on N
machines in N settings files, to save one copy/paste, is a bad trade.

**The real fix is per-user personal access tokens on the console2 side, which do
not exist yet.** Until they do, you will re-paste the cookie whenever your
console session expires. If that becomes annoying enough, build the PAT flow —
that is the signal to.

## Commands

| Command | What it does |
|---|---|
| **Preflight this template** | Scans the open `.html` and puts every unresolved / http / localhost image in the Problems panel, positioned on the offending path. Also flags Gmail's 102 KB clip threshold. |
| **Push this template** | Uploads every locally-referenced image, rewrites the references to permanent public URLs, then creates a new template or updates an existing one. |
| **Pull a template into the workspace** | Pick a template, write its published HTML into the workspace root, open it. |
| **Set / Clear console session** | Manage the stored cookie. |

Preflight also runs automatically on save. Failures there are silent by design —
an unreachable console or an expired session must not throw an error toast on
every <kbd>Ctrl</kbd>+<kbd>S</kbd>.

## How push resolves images

Relative paths resolve against the HTML file's own directory, exactly as a
browser would, so the folder layout designers already use needs no rearranging:

```
welcome/
  index.html          ← open this, run Push
  images/
    hero.png          ← referenced as images/hero.png, uploaded automatically
```

Images are content-addressed and **never deleted** once uploaded — a two-year-old
email in someone's inbox still fetches that exact URL. Editing an image produces
a new object rather than mutating a live one.

If a referenced file is missing from disk, push **aborts** and lists what it
could not find. It will not publish a template with a known hole in it.

## Limitations

- One HTML file at a time. For a whole archive of templates, use the console's
  batch import (`/admin/edm/import` → "Many").
- Push always writes to the active version; there is no draft state here.
- No live preview pane. Use the console's preview or a test send.
