> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference

> Complete type reference for the GBGBridge iOS framework.

Complete reference for every public type, method, and property in the GBGBridge framework.

**Module:** `GBGBridge`
**Platforms:** iOS 15.0+
**Swift:** 5.9+

***

## Table of contents

* [Primary entry points](#primary-entry-points)
  * [BridgeHost](#bridgehost)
  * [BridgeWebView](#bridgewebview)
  * [BridgeWebViewConfigurator](#bridgewebviewconfigurator)
* [Capabilities](#capabilities)
  * [CaptureCapability](#capturecapability)
  * [CaptureResult](#captureresult)
  * [DocumentCaptureResult](#documentcaptureresult)
  * [SelfieCaptureResult](#selfiecaptureresult)
  * [PermissionState](#permissionstate)
  * [CameraDetector](#cameradetector)
* [Configuration](#configuration)
  * [BridgeConfiguration](#bridgeconfiguration)
  * [BridgeCapabilityInfo](#bridgecapabilityinfo)
* [Message models](#message-models)
  * [BridgeMessage](#bridgemessage)
  * [BridgePayload](#bridgepayload)
  * [BridgeErrorPayload](#bridgeerrorpayload)
  * [BridgeMessageType](#bridgemessagetype)
  * [BridgeResponseStatus](#bridgeresponsestatus)
  * [JSONValue](#jsonvalue)
* [Protocols](#protocols)
  * [BridgeCapabilityHandler](#bridgecapabilityhandler)
  * [BridgeResponder](#bridgeresponder)
  * [BridgeHostDelegate](#bridgehostdelegate)
* [Built-in handlers](#built-in-handlers)
  * [CapabilityQueryHandler](#capabilityqueryhandler)

***

## Primary entry points

These are the types you'll interact with directly to wire the bridge into your app: a host that routes messages, a SwiftUI view that hosts the WebView, and a configurator for UIKit or custom WebView setups.

### BridgeHost

The central coordinator that manages message routing between a `WKWebView` and your native code.

```swift theme={null}
@MainActor
open class BridgeHost: NSObject, ObservableObject, WKScriptMessageHandler
```

**Why it exists:** `BridgeHost` is the main object you interact with. It decodes incoming messages from the WebView, routes requests to registered handlers, tracks pending requests, and sends responses and events back to the web journey.

**Threading:** `@MainActor` — all access must be from the main thread. This is enforced by the Swift concurrency system. In SwiftUI, use `@StateObject` or `@ObservedObject` to hold a reference.

#### Initializers

`BridgeHost` offers two initializers. Most apps should use `init(hostVersion:)`, which wires up typed capability slots automatically. Use `init(configuration:)` only when you need to declare capabilities explicitly via a dictionary.

##### init(hostVersion:) — Recommended

```swift theme={null}
public convenience init(hostVersion: String)
```

Creates a new bridge host with typed capability slots. Capability support is declared by setting handlers on the `documentCapture` and `selfieCapture` slots. The `CapabilityQueryHandler` is registered automatically with a rich provider that builds the response dynamically from typed slots and custom capabilities, including `permissionState` metadata.

| Parameter     | Type     | Description                                          |
| ------------- | -------- | ---------------------------------------------------- |
| `hostVersion` | `String` | A version string for the host app (e.g., `"1.0.0"`). |

**Example:**

```swift theme={null}
let host = BridgeHost(hostVersion: "1.0.0")

// Declare support by setting handlers
host.documentCapture.handler = { request in
    return await host.documentCapture.awaitCompletion()
}
```

***

##### init(configuration:) — Configuration-Based

```swift theme={null}
public init(configuration: BridgeConfiguration)
```

Creates a new bridge host with explicit configuration. Capabilities are declared statically in the `BridgeConfiguration` dictionary. Automatically registers a built-in `CapabilityQueryHandler` that responds to `"capability.query"` requests. Typed slots exist but are not wired into the query handler — use `register(handler:)` to add capability handlers.

| Parameter       | Type                  | Description                                           |
| --------------- | --------------------- | ----------------------------------------------------- |
| `configuration` | `BridgeConfiguration` | Declares the host version and supported capabilities. |

**Example:**

```swift theme={null}
let host = BridgeHost(
    configuration: BridgeConfiguration(
        hostVersion: "1.0.0",
        capabilities: [
            "camera.capture": BridgeCapabilityInfo(supported: true, version: "1.0")
        ]
    )
)
```

#### Published Properties

These properties are `@Published` and can be observed in SwiftUI views or via Combine subscribers.

***

##### receivedMessages

```swift theme={null}
@Published public var receivedMessages: [BridgeMessage]
```

An ordered list of all messages received from the web journey (requests, responses, and events). Messages are appended in the order they arrive. Useful for debugging or building a message log UI.

***

##### pendingRequests

```swift theme={null}
@Published public var pendingRequests: [BridgeMessage]
```

Requests from the web journey that have no registered handler. These are waiting for manual response via `respond(to:status:data:error:)`. When a response is sent for a pending request, it is removed from this list.

***

##### capabilities

```swift theme={null}
@Published public var capabilities: [String: Bool]
```

A simplified view of the declared capabilities, mapping capability identifiers to their `supported` status. Derived from the `BridgeConfiguration` at initialization.

***

##### lastError

```swift theme={null}
@Published public var lastError: String?
```

The most recent error message, if any. Set when message decoding fails, JavaScript evaluation fails, or the WebView is not attached. Call `clearError()` to reset.

***

#### Typed Capability Slots

##### documentCapture

```swift theme={null}
public let documentCapture: CaptureCapability
```

The typed slot for document capture (`camera.document`). Set `handler` to declare support. Routes requests for the `"camera.document.capture"` action.

***

##### selfieCapture

```swift theme={null}
public let selfieCapture: CaptureCapability
```

The typed slot for selfie capture (`camera.selfie`). Set `handler` to declare support. Routes requests for the `"camera.selfie.capture"` action.

***

#### Properties

##### delegate

```swift theme={null}
public weak var delegate: BridgeHostDelegate?
```

An optional delegate that receives notifications about all incoming messages and unhandled requests. Set this to observe bridge activity without registering handlers.

***

##### configuration

```swift theme={null}
public private(set) var configuration: BridgeConfiguration
```

The configuration passed at initialization. Read-only after creation.

***

#### Methods

##### register(handler:)

```swift theme={null}
public func register(handler: any BridgeCapabilityHandler)
```

Registers a capability handler. When a request arrives with an `action` matching the handler's `action` property, the handler's `handle(request:responder:)` method is called.

If a handler is already registered for the same action, it is replaced.

| Parameter | Type                          | Description              |
| --------- | ----------------------------- | ------------------------ |
| `handler` | `any BridgeCapabilityHandler` | The handler to register. |

**Example:**

```swift theme={null}
host.register(handler: DocumentCaptureHandler())
```

***

##### unregister(action:)

```swift theme={null}
public func unregister(action: String)
```

Removes the handler registered for the given action. Subsequent requests for that action will be added to `pendingRequests` instead.

| Parameter | Type     | Description                          |
| --------- | -------- | ------------------------------------ |
| `action`  | `String` | The action identifier to unregister. |

***

##### registerCustomCapability(\_:version:handler:)

```swift theme={null}
public func registerCustomCapability(
    _ id: String,
    version: String? = nil,
    handler: @escaping @Sendable (BridgeMessage, BridgeResponder) async -> Void
)
```

Registers a custom capability that appears in `capability.query` responses and handles requests for the given action. Use this for capabilities that don't have a typed slot (e.g., NFC, biometrics).

If a typed slot is registered for the same action ID, the typed slot takes precedence in both query responses and request routing.

| Parameter | Type                                                                 | Description                                                      |
| --------- | -------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `id`      | `String`                                                             | The capability/action identifier (e.g., `"nfc.read"`).           |
| `version` | `String?`                                                            | Optional version string. Defaults to `"1.0"` in query responses. |
| `handler` | `@escaping @Sendable (BridgeMessage, BridgeResponder) async -> Void` | The handler closure called when a matching request arrives.      |

**Example:**

```swift theme={null}
host.registerCustomCapability("nfc.read", version: "1.0") { request, responder in
    // Handle NFC read request
    responder.respond(status: .success, data: ["chipRead": .bool(true)], error: nil)
}
```

***

##### attach(webView:)

```swift theme={null}
public func attach(webView: WKWebView)
```

Associates a `WKWebView` with this host. Messages sent via `send(event:data:)` and `respond(to:...)` are delivered to this WebView.

You do not need to call this method if you use `BridgeWebView` or `BridgeWebViewConfigurator` — they call it automatically.

| Parameter | Type        | Description            |
| --------- | ----------- | ---------------------- |
| `webView` | `WKWebView` | The WebView to attach. |

<Note>The host holds a weak reference to the WebView. If the WebView is deallocated, sending messages will set `lastError`.</Note>

***

##### clearError()

```swift theme={null}
public func clearError()
```

Resets `lastError` to `nil`.

***

##### send(event:data:)

```swift theme={null}
public func send(event action: String, data: [String: JSONValue])
```

Sends an event message to the web journey. Events are fire-and-forget — no response is expected.

| Parameter | Type                  | Description                                               |
| --------- | --------------------- | --------------------------------------------------------- |
| `action`  | `String`              | The event action identifier (e.g., `"journey.progress"`). |
| `data`    | `[String: JSONValue]` | The event payload data.                                   |

**Example:**

```swift theme={null}
host.send(event: "host.ready", data: [
    "timestamp": .number(Date().timeIntervalSince1970)
])
```

**Error cases:** Sets `lastError` if the WebView is not attached or if JSON encoding fails.

***

##### respond(to:status:data:error:)

```swift theme={null}
public func respond(
    to correlationId: String,
    status: BridgeResponseStatus,
    data: [String: JSONValue]? = nil,
    error: BridgeErrorPayload? = nil
)
```

Sends a response to a pending request. The `correlationId` must match a message in `pendingRequests`. The matched request is removed from `pendingRequests` upon sending. The response's `action` is automatically set to the original request's action.

| Parameter       | Type                   | Description                                                       |
| --------------- | ---------------------- | ----------------------------------------------------------------- |
| `correlationId` | `String`               | The correlation ID of the request being responded to.             |
| `status`        | `BridgeResponseStatus` | The response status.                                              |
| `data`          | `[String: JSONValue]?` | Optional response data.                                           |
| `error`         | `BridgeErrorPayload?`  | Optional error details (typically set when `status` is `.error`). |

**Example:**

```swift theme={null}
host.respond(
    to: request.correlationId,
    status: .success,
    data: ["imagePath": .string("/tmp/capture.jpg")]
)
```

***

##### respond(to:action:status:data:error:)

```swift theme={null}
public func respond(
    to correlationId: String,
    action: String,
    status: BridgeResponseStatus,
    data: [String: JSONValue]? = nil,
    error: BridgeErrorPayload? = nil
)
```

Sends a response with an explicit action. This overload does not look up `pendingRequests` — it sends directly. Use this from within a `BridgeCapabilityHandler` via the `BridgeResponder`, or when you need to respond to a request that may not be in the pending list.

| Parameter       | Type                   | Description                             |
| --------------- | ---------------------- | --------------------------------------- |
| `correlationId` | `String`               | The correlation ID of the request.      |
| `action`        | `String`               | The action identifier for the response. |
| `status`        | `BridgeResponseStatus` | The response status.                    |
| `data`          | `[String: JSONValue]?` | Optional response data.                 |
| `error`         | `BridgeErrorPayload?`  | Optional error details.                 |

***

##### userContentController(\_:didReceive:)

```swift theme={null}
public func userContentController(
    _ userContentController: WKUserContentController,
    didReceive message: WKScriptMessage
)
```

`WKScriptMessageHandler` conformance. Called by WebKit when the web journey sends a message via `window.webkit.messageHandlers.gbgBridge.postMessage()`. You should not call this method directly.

***

### BridgeWebView

A SwiftUI view that displays a web journey inside a bridge-connected `WKWebView`.

```swift theme={null}
public struct BridgeWebView: UIViewRepresentable
```

**Why it exists:** Provides the simplest integration path for SwiftUI apps. Handles WebView creation, configuration, bootstrap script injection, message handler registration, and URL loading.

#### Initializer

```swift theme={null}
public init(url: URL, host: BridgeHost)
```

| Parameter | Type         | Description                             |
| --------- | ------------ | --------------------------------------- |
| `url`     | `URL`        | The URL of the web journey to load.     |
| `host`    | `BridgeHost` | The bridge host that manages messaging. |

**Example:**

```swift theme={null}
BridgeWebView(
    url: URL(string: "https://journey.example.com")!,
    host: host
)
```

#### Properties

##### url

```swift theme={null}
public let url: URL
```

The journey URL. If this value changes, the WebView navigates to the new URL (unless the normalized URL is unchanged).

***

##### host

```swift theme={null}
@ObservedObject public var host: BridgeHost
```

The bridge host. Observed so that SwiftUI can react to state changes (e.g., `lastError`, `receivedMessages`).

***

#### Coordinator

```swift theme={null}
public final class Coordinator: NSObject, WKNavigationDelegate
```

The WebView's navigation delegate. Currently provides default behavior. You can subclass `BridgeWebView.Coordinator` for custom navigation handling.

***

### BridgeWebViewConfigurator

A utility for configuring a `WKWebView` with the bridge infrastructure. Use this when you need more control than `BridgeWebView` provides — for example, in UIKit-based apps or when you need a custom WebView configuration.

```swift theme={null}
public struct BridgeWebViewConfigurator
```

**Why it exists:** Separates WebView setup from display. You can configure an existing WebView or create a new one with all bridge wiring in place.

#### Static Methods

##### configure(\_:host:)

```swift theme={null}
@MainActor
public static func configure(_ webView: WKWebView, host: BridgeHost)
```

Configures an existing `WKWebView` with the bridge:

1. Injects the bootstrap user script at document start.
2. Registers the `BridgeHost` as the handler for the `"gbgBridge"` script message channel.
3. Attaches the WebView to the host.

| Parameter | Type         | Description               |
| --------- | ------------ | ------------------------- |
| `webView` | `WKWebView`  | The WebView to configure. |
| `host`    | `BridgeHost` | The bridge host.          |

**Example:**

```swift theme={null}
let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
BridgeWebViewConfigurator.configure(webView, host: host)
```

***

##### makeWebView(host:)

```swift theme={null}
@MainActor
public static func makeWebView(host: BridgeHost) -> WKWebView
```

Creates and returns a new `WKWebView` that is fully configured with the bridge. Equivalent to creating a `WKWebView` and calling `configure(_:host:)`.

| Parameter | Type         | Description      |
| --------- | ------------ | ---------------- |
| `host`    | `BridgeHost` | The bridge host. |

**Returns:** A configured `WKWebView` instance.

***

## Capabilities

### CaptureCapability

A typed capability slot that represents a capture operation (document or selfie). Setting a `handler` declares support; the SDK handles routing, result encoding, and busy rejection automatically.

```swift theme={null}
@MainActor
public class CaptureCapability: ObservableObject
```

**Why it exists:** Eliminates the need to manually build `BridgeCapabilityInfo` dictionaries, encode capture results into `JSONValue`, and keep capability declarations in sync with handler registrations. Setting a handler is the declaration.

#### Initializer

```swift theme={null}
public init(id: String, actionId: String, version: String? = nil)
```

You typically don't create `CaptureCapability` instances directly — use the built-in slots on `BridgeHost` (`documentCapture`, `selfieCapture`).

#### Properties

| Property          | Type                                                  | Description                                                                                                                |
| ----------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `id`              | `String`                                              | The capability identifier (e.g., `"camera.document"`).                                                                     |
| `actionId`        | `String`                                              | The bridge action this slot handles (e.g., `"camera.document.capture"`).                                                   |
| `handler`         | `(@Sendable (BridgeMessage) async -> CaptureResult)?` | The handler closure. Setting this declares support.                                                                        |
| `isEnabled`       | `Bool`                                                | Runtime toggle. When `false`, the slot reports as unsupported even if a handler is set. Default: `true`. `@Published`.     |
| `isSupported`     | `Bool`                                                | Computed: `handler != nil && isEnabled`.                                                                                   |
| `activeRequest`   | `BridgeMessage?`                                      | The currently in-flight request, or `nil`. `@Published`. Use this to drive SwiftUI presentation (e.g., `fullScreenCover`). |
| `permissionState` | `PermissionState`                                     | The current permission state for this capability. Included in query responses. Default: `.notDetermined`.                  |
| `version`         | `String?`                                             | Optional version override. Defaults to `"1.0"` in query responses when supported.                                          |

#### Methods

These methods drive capability handling at runtime — building query responses, awaiting capture completion, and signalling cancellation:

##### buildCapabilityInfo()

```swift theme={null}
public func buildCapabilityInfo() -> BridgeCapabilityInfo
```

Returns a `BridgeCapabilityInfo` reflecting the slot's current state. Used internally to build `capability.query` responses.

***

##### awaitCompletion()

```swift theme={null}
public func awaitCompletion() async -> CaptureResult
```

Suspends the current handler until `complete(_:)` is called. Use this in handlers that drive SwiftUI-presented camera UI rather than imperative capture APIs.

**Example:**

```swift theme={null}
host.documentCapture.handler = { [weak host] request in
    guard let host else { return .cancelled(reason: "Host deallocated") }
    return await host.documentCapture.awaitCompletion()
}
```

***

##### complete(\_:)

```swift theme={null}
public func complete(_ result: CaptureResult)
```

Resumes the pending handler with a capture result. Call from view-layer code (e.g., camera callback closures) to complete the flow.

**Example:**

```swift theme={null}
// In a camera completion handler:
host.documentCapture.complete(.document(DocumentCaptureResult(
    imageData: imageData,
    width: 1920,
    height: 1080
)))
```

***

### CaptureResult

A strongly-typed result returned by capture handlers.

```swift theme={null}
public enum CaptureResult: Sendable
```

**Why it exists:** Eliminates manual `JSONValue` dictionary construction. The SDK converts `CaptureResult` values to the bridge protocol format automatically.

#### Cases

| Case                                                        | Description                                                               |
| ----------------------------------------------------------- | ------------------------------------------------------------------------- |
| `.document(DocumentCaptureResult)`                          | Successful document capture with image data and dimensions.               |
| `.selfie(SelfieCaptureResult)`                              | Successful selfie capture with preview image and encrypted blobs.         |
| `.cancelled(reason: String)`                                | User cancelled the operation. Sends a `.cancelled` response.              |
| `.failed(code: String, message: String, recoverable: Bool)` | Operation failed. Sends an `.error` response with a `BridgeErrorPayload`. |

***

### DocumentCaptureResult

Result data for a successful document capture.

```swift theme={null}
public struct DocumentCaptureResult: Sendable
```

#### Initializer

```swift theme={null}
public init(imageData: Data, width: Int, height: Int, mimeType: String = "image/png")
```

| Parameter   | Type     | Default       | Description                                                     |
| ----------- | -------- | ------------- | --------------------------------------------------------------- |
| `imageData` | `Data`   | —             | The captured image data. Base64-encoded in the bridge response. |
| `width`     | `Int`    | —             | Image width in pixels.                                          |
| `height`    | `Int`    | —             | Image height in pixels.                                         |
| `mimeType`  | `String` | `"image/png"` | The MIME type of the image data.                                |

**Bridge response data:**

```json theme={null}
{
  "imageBase64": "<base64-encoded image>",
  "imageWidth": 1920,
  "imageHeight": 1080,
  "mimeType": "image/png"
}
```

***

### SelfieCaptureResult

Result data for a successful selfie capture.

```swift theme={null}
public struct SelfieCaptureResult: Sendable
```

#### Initializer

```swift theme={null}
public init(
    previewImageData: Data,
    width: Int,
    height: Int,
    mimeType: String = "image/jpeg",
    encryptedBlob: Data,
    unencryptedBlob: Data
)
```

| Parameter          | Type     | Default        | Description                                                             |
| ------------------ | -------- | -------------- | ----------------------------------------------------------------------- |
| `previewImageData` | `Data`   | —              | Preview image data. Base64-encoded in the bridge response.              |
| `width`            | `Int`    | —              | Image width in pixels.                                                  |
| `height`           | `Int`    | —              | Image height in pixels.                                                 |
| `mimeType`         | `String` | `"image/jpeg"` | The MIME type of the preview image.                                     |
| `encryptedBlob`    | `Data`   | —              | Encrypted biometric data blob. Base64-encoded in the bridge response.   |
| `unencryptedBlob`  | `Data`   | —              | Unencrypted biometric data blob. Base64-encoded in the bridge response. |

**Bridge response data:**

```json theme={null}
{
  "imageBase64": "<base64>",
  "imageWidth": 640,
  "imageHeight": 480,
  "mimeType": "image/jpeg",
  "encryptedBlobBase64": "<base64>",
  "unencryptedBlobBase64": "<base64>"
}
```

***

### PermissionState

The current authorization status for a native capability.

```swift theme={null}
public enum PermissionState: String, Codable, Sendable
```

| Case             | Raw Value         | Description                                       |
| ---------------- | ----------------- | ------------------------------------------------- |
| `.granted`       | `"granted"`       | Permission has been granted.                      |
| `.denied`        | `"denied"`        | Permission has been explicitly denied.            |
| `.notDetermined` | `"notDetermined"` | Permission has not been requested yet.            |
| `.restricted`    | `"restricted"`    | Permission is restricted by device management.    |
| `.notApplicable` | `"notApplicable"` | Permission is not applicable for this capability. |

***

### CameraDetector

A utility for detecting camera hardware availability and permission status.

```swift theme={null}
public struct CameraDetector
```

**Why it exists:** Provides a simple way to populate `permissionState` on capture slots without writing AVFoundation boilerplate.

#### Static Methods

##### check()

```swift theme={null}
public static func check() -> CameraDetector.Result
```

Checks camera hardware availability using `AVCaptureDevice.default(for: .video)` and permission status using `AVCaptureDevice.authorizationStatus(for: .video)`.

**Returns:** A `CameraDetector.Result` with hardware and permission info.

#### CameraDetector.Result

```swift theme={null}
public struct Result: Sendable {
    public let hardwareAvailable: Bool
    public let permissionState: PermissionState
}
```

| Property            | Type              | Description                                                 |
| ------------------- | ----------------- | ----------------------------------------------------------- |
| `hardwareAvailable` | `Bool`            | Whether camera hardware was detected. `false` on Simulator. |
| `permissionState`   | `PermissionState` | Maps from `AVAuthorizationStatus` to `PermissionState`.     |

Example:

```swift theme={null}
let camera = CameraDetector.check()
host.documentCapture.permissionState = camera.permissionState
host.selfieCapture.permissionState = camera.permissionState
```

***

## Configuration

### BridgeConfiguration

Declares the host application's version and supported capabilities.

```swift theme={null}
public struct BridgeConfiguration: Sendable
```

**Why it exists:** Provides a single configuration object that `BridgeHost` uses to initialize capability state and respond to capability queries from the web journey.

#### Initializer

```swift theme={null}
public init(
    hostVersion: String,
    capabilities: [String: BridgeCapabilityInfo],
    bootstrapScript: String? = nil
)
```

| Parameter         | Type                             | Default | Description                                                                                              |
| ----------------- | -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| `hostVersion`     | `String`                         | —       | A version string for the host app (e.g., `"1.0.0"`). Reported to the web journey via capability queries. |
| `capabilities`    | `[String: BridgeCapabilityInfo]` | —       | A dictionary mapping capability identifiers to their support status and metadata.                        |
| `bootstrapScript` | `String?`                        | `nil`   | Optional custom JavaScript to inject at document start. If `nil`, a default script is used.              |

#### Properties

| Property          | Type                             | Description                                            |
| ----------------- | -------------------------------- | ------------------------------------------------------ |
| `hostVersion`     | `String`                         | The host app version string.                           |
| `capabilities`    | `[String: BridgeCapabilityInfo]` | Capability declarations.                               |
| `bootstrapScript` | `String?`                        | Custom bootstrap JavaScript, or `nil` for the default. |

***

### BridgeCapabilityInfo

Metadata about a single capability.

```swift theme={null}
public struct BridgeCapabilityInfo: Codable, Sendable
```

**Why it exists:** Allows the host to express not just whether a capability is supported, but also its version and any constraints (e.g., maximum resolution, supported document types).

#### Initializer

```swift theme={null}
public init(
    supported: Bool,
    version: String? = nil,
    constraints: [String: JSONValue]? = nil,
    permissionState: String? = nil
)
```

| Parameter         | Type                   | Default | Description                                                                                                        |
| ----------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `supported`       | `Bool`                 | —       | Whether the capability is available.                                                                               |
| `version`         | `String?`              | `nil`   | The capability implementation version.                                                                             |
| `constraints`     | `[String: JSONValue]?` | `nil`   | Arbitrary key-value constraints (e.g., `"maxResolution": .number(4096)`).                                          |
| `permissionState` | `String?`              | `nil`   | The native permission status (e.g., `"granted"`, `"denied"`). Included in capability query responses when non-nil. |

#### Properties

| Property          | Type                   | Description                                                         |
| ----------------- | ---------------------- | ------------------------------------------------------------------- |
| `supported`       | `Bool`                 | Whether the capability is available.                                |
| `version`         | `String?`              | Implementation version, if any.                                     |
| `constraints`     | `[String: JSONValue]?` | Arbitrary constraints.                                              |
| `permissionState` | `String?`              | Native permission status. Included in query responses when non-nil. |

***

## Message models

Every value that crosses the bridge is wrapped in a `BridgeMessage` envelope, which carries a typed payload, a correlation ID, and a status. The types in this section describe that envelope and the shapes you'll embed inside it.

### BridgeMessage

A structured envelope for all bridge communication.

```swift theme={null}
public struct BridgeMessage: Codable, Identifiable, Sendable
```

**Why it exists:** Provides a consistent, type-safe format for all messages exchanged between the web journey and the native host. The `Identifiable` conformance enables use in SwiftUI lists.

#### Initializer

```swift theme={null}
public init(
    version: String,
    correlationId: String,
    type: BridgeMessageType,
    timestamp: TimeInterval,
    payload: BridgePayload
)
```

| Parameter       | Type                | Description                                         |
| --------------- | ------------------- | --------------------------------------------------- |
| `version`       | `String`            | Protocol version (currently `"1.0"`).               |
| `correlationId` | `String`            | Unique identifier for request-response correlation. |
| `type`          | `BridgeMessageType` | Message type: `.request`, `.response`, or `.event`. |
| `timestamp`     | `TimeInterval`      | Milliseconds since Unix epoch.                      |
| `payload`       | `BridgePayload`     | The message payload.                                |

#### Properties

| Property        | Type                | Description                                               |
| --------------- | ------------------- | --------------------------------------------------------- |
| `version`       | `String`            | Protocol version.                                         |
| `correlationId` | `String`            | Correlation identifier.                                   |
| `type`          | `BridgeMessageType` | Message type.                                             |
| `timestamp`     | `TimeInterval`      | Timestamp in milliseconds.                                |
| `payload`       | `BridgePayload`     | Message payload.                                          |
| `id`            | `String`            | Computed. Format: `"{correlationId}-{timestamp}-{type}"`. |

***

### BridgePayload

The payload carried within a `BridgeMessage`.

```swift theme={null}
public struct BridgePayload: Codable, Sendable
```

#### Initializer

```swift theme={null}
public init(
    action: String,
    data: [String: JSONValue]?,
    status: BridgeResponseStatus?,
    error: BridgeErrorPayload?
)
```

| Parameter | Type                    | Description                                                             |
| --------- | ----------------------- | ----------------------------------------------------------------------- |
| `action`  | `String`                | The action identifier (e.g., `"camera.capture"`, `"capability.query"`). |
| `data`    | `[String: JSONValue]?`  | Arbitrary typed JSON data.                                              |
| `status`  | `BridgeResponseStatus?` | Response status (only present in response messages).                    |
| `error`   | `BridgeErrorPayload?`   | Error details (only present when status is `.error`).                   |

#### Properties

| Property | Type                    | Description        |
| -------- | ----------------------- | ------------------ |
| `action` | `String`                | Action identifier. |
| `data`   | `[String: JSONValue]?`  | Payload data.      |
| `status` | `BridgeResponseStatus?` | Response status.   |
| `error`  | `BridgeErrorPayload?`   | Error details.     |

***

### BridgeErrorPayload

Structured error information included in error responses.

```swift theme={null}
public struct BridgeErrorPayload: Codable, Sendable
```

**Why it exists:** Provides machine-readable error codes alongside human-readable messages, plus a `recoverable` flag that tells the web journey whether it should retry or fail.

#### Initializer

```swift theme={null}
public init(code: String, message: String, recoverable: Bool)
```

| Parameter     | Type     | Description                                                                   |
| ------------- | -------- | ----------------------------------------------------------------------------- |
| `code`        | `String` | A machine-readable error code (e.g., `"CAMERA_DENIED"`, `"NFC_UNAVAILABLE"`). |
| `message`     | `String` | A human-readable error description.                                           |
| `recoverable` | `Bool`   | Whether the error is recoverable (e.g., user can retry).                      |

#### Properties

| Property      | Type     | Description                   |
| ------------- | -------- | ----------------------------- |
| `code`        | `String` | Error code.                   |
| `message`     | `String` | Error description.            |
| `recoverable` | `Bool`   | Whether recovery is possible. |

***

### BridgeMessageType

The type of a bridge message.

```swift theme={null}
public enum BridgeMessageType: String, Codable, Sendable
```

| Case        | Raw Value    | Description                                         |
| ----------- | ------------ | --------------------------------------------------- |
| `.request`  | `"request"`  | A request from the web journey to the native host.  |
| `.response` | `"response"` | A response from the native host to the web journey. |
| `.event`    | `"event"`    | An asynchronous notification (either direction).    |

***

### BridgeResponseStatus

The status of a response message.

```swift theme={null}
public enum BridgeResponseStatus: String, Codable, Sendable
```

| Case            | Raw Value        | When to use                                           |
| --------------- | ---------------- | ----------------------------------------------------- |
| `.success`      | `"success"`      | The operation completed successfully.                 |
| `.error`        | `"error"`        | The operation failed. Include a `BridgeErrorPayload`. |
| `.cancelled`    | `"cancelled"`    | The user cancelled the operation.                     |
| `.unsupported`  | `"unsupported"`  | The requested capability is not available.            |
| `.acknowledged` | `"acknowledged"` | The request was received; result will follow.         |

***

### JSONValue

A type-safe representation of arbitrary JSON values.

```swift theme={null}
public enum JSONValue: Codable, Sendable
```

**Why it exists:** Swift's type system doesn't natively represent heterogeneous JSON. `JSONValue` provides a recursive enum that maps directly to JSON types, enabling type-safe construction and pattern matching of arbitrary payloads.

#### Cases

| Case                           | Associated Value    | JSON Equivalent      |
| ------------------------------ | ------------------- | -------------------- |
| `.string(String)`              | A string value      | `"hello"`            |
| `.number(Double)`              | A numeric value     | `42`, `3.14`         |
| `.bool(Bool)`                  | A boolean value     | `true`, `false`      |
| `.object([String: JSONValue])` | A dictionary        | `{ "key": "value" }` |
| `.array([JSONValue])`          | An array            | `[1, 2, 3]`          |
| `.null`                        | No associated value | `null`               |

#### Properties

##### anyValue

```swift theme={null}
public var anyValue: Any
```

Converts the `JSONValue` to its Foundation equivalent (`String`, `Double`, `Bool`, `[String: Any]`, `[Any]`, or `NSNull`). Useful for interoperating with APIs that expect `Any`.

#### Codable Conformance

`JSONValue` automatically decodes from and encodes to standard JSON. The decoding order is: null → bool → number → string → object → array.

**Example — constructing a payload:**

```swift theme={null}
let data: [String: JSONValue] = [
    "name": .string("John Doe"),
    "age": .number(30),
    "verified": .bool(true),
    "documents": .array([
        .object(["type": .string("passport"), "number": .string("AB123456")])
    ]),
    "metadata": .null
]
```

***

## Protocols

### BridgeCapabilityHandler

The interface for objects that handle specific bridge request actions.

```swift theme={null}
public protocol BridgeCapabilityHandler: AnyObject, Sendable
```

**Why it exists:** Defines the contract for capability implementations. Each handler is responsible for a single action and receives a responder to send its result back to the web journey.

#### Requirements

##### action

```swift theme={null}
var action: String { get }
```

The action identifier this handler responds to (e.g., `"camera.document.capture"`, `"nfc.read"`). Must be unique per `BridgeHost` — registering a handler with the same action replaces the previous one.

***

##### handle(request:responder:)

```swift theme={null}
func handle(request: BridgeMessage, responder: BridgeResponder) async
```

Called when a request arrives with a matching action. Perform your native operation and call `responder.respond(...)` when done.

| Parameter   | Type              | Description                                                                         |
| ----------- | ----------------- | ----------------------------------------------------------------------------------- |
| `request`   | `BridgeMessage`   | The incoming request message. Access `request.payload.data` for request parameters. |
| `responder` | `BridgeResponder` | A callback to send the response. Call exactly once.                                 |

**Threading:** This method is `async` and runs in a `Task` dispatched by `BridgeHost`. You can safely `await` async operations, present UI (from the main actor), and perform background work.

**Example:**

```swift theme={null}
public final class DocumentCaptureHandler: BridgeCapabilityHandler, @unchecked Sendable {
    public let action = "camera.document.capture"

    public func handle(request: BridgeMessage, responder: BridgeResponder) async {
        // Extract parameters from the request
        let side = request.payload.data?["side"] // .string("front") or .string("back")

        // Perform capture (your implementation)
        do {
            let imageData = try await captureDocument()
            responder.respond(
                status: .success,
                data: ["imageBase64": .string(imageData.base64EncodedString())],
                error: nil
            )
        } catch {
            responder.respond(
                status: .error,
                data: nil,
                error: BridgeErrorPayload(
                    code: "CAPTURE_FAILED",
                    message: error.localizedDescription,
                    recoverable: true
                )
            )
        }
    }
}
```

***

### BridgeResponder

A callback interface used to send a response from a capability handler back to the web journey.

```swift theme={null}
public protocol BridgeResponder: Sendable
```

**Why it exists:** Decouples the handler from `BridgeHost` internals. Handlers don't need to know about WebViews or JavaScript evaluation — they simply call `respond()`.

#### Requirements

##### respond(status:data:error:)

```swift theme={null}
func respond(
    status: BridgeResponseStatus,
    data: [String: JSONValue]?,
    error: BridgeErrorPayload?
)
```

Sends a response to the web journey for the associated request.

| Parameter | Type                   | Description                |
| --------- | ---------------------- | -------------------------- |
| `status`  | `BridgeResponseStatus` | The response status.       |
| `data`    | `[String: JSONValue]?` | Optional response payload. |
| `error`   | `BridgeErrorPayload?`  | Optional error details.    |

**Threading:** Safe to call from any thread. The internal implementation dispatches to the main actor.

<Note>Call this method exactly once per request. Calling it multiple times has no effect (the first call wins for request correlation).</Note>

***

### BridgeHostDelegate

An observer protocol for monitoring bridge activity.

```swift theme={null}
@MainActor
public protocol BridgeHostDelegate: AnyObject
```

**Why it exists:** Provides a way to observe all bridge messages and react to unhandled requests without registering a handler. Useful for logging, analytics, or building custom request handling logic.

#### Methods

##### bridgeHost(\_:didReceive:)

```swift theme={null}
func bridgeHost(_ host: BridgeHost, didReceive message: BridgeMessage)
```

Called for every message received from the web journey, regardless of type. Default implementation does nothing.

| Parameter | Type            | Description                                |
| --------- | --------------- | ------------------------------------------ |
| `host`    | `BridgeHost`    | The bridge host that received the message. |
| `message` | `BridgeMessage` | The received message.                      |

***

##### bridgeHost(\_:unhandledRequest:)

```swift theme={null}
func bridgeHost(_ host: BridgeHost, unhandledRequest message: BridgeMessage)
```

Called when a request arrives with no registered handler. The request is also added to `host.pendingRequests`. Default implementation does nothing.

| Parameter | Type            | Description            |
| --------- | --------------- | ---------------------- |
| `host`    | `BridgeHost`    | The bridge host.       |
| `message` | `BridgeMessage` | The unhandled request. |

***

## Built-in handlers

### CapabilityQueryHandler

A built-in handler that responds to `"capability.query"` requests with the host's declared capabilities.

```swift theme={null}
public final class CapabilityQueryHandler: BridgeCapabilityHandler, @unchecked Sendable
```

**Why it exists:** Capability negotiation is fundamental to the bridge protocol. This handler is automatically registered by `BridgeHost` so the web journey can always discover available capabilities.

**Action:** `"capability.query"`

#### Initializers

##### Simple Provider

```swift theme={null}
public init(
    capabilities: @escaping () -> [String: Bool],
    hostVersion: String
)
```

Creates a query handler with a simple boolean capability map. Used by `init(configuration:)`.

| Parameter      | Type                             | Description                                                              |
| -------------- | -------------------------------- | ------------------------------------------------------------------------ |
| `capabilities` | `@escaping () -> [String: Bool]` | A closure that returns the current capability map. Called on each query. |
| `hostVersion`  | `String`                         | The host version string to include in the response.                      |

##### Rich Provider

```swift theme={null}
public init(
    richCapabilities: @escaping () -> [String: BridgeCapabilityInfo],
    hostVersion: String
)
```

Creates a query handler with full capability metadata including `permissionState`. Used by `init(hostVersion:)`.

| Parameter          | Type                                             | Description                                                        |
| ------------------ | ------------------------------------------------ | ------------------------------------------------------------------ |
| `richCapabilities` | `@escaping () -> [String: BridgeCapabilityInfo]` | A closure that returns rich capability info. Called on each query. |
| `hostVersion`      | `String`                                         | The host version string to include in the response.                |

<Note>You rarely need to create either initializer directly. `BridgeHost` creates and registers the appropriate one automatically.</Note>

#### Response Format

When the web journey sends a `capability.query` request, the response `data` contains:

```json theme={null}
{
  "environment": "ios",
  "hostVersion": "1.0.0",
  "capabilities": {
    "camera.document": {
      "supported": true,
      "version": "1.0",
      "permissionState": "granted"
    },
    "camera.selfie": {
      "supported": false,
      "version": null
    }
  }
}
```

| Field                              | Type      | Description                                                                    |
| ---------------------------------- | --------- | ------------------------------------------------------------------------------ |
| `environment`                      | `String`  | Always `"ios"` for this framework.                                             |
| `hostVersion`                      | `String`  | The host version from configuration.                                           |
| `capabilities`                     | `Object`  | Map of capability ID → `{ supported, version, permissionState? }`.             |
| `capabilities[id].permissionState` | `String?` | Present when the capability provides permission metadata (rich provider only). |
