Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
# Plivo — `@suaveplan/sms-providers`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Real Plivo SMS provider implementing `SmsProvider` from `@suaveplan/sms`. POSTs to `/v1/Account/{AuthId}/Message/` authenticated via HTTP Basic (`AuthId:AuthToken`); JSON body. Status fetched via `GET .../Message/{uuid}/`. Inbound webhook signature verification follows Plivo's documented `X-Plivo-Signature-V3` scheme — HMAC-SHA256 over the canonical signing string `<url><nonce><sorted form-fields joined as key=value, comma-separated>` with the auth token as the key, Base-64 encoded.
The class holds no in-flight state and routes every HTTP call through the injectable `FetchLike` seam. Tests stand up a `node:http` server on a random port and inject a `fetch` adapter that points at it.
## Features
- HTTP Basic auth with the canonical `AuthId:AuthToken` pair.
- JSON request body — `src`, `dst`, `text` (and `media_urls`/`type=mms` when MMS).
- `getStatus(uuid)` round-trips the documented `.../Message/{uuid}/` resource.
- Status mapping covers `queued` / `sent` / `delivered` / `undelivered` / `failed` / `rejected`.
- `verifyWebhookSignature(url, nonce, params, sig)` implements the X-Plivo-Signature-V3 canonical string scheme.
- `parseInbound` discriminates between inbound messages, delivery receipts, and opt-out/opt-in/help keywords.
- OTel — counter + histogram on every send + verify.
## Usage: Basic
```ts
import { PlivoProvider } from "@suaveplan/sms-providers";
const plivo = new PlivoProvider({
authId: "MA…",
authToken: "…",
});
const r = await plivo.send({
to: "+15551234567",
from: "+15559999999",
body: "hi",
});
```
## Usage: Advanced
```ts
import { PlivoProvider } from "@suaveplan/sms-providers";
const plivo = new PlivoProvider({ authId: "MA…", authToken: "…" });
const ok = await plivo.verifyWebhookSignature(
"https://your.app/webhooks/plivo",
"nonce-from-X-Plivo-Signature-Ma-Nonce-Header",
{ From: "+1", To: "+2", Text: "hi", MessageUUID: "uuid" },
"<base64 signature>"
);
```
## API Reference
| Symbol | Kind | Notes |
|---|---|---|
| `PlivoProvider` | class | Implements `SmsProvider`. |
| `send(message, options?)` | method | POST `.../Message/`; returns `SmsDeliveryReport`. |
| `getStatus(uuid)` | method | `GET .../Message/{uuid}/`. |
| `mapStatus(raw)` | method | Canonical mapping. |
| `verifyWebhookSignature(url, nonce, params, sig)` | method | HMAC-SHA256-Base-64 verifier; throws `SIGNATURE_INVALID` on mismatch. |
| `parseInbound(params)` | method | Discriminates into `InboundSmsEvent`. |
## Implementation Notes
`send` defaults the initial status to `"queued"` because Plivo's create response only returns the message UUID; the actual carrier-side state is later reported on the inbound DLR webhook. MMS support flips `type: "mms"` and forwards `mediaUrls` as `media_urls[]` per the documented Plivo convention.