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:
@@ -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.
|
||||
Reference in New Issue
Block a user