package bulwark:plugin; /* TODO: See https://github.com/WebAssembly/wasi-http for a more complete canonical http component interface */ /* TODO: request/response bodies might be better handled as resource types? see: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#item-resource */ world host-api { /* TODO: should these strings all be list? */ record request-interface { method: string, uri: string, version: string, headers: list>>, body-received: bool, chunk: list, chunk-start: u64, chunk-length: u64, end-of-stream: bool, } record response-interface { status: u32, headers: list>>, body-received: bool, chunk: list, chunk-start: u64, chunk-length: u64, end-of-stream: bool, } variant ip-interface { v4(tuple), v6(tuple), } record decision-interface { accepted: float64, restricted: float64, unknown: float64, } enum outcome-interface { restricted, suspected, accepted, trusted, } record rate-interface { attempts: s64, expiration: s64, } record breaker-interface { generation: s64, successes: s64, failures: s64, consecutive-successes: s64, consecutive-failures: s64, expiration: s64, } variant env-error { missing(string), not-unicode(string), permission(string), } variant decision-error { invalid(string), } variant param-error { json(string), } variant state-error { permission(string), remote(string), } variant http-error { permission(string), invalid-method(string), invalid-uri(string), transmit(string), unavailable-content(string), invalid-start(string), content-too-large(string), } /* TODO: many of these should return the result type; historically this wasn't supported but this should be fixed? */ import get-config: func() -> list; import get-param-value: func(key: string) -> result, param-error>; import set-param-value: func(key: string, value: list) -> result<_, param-error>; import get-env-bytes: func(key: string) -> result, env-error>; import get-request: func() -> request-interface; import get-response: func() -> option; import receive-request-body: func(body: bool); import receive-response-body: func(body: bool); import get-client-ip: func() -> option; import set-decision: func(decision: decision-interface) -> result<_, decision-error>; import set-tags: func(tags: list); import append-tags: func(tags: list) -> list; import get-combined-decision: func() -> option; import get-combined-tags: func() -> option>; import get-outcome: func() -> option; import get-remote-state: func(key: string) -> result, state-error>; import set-remote-state: func(key: string, value: list) -> result<_, state-error>; import increment-remote-state: func(key: string) -> result; import increment-remote-state-by: func(key: string, delta: s64) -> result; import set-remote-ttl: func(key: string, ttl: s64) -> result<_, state-error>; import send-request: func(request: request-interface) -> result; import increment-rate-limit: func(key: string, delta: s64, window: s64) -> result; import check-rate-limit: func(key: string) -> result; import increment-breaker: func(key: string, success-delta: s64, failure-delta: s64, window: s64) -> result; import check-breaker: func(key: string) -> result; } world handlers { export on-init: func() -> result; export on-request: func() -> result; export on-request-decision: func() -> result; export on-response-decision: func() -> result; export on-request-body-decision: func() -> result; export on-response-body-decision: func() -> result; export on-decision-feedback: func() -> result; }