|
| 1 | +<!-- SPDX-License-Identifier: PMPL-1.0-or-later --> |
| 2 | + |
| 3 | +# Supported Features — HTTP Capability Gateway |
| 4 | + |
| 5 | +**Version:** 0.1.0-dev |
| 6 | +**Last updated:** 2026-04-16 |
| 7 | +**Status:** MVP verification phase (CRG grade C) |
| 8 | + |
| 9 | +This document is the single authoritative reference for what the gateway |
| 10 | +actually supports today. If it is not in the **Supported** list below, it |
| 11 | +is either a stub, planned work, or out of scope — do not rely on it in |
| 12 | +production. |
| 13 | + |
| 14 | +See `ROADMAP.adoc` for the formal MVP scope definition with test mappings, |
| 15 | +and `MULTI-PROTOCOL.md` for protocol-specific details (note that document |
| 16 | +describes a broader vision; the table here reflects actual runtime behaviour). |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## Protocols |
| 21 | + |
| 22 | +| Protocol | Status | Notes | |
| 23 | +|----------|--------|-------| |
| 24 | +| **HTTP/1.1** | Supported | Full verb governance, proxy forwarding, stealth mode. This is the MVP scope. | |
| 25 | +| **HTTP/2** | Supported (via Cowboy) | Inherited from Plug.Cowboy adapter. Not exercised by gateway-specific tests. | |
| 26 | +| **HTTPS / TLS** | Not supported | No TLS termination inside the gateway. Run behind a TLS-terminating proxy (nginx, Caddy, Svalinn, etc.). | |
| 27 | +| **mTLS (client certs)** | Partial | `extract_trust_level_from_cert/1` exists but is an approximation; the ASN.1 OTPCertificate record unpacking has a documented `TODO` for production use. Do not rely on mTLS trust extraction without adapting `gateway.ex:552-617`. | |
| 28 | +| **GraphQL** | Stub only | `GraphQLHandler` parses JSON bodies and does naive prefix-based operation detection. `check_operation_policy/2` always returns true. Operation-level governance is not implemented. | |
| 29 | +| **gRPC** | Stub only | `GRPCHandler` extracts service/method from path but `forward_grpc_request/5` returns a hardcoded response — no actual gRPC forwarding. | |
| 30 | +| **WebSocket** | Not supported | No implementation. | |
| 31 | + |
| 32 | +## Trust Sources |
| 33 | + |
| 34 | +| Source | Status | Notes | |
| 35 | +|--------|--------|-------| |
| 36 | +| **`X-Trust-Level` header** | Supported | The canonical trust source. Values: `untrusted`, `authenticated`, `internal`. Anything else is parsed as `:untrusted` (see `SafeTrust.parse_trust/1`). | |
| 37 | +| **Header stripping for untrusted sources** | Supported | `strip_untrusted_headers/2` removes `X-Trust-Level` from any request whose `remote_ip` is not in `:trusted_proxies`. Default trusted proxies: `["127.0.0.1", "::1"]`. **Operator action required**: configure `:trusted_proxies` for your deployment before exposing the gateway. | |
| 38 | +| **mTLS certificate OU** | Not recommended | Implementation exists but has a TODO (see above). Use only with caution and test thoroughly against your CA's certificate format. | |
| 39 | +| **Authorization header (JWT/Bearer)** | Not parsed | The gateway does not parse or validate tokens. The upstream that sets `X-Trust-Level` is expected to do this (e.g., indieweb2-bastion in the hyperpolymath stack). | |
| 40 | +| **IP allowlist** | Not supported | The gateway does not block by IP. Rely on upstream L4/L7 filtering. | |
| 41 | + |
| 42 | +## Policy Enforcement |
| 43 | + |
| 44 | +| Feature | Status | Notes | |
| 45 | +|---------|--------|-------| |
| 46 | +| **YAML policy loading** | Supported | `PolicyLoader.load_from_file/1` reads DSL v1 files. | |
| 47 | +| **Policy validation** | Supported | `PolicyValidator.validate/1` rejects malformed policies before compilation. | |
| 48 | +| **Policy compilation to ETS** | Supported | Dual-table layout: main (exact + global) and regex. | |
| 49 | +| **Exact path matching** | Supported | O(1) via ETS `{:exact, path, verb}` keys. | |
| 50 | +| **Regex path matching** | Supported | O(r) scan of dedicated regex table. | |
| 51 | +| **Global verb rules** | Supported | Fallback when no route matches. | |
| 52 | +| **Atomic policy hot-reload** | Supported | Recompiling creates new tables and swaps app env references atomically. See `test/e2e_test.exs` hot-reload tests. | |
| 53 | +| **Per-route exposure overrides** | Supported | Route `exposure` field overrides global behaviour. | |
| 54 | +| **Stealth mode (configurable status codes)** | Supported | Default 404 hides denied endpoints. | |
| 55 | +| **Default-deny on no match** | Supported | Returns 403 (or stealth code) when no rule matches. | |
| 56 | + |
| 57 | +## Runtime Features |
| 58 | + |
| 59 | +| Feature | Status | Notes | |
| 60 | +|---------|--------|-------| |
| 61 | +| **Rate limiting (token bucket)** | Supported | Per-(IP, trust) buckets. Defaults: `untrusted` 10 req/s, `authenticated` 100 req/s, `internal` unlimited. `X-Forwarded-For` is trusted for client IP — require a trusted reverse proxy to prevent spoofing. | |
| 62 | +| **Circuit breaker** | Supported | Three-state FSM (closed/open/half_open) per backend. 5 failures to trip, 30s before half-open probe (configurable). | |
| 63 | +| **K9 service contracts** | Partial | Trust threshold enforcement works. `rate_limit` field on contracts is declared but NOT enforced. | |
| 64 | +| **Structured JSON logs** | Supported | Every access decision logged with request_id, path, verb, trust_level, decision. | |
| 65 | +| **Telemetry events** | Supported | All major events emit `[:http_capability_gateway, ...]` telemetry. | |
| 66 | +| **Health probe** | Supported | `GET /health` returns 200 with uptime. | |
| 67 | +| **Readiness probe** | Supported | `GET /ready` returns 200 iff policy is loaded. | |
| 68 | +| **Prometheus metrics** | Supported | `GET /metrics` via `TelemetryMetricsPrometheus.Core.scrape/0`. | |
| 69 | +| **Anomaly detection (Minikaran)** | Supported | `GET /api/v1/minikaran` returns current anomalies. | |
| 70 | +| **Audit log (VeriSimDB)** | Supported | Allow/deny decisions persisted asynchronously. | |
| 71 | + |
| 72 | +## Out of MVP Scope |
| 73 | + |
| 74 | +The following are explicitly **not** in the v0.1.0 MVP: |
| 75 | + |
| 76 | +- Multi-backend load balancing |
| 77 | +- TLS termination |
| 78 | +- Response caching |
| 79 | +- Request/response body transformation |
| 80 | +- Dynamic trust scoring / ML-based trust |
| 81 | +- Web UI / admin dashboard |
| 82 | +- Plugin system (auth, filters, custom loaders) |
| 83 | +- Distributed cluster coordination |
| 84 | +- Kubernetes operator |
| 85 | +- Helm chart |
| 86 | + |
| 87 | +See `ROADMAP-v2.md` for these items; they are **aspirational** and not |
| 88 | +on the release path for v0.1.0. |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +## Operator Quick Checklist |
| 93 | + |
| 94 | +Before exposing the gateway to the public internet: |
| 95 | + |
| 96 | +1. **Configure `:trusted_proxies`** — add the IP addresses of your upstream |
| 97 | + TLS-terminating proxies. Without this, direct clients can forge |
| 98 | + `X-Trust-Level: internal` and bypass all governance. |
| 99 | +2. **Do NOT rely on mTLS trust extraction** until `extract_cert_subject/1` |
| 100 | + is reviewed for your certificate format. |
| 101 | +3. **Do NOT route GraphQL or gRPC traffic through this gateway** — |
| 102 | + handlers are stubs. HTTP/REST only. |
| 103 | +4. **Set realistic `:rate_limits`** for your traffic. The test defaults |
| 104 | + are set very high for test predictability. |
| 105 | +5. **Provide a valid policy file at startup** — the application refuses |
| 106 | + to start without one (fail-closed). |
| 107 | +6. **Put a TLS-terminating proxy in front** — the gateway does not do TLS. |
| 108 | +7. **Monitor the `/metrics` endpoint** — especially |
| 109 | + `http_capability_gateway_circuit_breaker_*` and rate-limit counters. |
0 commit comments