feat: http.request v0.1.0 — generic HTTP client

First release. Pure-WASM HTTP client built on waki 0.5 for
F∆I flow steps that need to call REST APIs.

Capability: http.request@0.1.0

Inputs: method (GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS),
url, headers (JSON object string), body (UTF-8).

Outputs: status (decimal text), headers (JSON object), body
(UTF-8 lossy).

Permissions: net: *. The wildcard is deliberate — operators
clamp to specific hosts via their operator-policy ceiling.

6 unit tests on the headers-input parser (empty / strings /
numbers coerced / non-object rejected / nested rejected /
malformed JSON rejected).

Bundle: target/wasm32-wasip2/release/http_request.wasm
(~120 KiB stripped).

v0.2.0 candidates: http.request-bytes for binary payloads,
per-request timeout / retry inputs, cookie-jar.

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-05-25 14:16:09 +02:00
commit 4681d0bb2c
8 changed files with 1194 additions and 0 deletions

96
MODULE.de.md Normal file
View file

@ -0,0 +1,96 @@
# http.request
Generischer HTTP-Client für Flow-Steps. GET / POST / PUT /
PATCH / DELETE / HEAD / OPTIONS mit beliebigen Headern und
einem UTF-8-Body. Die audit-freundliche Alternative zu Flows,
die ihren eigenen HTTP-Client mitbringen.
## Capability
- `http.request@0.1.0`
## Eingaben
| Name | Typ | Beschreibung |
| --------- | ---- | ---------------------------------------------------------------------------------- |
| `method` | text | HTTP-Verb in Großbuchstaben (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`). |
| `url` | text | Vollständige URL inklusive Scheme. |
| `headers` | text | Optional. JSON-Objekt-String mit zusätzlichen Headern. Leer = keine. |
| `body` | text | Optional. UTF-8-Request-Body. Leer = kein Body. |
Beispiel-`headers`:
```json
{"Accept":"application/json","X-Tenant":"acme","Content-Length":42}
```
String-, Zahl- und Boolean-Werte werden akzeptiert (Zahlen und
Booleans werden zu Strings koerziert). Verschachtelte
Arrays/Objekte werden beim Parsen mit einem klaren Fehler
abgelehnt.
## Ausgaben
| Name | Typ | Beschreibung |
| --------- | ---- | ------------------------------------------------------------------ |
| `status` | text | Dezimal-Statuscode als Text (z.B. `"200"`, `"404"`). |
| `headers` | text | Antwort-Header als JSON-Objekt (Schlüssel kleingeschrieben). |
| `body` | text | Antwort-Body als UTF-8. Ersatzzeichen bei nicht-UTF-8-Daten. |
Status als Text, damit der Audit-Log-Eintrag ohne JSON-
Reparsing operator-lesbar bleibt.
## Berechtigungen
```yaml
permissions:
- "net: *"
```
Der Wildcard macht explizit, dass dieses Modul absichtlich
beliebige HTTP-Endpunkte aufrufen kann. Operator:innen
beschränken den Spielraum über das Policy-Ceiling
(`~/.fai/config.yaml#security.max_permissions.net`) — eine
Installation gegen eine Policy ohne Wildcards schlägt zur
Install-Zeit fehl.
## Warum ein generisches Primitiv statt API-spezifischer Module
Gleiche Antwort wie bei `llm.chat`: ein einzelnes explizites
Egress-Modul bedeutet, dass Operator:innen `net: *` genau
einmal auditieren statt versteckt in jedem Flow-YAML. Die
Permission-Posture bleibt sichtbar.
## Grenzen in v0.1.0
- Nur UTF-8-Body. Binäre Up-/Downloads kommen über ein
separates `http.request-bytes` (v0.2.0).
- Keine pro-Request-Timeout-/Retry-Inputs (waki-Defaults
gelten).
- Kein Cookie-Jar / Session-Keeping.
## Beispiel-Flow
```yaml
name: post-to-webhook
inputs:
payload: text
steps:
- id: notify
use: http.request@^0
with:
method: "POST"
url: "https://example.org/webhook"
headers: '{"Content-Type":"application/json"}'
body: $inputs.payload
outputs:
status: $notify.status
echo: $notify.body
```
## Build
```bash
cargo build --release --target wasm32-wasip2
# Ausgabe: target/wasm32-wasip2/release/http_request.wasm
```