From 40593c340443cf44993c5152cc3b59ece1a60451 Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Mon, 27 Oct 2025 16:11:04 -0400 Subject: [PATCH 01/25] small deployment status updates Signed-off-by: Armand Craig --- .../margo-management-interface/deployment-status.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system-design/specification/margo-management-interface/deployment-status.md b/system-design/specification/margo-management-interface/deployment-status.md index 08975dd..1fb25b3 100644 --- a/system-design/specification/margo-management-interface/deployment-status.md +++ b/system-design/specification/margo-management-interface/deployment-status.md @@ -1,6 +1,6 @@ # Deployment Status -While applying a new desired state, the device's management client MUST provide the Workload Fleet Manager service with an indication of the current workload deployment status. This is done by calling the Device API's `device status` endpoint. +While applying a new desired state, the device's management client MUST provide the Workload Fleet Manager service with an indication of the current workload deployment status. This is done by calling the Device API's `deployment status` endpoint. ### Route and HTTP Methods @@ -31,7 +31,7 @@ POST /api/v1/device/{deviceId}/deployment/{deploymentId}/status | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| -| state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: Pending, Installing, Installed, Failed. The overall deployment status MUST inherit the current component's status until it has gone through installing each component.| +| state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: Pending, Installing, Installed, Removing, Removed, Failed. The overall deployment status MUST inherit the current component's status until it has gone through installing each component.| | error | Error | N | Element that defines the overall installation error if one occured. See the [Error Fields](#error-fields) section below.| #### Component Fields @@ -39,7 +39,7 @@ POST /api/v1/device/{deviceId}/deployment/{deploymentId}/status | Attribute | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| | name | string | Y | Name of the deployment component, inherited via the deployment specification | -| state | string | Y | The component's current deployment state of the component. MUST be one of the following options: Pending, Installing, Installed, Failed | +| state | string | Y | The component's current deployment state of the component. MUST be one of the following options: Pending, Installing, Installed, Removing, Removed, Failed | | error | Error | N | Element that defines the components installation error if one occured. See the [Error Fields](#error-fields) section below. | #### Error Fields From b5a70406f5ac875c9c96b2b95476ab6ef6a14c9a Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Wed, 29 Oct 2025 16:45:14 -0400 Subject: [PATCH 02/25] Initial content injection from approved SUP Signed-off-by: Armand Craig --- .../api-requirements-and-security.md | 150 ++++++++++++------ .../device-onboarding.md | 64 ++++++-- 2 files changed, 151 insertions(+), 63 deletions(-) diff --git a/system-design/specification/margo-management-interface/api-requirements-and-security.md b/system-design/specification/margo-management-interface/api-requirements-and-security.md index e4e26f1..e0489c4 100644 --- a/system-design/specification/margo-management-interface/api-requirements-and-security.md +++ b/system-design/specification/margo-management-interface/api-requirements-and-security.md @@ -8,62 +8,114 @@ Below is a breakdown of the three major categories these requirements fall under 1. Basic functions for supporting the Management Interface - Onboarding of the management interface client 2. Workload management functions - - Set workload(s) desired state - - Report the workload's deployment status -3. Device or Client Specific Functions - - Device Bootstrap (To be further defined by Margo) - - Device Onboarding (To be further defined by Margo) - - Device Software Runtime Management (To be further defined by Margo) + - Set Desired State(s) assigned to particular device clients +3. Device client specific functions + - Client Onboarding - Device Capability Reporting + - Workload Status deployment reporting + +### API Technical Overview +#### REST API Definition +The REST API is defined via the Open API Specification. + +- Follow the link below to see the specification: + - [OPEN API SPEC](https://github.com/margo/specification-enhancements/blob/api-details-finalization-wip/submitted/api-details-finalization-SUP-folder/margo_workload_api_wip.yaml) +> Note: This definition is a work in progress +#### General Rest API information +Server-side TLS REST API MUST be utilized operating over HTTP1.1. + +- The motivation to utilize HTTP1.1 is to ensure maximum support for existing infrastructure within our install base. +- Server-side tls is utilized instead of mTLS due to possible issues with TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection. See [Security and Integrity](#security-and-integrity-information) section for more details. +- This REST API should utilize a known root CA the client can download, which enables the TLS handshake and other onboarding credentials. + +#### Authentication Mechanism +Initial trust is accomplished via TLS version 1.3 or greater + +- The device establishes a secure HTTPS connection using server-side TLS. +- It validates the server’s identity using the public root CA certificate. + +#### API Port Details + +This API is designed to minimize the ports required on the customer's infrastructure to enable cloud to edge communication. + -The API MUST ONLY utilize port 443 for it's traffic. + +#### Unique Identifiers + +The WFM MUST create create a URL safe client id to uniquely identify each client within the architecture. + +- This client ID MAY be in the format of UUIDv4 +- Other URL safe string identifiers are permitted to be used + +> Note: This does introduce a change in philosophy regarding the unique identifier, changing towards a more flexible client id that is separate from device id. + +#### Certificate Information +Both the WFM and Device client MUST utilize a x.509 certificates to represent themselves within the API interactions. + +- These certificates are utilized to prove each participants identity, establish secure TLS session, and securely transport information in secure envelopes. +- This proposal supports client authentication using X.509 certificates conforming to RFC 5280. Both RSA and ECC-based public key algorithms are accepted. + +> Note: Further investigation and clarity to come regarding Margo's position on the root CA mentioned. -## Basic functions for supporting the Management Interface -### Onboarding of the Management Interface Client -> Note: This section will be completed in a future SUP submission. #### Support for Extended Device Communications Downtime -- Interface patterns MUST support extended device communication downtime. +Interface patterns MUST support extended device communication downtime. + - The Management Interface MUST allow an end user to configure the following: - Downtime configuration - ensures the device's management client is not retrying communication when operating under a known downtime. Additionally, communication errors MUST be ignored during this configurable period. - Polling Interval Period - describes a configurable time period indicating the hours in which the device's management client checks for updates to the device's desired state. - Polling Interval Rate - describes the rate for how frequently the device's management client checks for updates to the device's desire state. - Running the device's management client as containerized services is preferred. By following Margo application packaging guidelines, it makes the management interface easier to lifecycle manage, however this is not required. -## API Security Requirements -> Note: The content documented below is still being finalized within the community, SUP process will be started shortly to finalize. -### Margo Web API Authentication Method -The Margo Web API communication pattern between the device's management client and the Workload Fleet Manager web service must use a secure communication channel. -### Authentication and Authorization using Certificates -> Note: This section will be completed in a future SUP submission. -### Unique Identifiers for the Workload Fleet Manager and Device's Management Interface Relationship -> Note: This section will be completed in a future SUP submission. ### Payload Security Method -> Action: Certificate Rotation (CRLs) / Unique Identifier for device are still research areas needed. - -Due to the limitations of utilizing mTLS with common OT infrastructure components, such as TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection, Margo has adopted a certificate-based payload signing approach to protect payloads from being tampered with. By utilizing the certificates to create payload envelopes, the device's management client can ensure secure transport between the device's management client and the Workload Fleet Management's web service. -#### Details pertaining to the message Envelope: -Once the edge device has a message prepared for the Workload Fleet Management's web service, it completes the following to secure the message. - -- The device's management client calculates a digest and signature of the payload -- The device's management client adds an envelope around it that has: - - actual payload - - SHA of the payload, signed by the device certificate - - Identifier for the certificate that corresponds to the private key used to sign it. - - This identifier MUST be the UUID provided by the WFM server. -- The envelope is sent as the payload to the Workload Fleet Management's web service. -- The Workload Fleet Management's web service treats the request's payload as envelope structure, and receives the certificate identifier. -> Note: This certificate is the device certificate that was manually uploaded to the Workload Fleet Manager solution during onboarding. -- The Workload Fleet Management's web service computes digest from the payload, and verifies the signature using the device certification. -- The payload is then processed by the Workload Fleet Management's web service. -#### Signing Payloads -The following steps are used to sign a payload: - -1. Generate a SHA-256 hash value for the request's body -2. Create a digital signature by using the message source certificates's private key to encrypt the the hash value -3. Base-64 encode the certificate's public key and the digital signature in the format of `;` -3. Include the base-64 encoded string in the request's `X-Payload-Signature` header -### Verifying Signed Payloads -The following steps are used to verify signed payload: - -1. Retrieve the public key from the `X-Payload-Signature` header -2. Decrypt the digital signature using the public key to get the original hash value -3. Generate a SHA-256 hash value for the requests's body -4. Ensure the generated hash value matches the hash value from the message +#### Security and Integrity Information +- Due to the limitations of utilizing mTLS with common OT infrastructure components, such as TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection, Margo has adopted a certificate-based payload signing approach to protect payloads from being tampered with. By utilizing the certificates to create payload envelopes (HTTP Request body), the device's management client can ensure secure transport between the device's management client and the Workload Fleet Management's web service. + - For API security, Server side TLS 1.3 (minimum) is used, where the keys are obtained from the Server's X.509 Certificate as defined in standard HTTP over TLS + - For API integrity, the device's management client is issued a client specific X.509 certificate. + - The issuer of the client X.509 certificate is trusted under the assumption that the root CA download to the Workload Fleet Management server occurs as a precondition to onboarding the devices + - Similarly the issuer of the server X.509 certificate is trusted under the assumption that the root CA download to the device's management client occurs over a "protected" connection as part of the yet to be defined device onboarding procedure +#### Device Management Client +- Once the device management client has a message prepared for the Workload Fleet Management's web service, it MUST complete the following to establish the integrity of the message as defined in RFC 9421 : + - The device's management client MUST create SHA256 hash Message-Digest of the base64 encoded payload (HTTP Request Body). This forms the 'Content-Digest' parameter in the HTTP Header. + ``` + Content-Digest: sha-256=:: + ``` + - The device management client MUST create a Signature Base String embedding the content-digest. An example is given below. + ``` + @method: POST + @target-uri: https://api.example.com/resource + Content-Digest: sha-256=:: + @signature-params: ("@method" "@target-uri" "Content-Digest");created=1680575171;keyid="my-rsa-key" + ``` + - The device management client MUST create the Signature field by signing the SHA256 hash of the Base64 encoded Signature Base String, using the client X.509 RSA Private Key + - The devices's management client MUST insert the following in the HTTP1.1 Header : + - Content-Digest as formed above + - Signature-Input as given below, replacing the created and keyid parts appropriately : + ``` + sig1=("@method" "@target-uri" "Content-Digest");created=;keyid="" + ``` + - Signature as explained above + - The base64 encoded signature of the SHA256 has of the payload, signed with the private-key of the Client X.509 certificate + Note: The private-key is not stored in the X.509 certificate, it may be stored in a .pem file and this information is used while generating the X.509 certificate for the client +#### Workload Fleet Manager Web-Service +- On receiving the message from the Device Client, The Workload Fleet Management's web service MUST do the following : + - It looks up the client certificate from the Client-ID in the API Request URL + - The Workload Fleet Management's web service reads the following from the HTTP Request Header : + - Signature-Input + - Signature + - Content-Digest (if body is present) + - Use the Signature-Input in the header to determine which components were signed. Reconstruct the Signature Base canonical string using the actual values from the request including the SHA256 encoded content-digest from the received request body + - Then extract the base64-encoded message signature from the Signature header, and also verifies the message signature string using the client's X.509 public-key. + - If the message signature in the HTTP Header and the verified message signature match, then the payload is then processed by the Workload Fleet Management's web service. + - If the two do not match, the Workload Fleet Manager will respond with HTTP Error 401 as given below, and discontinue the session + ``` + HTTP/1.1 401 Unauthorized + Content-Type: application/json + { + "error": "Invalid signature", + "message": "The X-Body-Signature header does not match the content of the request body." + } + ``` +#### Open Source examples: +- Full RFC 9421 implementation with support for RSA, ECDSA, HMAC + - [LINK](https://github.com/lestrrat-go/htmsig) +- Feature-complete RFC 9421 implementation with RSA-PSS and RSA-v1_5 support + - [LINK](https://github.com/yaronf/httpsign) diff --git a/system-design/specification/margo-management-interface/device-onboarding.md b/system-design/specification/margo-management-interface/device-onboarding.md index 78c95ff..cac843f 100644 --- a/system-design/specification/margo-management-interface/device-onboarding.md +++ b/system-design/specification/margo-management-interface/device-onboarding.md @@ -14,21 +14,57 @@ In order for the Workload Fleet Management software to manage the edge device's > Action: The Margo TWG is currently reviewing alternatives to GitOps. This page will be updated upon a finalization of a new strategy. - The [device capabilities](../../concepts/workload-fleet-managers/device-capabilities.md) information is sent from the device to the WFM service using the [Device API](../../specification/margo-management-interface/device-capabilities.md) +## Onboarding Sequence diagram + +```mermaid +sequenceDiagram + autonumber + participant Client + participant Server + + Note over Client,Server: 🔐 Initial Trust Establishment. + Note over Client,Server: This root CA certificate could alternatively been provided out of band.
e.g.: USB Stick, from Device Fleet management onboarding, FDO workflow. + Client->>Server: GET /onboarding/certificate + Server-->>Client: base64-encoded Root CA certificate + Client-->>Client: injecting Root CA into trusted store + + Note over Client,Server: 🔒 Standard TLS Handshake Start + Client->>Server: TLS ClientHello (TLS versions, cipher suites, random) + Server-->>Client: TLS ServerHello (chosen version, cipher, random) + Server-->>Client: X.509 certificate chain(server + intermediate(if applicable)) + Client-->>Client: Verifies server cert chain based on RootCA + Note over Client,Server: 🔒 Standard TLS Handshake completed + WFMUser->>Server: Opportunity for user to manually upload client certificate + Note over Client,Server: Device Client onboarding begins + Client->>Server: POST /onboarding with public_certificate (could exchange additional info) + WFMUser->>Server: Opportunity for user to approve or reject client onboarding + alt Public key trusted/user approved + Note over Server: Server verifies client certificate and assigns UUID + Server-->>Client: 201 Created { client_id } + else Public key invalid/Client rejected + Server-->>Client: 400 Bad Request {error: "Invalid certificate"} + Server-->>Client: 403 Forbidden{ error: "Client rejected"} + end + Note over Client,Server: Device Client onboarding Ends + Note over Client,Server: 📡 Secure API Usage with Signed Payloads can now begin + + Client->>Server: POST /client/{clientId}/capabilities + Server-->>Client: 201 Created + Note over Client,Server: Enrollment is complete + + Note over Client,Server: Assumed Desired state has been transmitted via WFM(out of scope for this SUP) + Note over Client,Server: 📡 Secure API Usage with Signed Payloads + Client->>Server: POST /client/{clientId}/deployment/{deploymentId}/status + Server-->>Client: 201 Created +``` -### Configuring the Workload Fleet Management Web Service URL - -> Action: Ideally this URL is discoverable instead of having to manually enter it but we still need to determine if there is a good way to make this discoverable by using something like the FDO Rendezvous service or multicast DNS. Also, once we determine how the Margo compliant device onboarding and fleet management is going to work it will probably impact this. - -To ensure the management client is configured to communicate with the correct Workload Fleet Management web service, the device's management client needs to be configured with the expected URL. The device vendor MUST provide a way for the end user to manually set the URL the device's management client uses to communicate with the Workload FLeet Management solution chosen by the end user. - -### GitOps Service Enrollment - -> Action: The Margo TWG is currently reviewing alternatives to GitOps. This page will be updated upon a finalization of a new strategy. - -#### Authorization methods for the Desired State Git Repository - -- Git access tokens shall be provided to the device's management client. These access tokens MUST be tied to a dedicated non-user account for access where credentials are frequently rotated and short lived. -- Need to support accessing rotations of tokens +#### Sequence Diagram Notes +- Following Step 3: Root CA is now trusted in the TLS handshake +- Diagram depicts a standard TLS flow, but additional steps in the handshake can occur. +- (After post /onboarding) + - Verification of client cert out of scope of this. Pre specify + - Step approves the client can join the server. Additional information can be tied to the certificate but are not required in this SUP. supporting information can also be transferred during this step approving this client can join the server. other things could be tied to the certificate. i.e. Cert supplied via Dell / serial number of device / + - FDO bootstrapping off of ownership vouchers could be integrated here as well. ## Onboarding API Details > Action: This API needs to be defined From fde295fa4b21747434b64bffa04690523bef85d2 Mon Sep 17 00:00:00 2001 From: Matthias Lechner Date: Thu, 30 Oct 2025 16:33:45 +0000 Subject: [PATCH 03/25] feat: Migrate Desired State SUP into spec Signed-off-by: Matthias Lechner --- .../desired-state.linkml.yaml | 5 +- .../resources/index.md.jinja2 | 262 +++++++++++++++++- 2 files changed, 258 insertions(+), 9 deletions(-) diff --git a/src/specification/margo-management-interface/desired-state.linkml.yaml b/src/specification/margo-management-interface/desired-state.linkml.yaml index cfc2202..314a468 100644 --- a/src/specification/margo-management-interface/desired-state.linkml.yaml +++ b/src/specification/margo-management-interface/desired-state.linkml.yaml @@ -2,9 +2,8 @@ id: http://specification.margo.org/desired_state_schema name: DesiredState description: >- - The desired state is expressed as a - [Kubernetes custom resource definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) - and made available to the device's management client as a YAML document using the OpenGitOps pattern. + Each workload is represented as an `ApplicationDeployment` YAML file that specifies its components, configuration, and parameters. + This definition is shared across the Desired State and Deployment Status APIs. version: 1.0 #Arne: update later prefixes: linkml: https://w3id.org/linkml/ diff --git a/src/specification/margo-management-interface/resources/index.md.jinja2 b/src/specification/margo-management-interface/resources/index.md.jinja2 index a29d9de..6f5cc1f 100644 --- a/src/specification/margo-management-interface/resources/index.md.jinja2 +++ b/src/specification/margo-management-interface/resources/index.md.jinja2 @@ -1,12 +1,262 @@ # Desired State -> Action: This is incomplete and doesn't contain the details for the deploymentProfile or parameters +In order for the **Workload Fleet Manager (WFM)** to manage workloads on an **Edge Compute Device**, the device's **Workload Fleet Management Client** must periodically retrieve its desired workload configuration - referred to as the **Desired State** - from the WFM. -> Action: We are currently investigating the best way to interface with source control infrastructure. +The Desired State defines *what* workloads (applications) should run on the device and *how* they should be configured. +It is distributed using a lightweight, pull-based HTTP API that allows devices to stay synchronized with the WFM. -{% if schema.description %}{{ schema.description }}{% endif %} +At the center of this process is the **State Manifest**, a JSON document that lists all workloads assigned to the device. Each workload is represented by an [`ApplicationDeployment`](#applicationdeployment-yaml-definition) YAML - a self-contained object defining configuration, components, and parameters for that workload. + +The manifest includes two complementary ways for the client to obtain the same `ApplicationDeployment` YAMLs: + +- **Individual YAMLs** - each `ApplicationDeployment` YAML fetched separately using its own URL. +- **A bundle archive** - a single compressed archive containing multiple `ApplicationDeployment` YAMLs. + +Both references describe the same content. The bundle is simply a packaging optimization. +This design allows the Workload Fleet Management Client to choose the optimal retrieval strategy depending on network conditions or update size. + +| Retrieval Method | Typical Use | Advantages | +| ---------------- | ----------- | ---------- | +| **Bundle** | Initial onboarding, large updates, high-latency or high-round-trip networks | Single request with minimal overhead | +| **Individual YAMLs** | Incremental updates, bandwidth-limited or metered links | Only changed workloads are downloaded | + +The Workload Fleet Management Client compares the manifest with its current state and reconciles any differences by **deploying, updating, or removing** workloads. +For every change in deployment state - including installation, updates, removals, and failures - the client **MUST** report the corresponding status to the WFM using the [Deployment Status API](../../specification/margo-management-interface/deployment-status.md). + +## Endpoints - State Manifest + +This section defines the API endpoint used by a client to retrieve the State Manifest from the Workload Fleet Manager, representing the complete desired workload configuration assigned to the device. + +### Route and HTTP Methods + +```https +GET /api/v1/clients/{clientId}/deployments +``` + +### Route Parameters + +| Parameter | Type | Required? | Description | +| --------- | ---- | --------- | ----------- | +| `{clientId}` | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | + +### Request Headers + +| Header | Description | +| ------ | ------------| +| `If-None-Match` *(optional)* | The `ETag` value from the last successfully retrieved manifest. | +| `Accept` *(optional)* | The client **SHOULD** request the manifest in the `application/vnd.margo.manifest.v1+json` format. If the `Accept` header lists only unsupported types, the server **MUST** return **406 Not Acceptable**. If omitted, the server **MUST** return this format by default. | + +### Response Codes + +| Code | Description | +| ----- | ---------- | +| **200 OK** | The response body contains the manifest. The server **MUST** include a valid `ETag` and `Content-Type: application/vnd.margo.manifest.v1+json`. | +| **304 Not Modified** | The response body is empty. Returned if the `If-None-Match` `ETag` matches, i.e. the cached response body has not changed since the last retrieved version. | +| **406 Not Acceptable** | The server cannot return a representation matching the `Accept` header. | + +### Example Response + +```json +{ + "manifestVersion": 101, + "bundle": { + "mediaType": "application/vnd.margo.bundle.v1+tar+gzip", + "digest": "sha256:b5c6d7e8f9...", + "url": "/api/v1/clients/1234/bundles/sha256:b5c6d7e8f9..." + }, + "deployments": [ + { + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "digest": "sha256:a4e01b2c3d...", + "url": "/api/v1/clients/1234/deployments/a3e2f5dc-912e-494f-8395-52cf3769bc06/sha256:a4e01b2c3d..." + } + ] +} +``` + +### Response Fields + +| Field | Type | Required? | Description | +| ----- | ---- | --------- | ----------- | +| `manifestVersion` | number | Y | Monotonically increasing unsigned 64-bit integer in the inclusive range `[1, 2^64-1]`. Each new manifest for the same (device) client **MUST** have a strictly greater value than the previous. The first manifest for a given client **MUST** use the value 1. | +| `bundle` | object | Y | Describes an archive containing all referenced `ApplicationDeployment` YAMLs. If there are zero deployments (i.e., the `deployments` array is empty), this field **MUST** be present with the value `null`. An **empty archive MUST NOT** be served. | +| `bundle.mediaType` | string | Y | **MUST** be `application/vnd.margo.bundle.v1+tar+gzip`, which denotes a gzip-compressed tar archive (commonly delivered as a .tar.gz) whose root contains one or more `ApplicationDeployment` YAML files. Servers **MUST** set the HTTP `Content-Type` to this media type. The archive **MUST** contain exactly the set of YAML files referenced by `deployments`. | +| `bundle.digest` | string | Y | Digest of the bundle archive. **MUST** equal the digest computed over the exact sequence of bytes in the [bundle endpoint's](#endpoints-deployment-bundle) HTTP `200 OK` response body. See [Protocol - Digest](#protocol-digest) for further details. | +| `bundle.sizeBytes` | number | N | Optional unsigned 64-bit advisory estimate of the decoded payload length in bytes for the bundle archive. Provided for bandwidth estimation and update planning. **MUST NOT** be used for integrity verification. | +| `bundle.url` | string | Y | Content-addressable retrieval endpoint for the bundle of the form `/api/v1/clients/{clientId}/bundles/{digest}` where `{digest}` equals `bundle.digest`. | +| `deployments` | array | Y | List of deployment objects describing each workload. | +| `deployments[].deploymentId` | string | Y | The UUID of the deployment. **MUST** equal [`metadata.annotations.id`](#annotations-attributes) in the `ApplicationDeployment`. | +| `deployments[].digest` | string | Y | Digest of the corresponding `ApplicationDeployment` YAML file. **MUST** equal the digest computed over the exact sequence of bytes in the [individual deployment endpoint's](#endpoints-individual-deployment-yaml) HTTP `200 OK` response body. See [Protocol - Digest](#protocol-digest) for further details. | +| `deployments[].sizeBytes` | number | N | Optional unsigned 64-bit advisory estimate of the decoded payload length in bytes for the `ApplicationDeployment` YAML. Provided for bandwidth estimation and update planning. **MUST NOT** be used for integrity verification. | +| `deployments[].url` | string | Y | Content-addressable retrieval endpoint for the `ApplicationDeployment` YAML of the form `/api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}` where `{digest}` equals `deployments[].digest`. | + +> **Note:** The `ETag` returned from this endpoint is a digest of the **entire** JSON response body (after serialization). It is **independent** of `bundle.digest` and individual deployment digests (`deployments[].digest`). See [ETag and Caching](#protocol-etag-and-caching) for details. + +### Client Validation Rules + +- The client **MUST** verify the digest of every fetched artifact before use. +- If any digest validation fails, the client **MUST** abort the update and retain the previous state. +- The client **MUST** persist both the last accepted `manifestVersion` and `ETag` to prevent rollback across restarts. + +## Endpoints - Individual Deployment YAML + +This section defines the API endpoint used by a client to retrieve a single `ApplicationDeployment` YAML for incremental synchronization and targeted updates. + +### Route and HTTP Methods + +```https +GET /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest} +``` + +### Route Parameters + +| Parameter | Type | Required? | Description | +| --------- | ---- | --------- | ----------- | +| `{clientId}` | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | +| `{deploymentId}` | string | Y | The UUID of the served `ApplicationDeployment` YAML. This **MUST** equal to `metadata.annotations.id`. | +| `{digest}` | string | Y | Content-addressable digest of the served `ApplicationDeployment` YAML. See [Protocol - Digest](#protocol-digest) for further details. | + +### Response Codes + +| Code | Description | +| ---- | ----------- | +| **200 OK** | The response body contains the raw `ApplicationDeployment` YAML (`Content-Type: application/yaml`). Server **MUST** set `ETag` to the quoted digest and **SHOULD** return `Cache-Control: public, max-age=31536000, immutable`. | +| **404 Not Found** | The referenced digest does not exist on the server. `404 Not Found` indicates only that this specific digest is unavailable. It **MUST NOT** be interpreted as a deletion signal by a client; deletion of workloads is determined solely by absence from the state manifest. | + +> **Note:** Servers MAY apply HTTP `Content-Encoding` (e.g., gzip, br). The client advertises support via `Accept-Encoding`. Digests and ETags always refer to the decoded representation (i.e., the exact bytes of the response body after decompressing any HTTP `Content-Encoding` such as gzip). Servers **SHOULD** include `Vary: Accept-Encoding` if compression is used. + +## Endpoints - Deployment Bundle + +This section defines the API endpoint used by a client to retrieve a compressed bundle containing all `ApplicationDeployment` YAMLs for efficient bulk synchronization. + +### Route and HTTP Methods + +```https +GET /api/v1/clients/{clientId}/bundles/{digest} +``` -### ApplicationDeployment Definition +### Route Parameters + +| Parameter | Type | Required? | Description | +| --------- | ---- | --------- | ----------- | +| `{clientId}` | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | +| `{digest}` | string | Y | Content-addressable digest of the served bundle archive. See [Protocol - Digest](#protocol-digest) for further details. | + +### Response Codes + +| Code | Description | +| ---- | ----------- | +| **200 OK** | The bundle was successfully retrieved. The server **MUST** set `Content-Type` to the manifest-declared `bundle.mediaType`, `ETag` to the quoted digest, and **SHOULD** return `Cache-Control: public, max-age=31536000, immutable`. | +| **404 Not Found** | The referenced digest does not exist on the server. `404 Not Found` indicates only that this specific digest is unavailable. It **MUST NOT** be interpreted as a deletion signal by a client; deletion of workloads is determined solely by absence from the state manifest. | + +> **Note:** Servers **MAY** apply `Content-Encoding` (e.g., gzip, br) and **SHOULD** include `Vary: Accept-Encoding` if they do. + +## Protocol - Digest + +All Desired State artifacts - including the manifest, bundle archives, and individual `ApplicationDeployment` YAMLs - use a canonical digest to ensure content integrity and consistency across client and server implementations. + +A digest has the form `algorithm:encoded`, where both parts are lowercase. Clients and servers **MUST NOT** add prefixes, suffixes, or whitespace. The required algorithm is **`sha256`**, and the encoded portion is a **64-character lowercase hexadecimal string**. + +- The digest **MUST** be computed over the exact bytes of the decoded HTTP response body - that is, after decompressing any HTTP `Content-Encoding` (for example, gzip or br). +- No reformatting, re-serialization, or newline normalization is permitted during digest computation. + +The resulting digest value is used consistently across all API representations: + +- In JSON responses: `"digest": "sha256:a4e01b2c3d..."` +- In URLs: `/api/v1/clients/{clientId}/deployments/{deploymentId}/sha256:a4e01b2c3d...` +- In HTTP headers: `ETag: "sha256:a4e01b2c3d..."` + +Clients **MUST** verify that the digest they compute for every retrieved artifact matches the value provided in the manifest. Any mismatch **MUST** cause the client to abort the update and preserve the previous state. +If a manifest references a digest using an unsupported algorithm, the client **MUST** treat the manifest as invalid and abort processing. + +**Example:** + +```text +sha256:a1b2c3d4e5f67890123456789abcdef0123456789abcdef0123456789abcdef +``` + +## Protocol - ETag and Caching + +All Desired State endpoints implement standard HTTP caching semantics to optimize synchronization between the **Workload Fleet Manager (WFM)** and the **Workload Fleet Management Client**. ETags are used to detect content changes and avoid redundant data transfers. Two caching models are defined: one for the mutable **State Manifest**, and one for immutable, content-addressable resources such as individual deployments and bundles. + +### State Manifest Endpoint + +For the [State Manifest](#endpoints-state-manifest) endpoint, servers use **strong ETags** as defined in [RFC 9110 § 8.8.3](https://datatracker.ietf.org/doc/html/rfc9110#section-8.8.3). + +- The `ETag` **MUST** be a strong validator computed as a digest of the exact serialized JSON response body. + The format **MUST** follow the digest grammar defined in [Protocol – Digest](#protocol-digest): + `":"`, for example: + `"sha256:a4e01b2c3d..."`. +- Servers **SHOULD** serialize JSON deterministically (for example, per [RFC 8785](https://datatracker.ietf.org/doc/html/rfc8785)) so that logically identical manifests yield identical bytes and therefore identical ETags. +- Manifest responses **MUST NOT** be marked immutable (e.g., by applying `Cache-Control: immutable` or excessively long `max-age` values). Freshness is controlled through periodic polling using `If-None-Match` revalidation requests. +- When a client presents an `ETag` that matches the current manifest, the server **MUST** respond with **304 Not Modified**, omitting the response body. + +### Content-Addressable Endpoints + +For [Individual Deployment YAML](#endpoints-individual-deployment-yaml) and [Deployment Bundle](#endpoints-deployment-bundle) endpoints, the resources are immutable and uniquely identified by their digest. + +- The `ETag` **MUST** equal the quoted digest embedded in the resource’s URL (e.g., `ETag: "sha256:a4e01b2c3d..."`). + This constitutes a strong validator per [RFC 9110 § 8.8.3](https://datatracker.ietf.org/doc/html/rfc9110#section-8.8.3). +- Servers **SHOULD** include `Cache-Control: public, max-age=31536000, immutable` to enable long-term caching of immutable artifacts. +- If compression is applied, servers **SHOULD** include `Vary: Accept-Encoding` to ensure cache correctness across encodings. +- Clients **MAY** send `If-None-Match` when revalidating cached resources; servers **MAY** return **304 Not Modified** if the artifact has not changed. + +## Deployment Workflow + +This section defines the end-to-end workflow followed by a client to retrieve, validate, and reconcile its Desired State with the Workload Fleet Manager. + +- The client polls the WFM for the latest manifest using the last known `ETag` (if any): + + ```https + GET /api/v1/clients/{clientId}/deployments + ``` + + - If the manifest is unchanged, the WFM responds with **304 Not Modified**. + - If the manifest has changed (**200 OK**), the client: + - Verifies the `manifestVersion` is strictly greater than the stored version. If not, the update **MUST** be rejected and logged as a security event. + - Parses the manifest and decides whether to fetch the **bundle** or **individual deployments**. + - Downloads and verifies digests for all referenced `ApplicationDeployment` YAMLs. + - The client reconciles its local workloads: + - Adds or updates workloads that appear in the new manifest. + - Removes workloads no longer present in the new manifest. + - For each change in workload state, the client reports progress and results to the WFM using the [Deployment Status API](../../specification/margo-management-interface/deployment-status.md). + - Once reconciliation succeeds, the client **MUST** durably persist the new `manifestVersion` and associated `ETag` for use in the next poll cycle. + +### Sequence Diagram + +```mermaid +sequenceDiagram + autonumber + participant Client as Workload Fleet
Management Client + participant WFM as Workload Fleet
Manager + + loop Poll for updates + Client->>+WFM: GET /api/v1/clients/{clientId}/deployments
Header: If-None-Match: "sha256:abc..." + alt State unchanged + WFM-->>-Client: 304 Not Modified + else State updated + WFM-->>Client: 200 OK
Header: ETag: "sha256:xyz..."
Body: Manifest JSON + Client->>Client: Compare manifestVersion and current state + + alt Initial sync or major update + Client->>WFM: GET (bundle URL) + WFM-->>Client: 200 OK
Body: Bundle archive + else Incremental update + Client->>WFM: GET (deployment URLs) + WFM-->>Client: 200 OK
Body: YAMLs + end + + Client->>Client: Verify digests and reconcile workloads + Client->>WFM: POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status
Report progress + end + end +``` + +## ApplicationDeployment YAML Definition + +This section defines the structure and YAML schema of an `ApplicationDeployment`, providing a normative reference for Desired State configuration objects. + +{% if schema.description %}{{ schema.description }}{% endif %} ```yaml apiVersion: application.margo.org/v1alpha1 @@ -59,6 +309,7 @@ spec: {% for c in gen.all_class_objects()|sort(attribute='rank') %} {%- if c.name != "DesiredState" and not c.name.startswith("Helm") and not c.name.startswith("DockerCompose") and not c.name == "Property" %} + #### {{ c.name }} Attributes | Attribute | Type | Required? | Description | @@ -75,9 +326,8 @@ spec: {% include 'examples/valid/DesiredState-001.yaml' %} ``` -### Example: Standalone Device Application Deployment Specification: +### Example: Standalone Device Application Deployment Specification ```yaml {% include 'examples/valid/DesiredState-002.yaml' %} ``` - From fed61ef025624d406bfebbdd10bac5cd44c3d325 Mon Sep 17 00:00:00 2001 From: Matthias Lechner Date: Thu, 30 Oct 2025 16:54:52 +0000 Subject: [PATCH 04/25] feat: Add note on digest format vs RFC 9421 Signed-off-by: Matthias Lechner --- .../resources/index.md.jinja2 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/specification/margo-management-interface/resources/index.md.jinja2 b/src/specification/margo-management-interface/resources/index.md.jinja2 index 6f5cc1f..2c6fac6 100644 --- a/src/specification/margo-management-interface/resources/index.md.jinja2 +++ b/src/specification/margo-management-interface/resources/index.md.jinja2 @@ -175,6 +175,16 @@ If a manifest references a digest using an unsupported algorithm, the client **M sha256:a1b2c3d4e5f67890123456789abcdef0123456789abcdef0123456789abcdef ``` +> **Note:** +> This API defines the digest format `sha256:` (lowercase) for JSON fields, URLs, and ETags. +> This digest represents **content identity**, ensuring that each artifact (manifest, bundle, or `ApplicationDeployment` YAML) can be uniquely verified and referenced within the Desired State API. +> +> By contrast, the mechanism described in the [API Requirements and Security Details](../../specification/margo-management-interface/api-requirements-and-security.md) document - which follows [RFC 9421](https://datatracker.ietf.org/doc/html/rfc9421) - provides **HTTP message-level integrity** through signed payloads. +> While both rely on the SHA-256 algorithm, they operate at different layers of the protocol: +> +> - The digest in this API defines immutable content identity for artifacts. +> - The RFC 9421 mechanism ensures end-to-end message integrity and authenticity during HTTP transport. + ## Protocol - ETag and Caching All Desired State endpoints implement standard HTTP caching semantics to optimize synchronization between the **Workload Fleet Manager (WFM)** and the **Workload Fleet Management Client**. ETags are used to detect content changes and avoid redundant data transfers. Two caching models are defined: one for the mutable **State Manifest**, and one for immutable, content-addressable resources such as individual deployments and bundles. From ed1668f54b6f8f59927f08c04cc2355d5d7b9733 Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Thu, 30 Oct 2025 17:14:40 -0400 Subject: [PATCH 05/25] Updated deployment status and device capabilities markdowns. Signed-off-by: Armand Craig --- .../deployment-status.md | 28 ++++++++++--------- .../device-capabilities.md | 25 +++++++++-------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/system-design/specification/margo-management-interface/deployment-status.md b/system-design/specification/margo-management-interface/deployment-status.md index 1fb25b3..755f849 100644 --- a/system-design/specification/margo-management-interface/deployment-status.md +++ b/system-design/specification/margo-management-interface/deployment-status.md @@ -5,19 +5,28 @@ While applying a new desired state, the device's management client MUST provide ### Route and HTTP Methods ```https -POST /api/v1/device/{deviceId}/deployment/{deploymentId}/status +POST /api/v1/client/{clientId}/deployment/{deploymentId}/status ``` ### Route Parameters |Parameter | Type | Required? | Description| |----------|------|-----------|------------| -| {deviceId} | string | Y | The device's Id registered with the Workload Fleet Manager solution during onboarding.| -| {deploymentId} | string | Y | The deployment Id the status is being reported for | +| {clientId} | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | +| {deploymentId} | string | Y | The UUID of the `ApplicationDeployment` YAML being reported. -### Request Body Fields +### Response Code -> Action: Need to figure out the options for error code and message. Are these to be free form? +| Code | Description | +|------|-------------| +| 200 OK | The deployment status was added, or updated, successfully. | +| 400 Bad Request | Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included. | +| 401 Unauthorized | Signature verification failed. Ensure you are signing with the correct X.509 private key. | +| 403 Forbidden | Client certificate is not trusted or has been revoked. | +| 422 Unprocessable Content | Request body includes a semantic error. | + + +### Request Body Fields | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| @@ -82,11 +91,4 @@ POST /api/v1/device/{deviceId}/deployment/{deploymentId}/status } ] } -``` - -### Response Code - -| Code | Description | -|------|-------------| -| 201 | The deployment status was added, or updated, successfully | -| 4XX-5XX | The requests was not completed successfully | +``` \ No newline at end of file diff --git a/system-design/specification/margo-management-interface/device-capabilities.md b/system-design/specification/margo-management-interface/device-capabilities.md index b78b0f1..380f7ad 100644 --- a/system-design/specification/margo-management-interface/device-capabilities.md +++ b/system-design/specification/margo-management-interface/device-capabilities.md @@ -7,15 +7,25 @@ To ensure the WFM is kept up to date, the device's client MUST send updated capa ### Route and HTTP Methods ```https -POST /api/v1/device/{deviceId}/capabilities -PUT /api/v1/device/{deviceId}/capabilities +POST /api/v1/client/{clientId}/capabilities +PUT /api/v1/client/{clientId}/capabilities ``` ### Route Parameters |Parameter | Type | Required? | Description| |----------|------|-----------|------------| -| {deviceId} | string | Y | The device's Id registered with the workload orchestration web service during onboarding.| +| {clientId} | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | + +### Response Code + +| Code | Description | +|------|-------------| +| 201 OK | The device capabilities document was added, or updated, successfully | +| 400 Bad Request | Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included. | +| 401 Unauthorized | Signature verification failed. Ensure you are signing with the correct X.509 private key. | +| 403 Forbidden | Client certificate is not trusted or has been revoked. | +| 422 Unprocessable Content | Request body includes a semantic error. | ### Request Body Attributes @@ -150,11 +160,4 @@ These enumerations are used as vocabularies for attribute values of the `DeviceC } } } -``` - -### Response Code - -| Code | Description | -|------|-------------| -| 201 | The device capabilities document was added, or updated, successfully | -| 4XX-5XX | The requests was not completed successfully | +``` \ No newline at end of file From ac4b9752a106b081720c6af44d286e936838224e Mon Sep 17 00:00:00 2001 From: Matthias Lechner Date: Fri, 31 Oct 2025 09:13:44 +0000 Subject: [PATCH 06/25] feat: Update workload deployment concepts Signed-off-by: Matthias Lechner --- .../workload-deployment.md | 122 ++++++++++++++---- 1 file changed, 94 insertions(+), 28 deletions(-) diff --git a/system-design/concepts/workload-fleet-managers/workload-deployment.md b/system-design/concepts/workload-fleet-managers/workload-deployment.md index fca553c..30da5bb 100644 --- a/system-design/concepts/workload-fleet-managers/workload-deployment.md +++ b/system-design/concepts/workload-fleet-managers/workload-deployment.md @@ -1,45 +1,111 @@ # Workload Deployment -Margo uses an [OpenGitOps](https://opengitops.dev/) approach for managing the edge device's desired state. The workload orchestration solution vendor maintains Git repositories, under their control, to push updates to the desired state for each device being managed. The device's management client is responsible for monitoring the device's assigned Git repository for any changes to the desired state that MUST be applied. -> Action: The use of GitOps patterns for pulling desired state is still being discussed/investigated. +This page describes how Margo manages the deployment and reconciliation of workloads on Edge Compute Devices. +Workload deployment in Margo is based on a declarative Desired State model. +A Workload Fleet Manager (WFM) defines the desired workloads for each Edge Compute Device, including what should run, how each workload should be configured, and the parameters needed for deployment and lifecycle management. +Each device runs a Workload Fleet Management Client (WFM Client) that retrieves and applies this Desired State, while reporting progress and results back to the WFM. +This model provides a consistent and observable way to manage workloads across distributed environments. -### Desired State Requirements: +### How it works -> Note: Need to investigate best way to construct the Git Repository. Folder structure / Multiple applications per Edge Device/Cluster -> Note: this is the recommendation from FluxCD +The Workload Fleet Manager coordinates workloads across Edge Compute Devices. +Operators use the WFM to define workloads, update deployments, and view rollout progress across devices. +The WFM Client continuously reconciles the Desired State provided by the WFM with the workloads actually running on the device. -- The workload orchestration solution MUST store the device's [desired state documents](../../specification/margo-management-interface/desired-state.md) within a Git repository the device's management client can access. -> Note: Git repository storage was selected to ensure secure storage and traceability pertaining to the workload's desire state(s). -- The device's management client MUST monitor the device's Git repository for updates to the desired state using the URL and access token provided by the workload orchestration solution during onboarding. +The WFM and WFM Clients communicate through two key interfaces: -### Workload Management Sequence of Operations +- The [Desired State API](../../specification/margo-management-interface/desired-state.md), which distributes workload definitions to devices +- The [Deployment Status API](../../specification/margo-management-interface/deployment-status.md), which collects deployment updates from devices -#### Desired State lifecycle: +Together, these interfaces establish a feedback loop between the centralized manager and the distributed devices, ensuring workload consistency and visibility at scale. -1. The workload orchestration solution creates the [desired state documents](../../specification/margo-management-interface/desired-state.md) based on the end user's inputs when installing, updating or deleting an application. -2. The workload orchestration solution pushes updates to the device's Git repository reflecting the changes to the desired state. -3. The device's management client monitors its assigned Git repository for changes. -4. When the device's management client notices a difference between the current (running) state and the desired state, it MUST pull down and attempt to apply the new desired state. +### Desired State -#### Applying the Desired State: +The Desired State defines the workloads that should run on each Edge Compute Device and the details of how they are deployed. +It is represented by a [State Manifest](../../specification/margo-management-interface/desired-state.md#endpoints-state-manifest) that lists all workloads assigned to a device. +The WFM exposes this manifest through the Desired State API. -1. The device attempts to apply the desired state to become new current state -2. While the new desired state is being applied, the device's management client MUST report progress on state changes (see the [deployment state](#deployment-status) section below) using the [Device API](../../specification/margo-management-interface/deployment-status.md) +Each workload is defined by an [ApplicationDeployment](../../specification/margo-management-interface/desired-state.md#applicationdeployment-yaml-definition), which describes: -#### Deployment Status +- The Components that make up the workload, such as Helm charts or Compose-based container bundles +- Configuration parameters and deployment profiles that control workload behavior +- Target information identifying which devices or groups of devices the deployment applies to -The deployment status is sent to the workload orchestration web service using the [Device API](../../specification/margo-management-interface/deployment-status.md) when there is a change in the deployment state. This informs the workload orchestration web service of the current state as the new desired state is applied. +The WFM can provide ApplicationDeployments in two formats: -The deployment status uses the following rules: +- Individual YAML files, allowing incremental synchronization +- A bundle archive that contains multiple ApplicationDeployments for bulk distribution -- The state is `Pending` once the device management client has received the updated desired state but has not started applying it. When reporting this state indicate the reason. - - Such as waiting on Policy agent - - Waiting on other applications in the 'Order of operations' to be completed. -- The state is `Installing` once the device management client has started the process of applying the desired state. -- The state is `Failure` if at any point the desired state fails to be applied. When reporting a `Failure` state the error message and error code MUST be reported -- The state is `Success` once the desired state has been applied completely +All files retrieved as part of the Desired State—manifests, ApplicationDeployment YAMLs, and bundle archives—are treated as immutable artifacts. +Each artifact is referenced by a SHA-256 digest. The WFM Client validates these digests before applying updates to ensure authenticity and consistency. +### Reconciliation process -> Note: Drawing to be replaced with mermaid sequence diagram. -![Workload Install Sequence Diagram (svg)](../../figures/workload-install-sequence.drawio.svg) +Each WFM Client maintains the Desired State on its Edge Compute Device by running a continuous reconciliation loop. + +1. **Retrieve the manifest:** + The WFM Client periodically checks the WFM for updates to its State Manifest. + When a new manifest version is available, the client initiates synchronization. + +2. **Retrieve artifacts:** + The WFM Client downloads the referenced ApplicationDeployment YAMLs or bundle archive. + +3. **Verify integrity:** + The WFM Client verifies that each artifact matches the digest declared in the manifest. + If verification fails, the update is halted and the current workloads remain unchanged. + +4. **Apply the Desired State:** + The WFM Client compares the current workloads with those defined in the Desired State: + + - Adds or updates workloads that have changed + - Removes workloads that are no longer listed + - Keeps workloads that remain valid and current + +5. **Report status:** + As the synchronization proceeds, the WFM Client reports its deployment status to the WFM through the Deployment Status API. + +This continuous process allows the WFM to maintain awareness of workload rollout progress and ensures devices converge toward the Desired State. + +### Deployment status + +The Deployment Status API provides feedback from devices to the Workload Fleet Manager. +The WFM Client reports progress, success, or failure during installation, update, and removal operations. +This feedback allows the WFM to present an aggregated view of deployment health and state across the managed fleet. + +A deployment status report includes: + +- The identifier of the ApplicationDeployment +- The current deployment state, which may be: + + - Pending - the Desired State has been received but not yet applied + - Installing - the workload is being deployed + - Installed - the workload has been successfully applied + - Removing or Removed - the workload is being or has been uninstalled + - Failed - an error occurred during deployment + +- Optional component-level progress information +- Error codes and messages, when applicable + +This information enables real-time monitoring and supports troubleshooting and auditing of workload operations. + +### Sequence diagram + +```mermaid +sequenceDiagram + participant WFM as Workload Fleet Manager + participant Client as WFM Client (running on Edge Compute Device) + + loop Periodic synchronization + Client->>WFM: Retrieve Desired State (Desired State API) + alt Desired State unchanged + WFM-->>Client: No update available + else Desired State updated + WFM-->>Client: Provide new State Manifest + Client->>WFM: Retrieve ApplicationDeployments or bundle + Client->>Client: Apply workloads from Desired State + Client->>WFM: Report deployment status (Deployment Status API) + end + end + +``` From 1dc2dafa4a5e5ebd0e06c60a0a068a80150ebeaf Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Fri, 31 Oct 2025 15:50:44 -0400 Subject: [PATCH 07/25] Improvements to concepts, certificate and onboarding API. Signed-off-by: Armand Craig --- mkdocs.yml | 1 + .../client-onboarding.md | 36 +++++++++++++ .../certificate-api.md | 9 +++- .../device-onboarding.md | 52 ++++++++++--------- 4 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 system-design/concepts/workload-fleet-managers/client-onboarding.md diff --git a/mkdocs.yml b/mkdocs.yml index 992af79..5578662 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,6 +20,7 @@ nav: - concepts/workloads/application-registry.md - concepts/workloads/local-registries.md - Workload Fleet Managers: + - concepts/workload-fleet-managers/client-onboarding.md - concepts/workload-fleet-managers/device-capabilities.md - concepts/workload-fleet-managers/workload-deployment.md - Edge Compute Devices: diff --git a/system-design/concepts/workload-fleet-managers/client-onboarding.md b/system-design/concepts/workload-fleet-managers/client-onboarding.md new file mode 100644 index 0000000..df88bf9 --- /dev/null +++ b/system-design/concepts/workload-fleet-managers/client-onboarding.md @@ -0,0 +1,36 @@ +# Device Client Onboarding + +Within Margo, late binding is an important non-functional requirement that enables a device to bind to any Margo compatible Workload Fleet Manager. To enable workload management, the device's client must first establish trust and complete an onboarding procedure with the End Users selected Workload Fleet Manager. + +The onboarding process includes the following major functions within Margo: +- trust establishment +- client onboarding +- device capability reporting + +## Trust Establishment + +Initial trust is established between the device’s management client and the Workload Fleet Management (WFM) web service using server-side TLS. The device downloads the WFM’s public root CA certificate via the onboarding API, or receives it via out-of-band strategies. The device injects the root CA into its trusted store, enabling secure TLS handshakes and certificate validation. This process avoids mTLS due to infrastructure compatibility concerns and relies on certificate-based trust. + +## Certificates required + +Both the WFM server and device clients use X.509 certificates for identity and secure communication. The server’s certificate is used for TLS authentication; the device client is issued a unique certificate for payload signing and integrity. Certificates are used to sign API payloads, ensuring authenticity and integrity. Private keys are securely stored and used for signing operations. + +## Unique Identifiers + +The Workload Fleet Manager assigns a unique identifier to the device's management client during the onboarding process. This is needed to ensure unique interactions between each device with the Fleet Manager. Unique identifiers + +## Device Capability Reporting + +After onboarding, the device client reports its capabilities to the WFM server using the Device API. The API operates over REST/HTTP1.1, exclusively on port 443. +Payloads are signed using the device’s X.509 certificate: +- The client creates a SHA256 hash of the base64-encoded payload (Content-Digest). +- A signature base string is constructed and signed with the client’s private key. +- The signature and digest are included in the HTTP headers. + +The WFM server verifies the signature using the client’s public key before processing the payload. + +## The following pages provide further details on the concepts described above: +- [API Security Details](../../specification/margo-management-interface/api-requirements-and-security.md) +- [Certificate API](../../specification/margo-management-interface/certificate-api.md) +- [Device Onboarding API](../../specification/margo-management-interface/device-onboarding.md) +- [Device Capabilities](../../specification/margo-management-interface/device-capabilities.md) \ No newline at end of file diff --git a/system-design/specification/margo-management-interface/certificate-api.md b/system-design/specification/margo-management-interface/certificate-api.md index 7a65f53..9889673 100644 --- a/system-design/specification/margo-management-interface/certificate-api.md +++ b/system-design/specification/margo-management-interface/certificate-api.md @@ -1,12 +1,17 @@ # Certificate API -In order to facilitate secure communication between the device's management client and workload orchestration web service the workload orchestration web service's root CA certificate must be downloaded using the Onboarding API's `certificate` endpoint. +In order to facilitate secure communication between the device's management client and the Workload Fleet Manager, the device must first retrieve the root CA certificate using the Onboarding API's `certificate` endpoint. ### Route and HTTP Methods ```http -GET /onboarding/certificate +GET /api/v1/onboarding/certificate ``` +### Response Code + +| Code | Description | +|------|-------------| +| 200 OK | Root CA provided in response | ### Response Body diff --git a/system-design/specification/margo-management-interface/device-onboarding.md b/system-design/specification/margo-management-interface/device-onboarding.md index cac843f..e2d24af 100644 --- a/system-design/specification/margo-management-interface/device-onboarding.md +++ b/system-design/specification/margo-management-interface/device-onboarding.md @@ -1,18 +1,38 @@ # Device Onboarding In order for the Workload Fleet Management software to manage the edge device's workloads, the device's management client must first complete onboarding. -> Action: The details in this page are still under discussion and have not been finalized. +## Onboarding API Details + +### Route and HTTP Methods + +```https +POST /api/v1/onboarding +``` +### Response Code + +| Code | Description | +|------|-------------| +| 200 OK | Certificate already present, onboarding successful. | +| 201 Created | New client onboarded successfully. | +| 400 Invalid Certificate | Invalid certificate format or structure. | +| 403 Forbidden | Client certificate is not trusted or has been rejected. | + +### Response Body + +```json +{ + "client_id": "" +} +``` -**The onboarding process includes:** +## Onboarding Sequence - The end user provides the the Workload Fleet Management web service's root URL to the device's management client - The device's management client downloads the Workload Fleet Manager's public root CA certificate using the [Onboarding API](../../specification/margo-management-interface/certificate-api.md) - Context and trust is established between the device's management client and the Workload Fleet Management web service -- The device's management client uses the [Onboarding API](../../specification/margo-management-interface/certificate-api.md) to onboard with the Workload Fleet Management service. -- The device's management client receives the client Id, client secret and token endpoint URL used to generate a bearer token. -- The device's management client receives the URL for the Git repository containing its desired state and an associated access token for authentication -> Action: The Margo TWG is currently reviewing alternatives to GitOps. This page will be updated upon a finalization of a new strategy. -- The [device capabilities](../../concepts/workload-fleet-managers/device-capabilities.md) information is sent from the device to the WFM service using the [Device API](../../specification/margo-management-interface/device-capabilities.md) +- The device's management client uses the [Onboarding API](../../specification/margo-management-interface/certificate-api.md) to onboard with the Workload Fleet Management service by providing it's x.509 certificate +- The device's management client receives it's unique client Id assigned via the Workload Fleet Manager +- The [device capabilities](../../concepts/workload-fleet-managers/device-capabilities.md) information is sent from the device to the WFM using the [Device API](../../specification/margo-management-interface/device-capabilities.md) ## Onboarding Sequence diagram @@ -64,20 +84,4 @@ sequenceDiagram - (After post /onboarding) - Verification of client cert out of scope of this. Pre specify - Step approves the client can join the server. Additional information can be tied to the certificate but are not required in this SUP. supporting information can also be transferred during this step approving this client can join the server. other things could be tied to the certificate. i.e. Cert supplied via Dell / serial number of device / - - FDO bootstrapping off of ownership vouchers could be integrated here as well. - -## Onboarding API Details -> Action: This API needs to be defined - -### Route and HTTP Methods - -```http -POST /onboarding/ -``` -### Request Body - -TBD - -### Response Body - -TBD \ No newline at end of file + - FDO bootstrapping off of ownership vouchers could be integrated here as well. \ No newline at end of file From 9e326c63d2a9be80fb44e91095db84696dcdec64 Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Fri, 31 Oct 2025 15:54:10 -0400 Subject: [PATCH 08/25] Small commit to reorder the navigation to match the client/server interaction workflow. Signed-off-by: Armand Craig --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 5578662..94bd622 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,8 +28,8 @@ nav: - Specification: - Margo Management Interface: - specification/margo-management-interface/api-requirements-and-security.md - - specification/margo-management-interface/device-onboarding.md - specification/margo-management-interface/certificate-api.md + - specification/margo-management-interface/device-onboarding.md - specification/margo-management-interface/device-capabilities.md - specification/margo-management-interface/desired-state.md - specification/margo-management-interface/deployment-status.md From ed3e38d8ede01c396b324e0bebfc194544774721 Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Wed, 12 Nov 2025 16:44:44 -0500 Subject: [PATCH 09/25] Updates to the various markdowns associated with the onboarding, capabilities, and certificate API sections. Additional improvements to the concepts section. Signed-off-by: Armand Craig --- .../client-onboarding.md | 26 +++++++--------- .../device-capabilities.md | 6 ++-- .../certificate-api.md | 6 ++-- .../deployment-status.md | 24 +++++++-------- .../device-capabilities.md | 30 +++++++++---------- .../device-onboarding.md | 19 ++++-------- 6 files changed, 49 insertions(+), 62 deletions(-) diff --git a/system-design/concepts/workload-fleet-managers/client-onboarding.md b/system-design/concepts/workload-fleet-managers/client-onboarding.md index df88bf9..4bde8a8 100644 --- a/system-design/concepts/workload-fleet-managers/client-onboarding.md +++ b/system-design/concepts/workload-fleet-managers/client-onboarding.md @@ -1,35 +1,31 @@ # Device Client Onboarding -Within Margo, late binding is an important non-functional requirement that enables a device to bind to any Margo compatible Workload Fleet Manager. To enable workload management, the device's client must first establish trust and complete an onboarding procedure with the End Users selected Workload Fleet Manager. +To enable workload management, the device's client must first establish trust and complete an onboarding process with the End Users selected Workload Fleet Manager. This onboarding process enables late binding, which is a critical Margo non-functional requirement that enables a device to bind to any Margo compatible Workload Fleet Manager. -The onboarding process includes the following major functions within Margo: -- trust establishment -- client onboarding -- device capability reporting +The onboarding process includes several core functions: + +- Establishing trust between the device and the WFM +- Registering the device client and assigning a unique identifier +- Reporting device capabilities to enable workload placement decisions ## Trust Establishment -Initial trust is established between the device’s management client and the Workload Fleet Management (WFM) web service using server-side TLS. The device downloads the WFM’s public root CA certificate via the onboarding API, or receives it via out-of-band strategies. The device injects the root CA into its trusted store, enabling secure TLS handshakes and certificate validation. This process avoids mTLS due to infrastructure compatibility concerns and relies on certificate-based trust. +Initial trust is established between the device’s management client and the Workload Fleet Management (WFM) web service using server-side TLS. The device downloads the WFM’s public root CA certificate via the onboarding API, or receives it via out-of-band strategies and injects into it's trusted certificate store. This enables secure TLS handshakes and certificate validation without requiring mutual TLS (mTLS), which was deliberately avoided due to infrastructure compatibility constraints. Instead, Margo relies on certificate-based trust, balancing security with operational simplicity. ## Certificates required -Both the WFM server and device clients use X.509 certificates for identity and secure communication. The server’s certificate is used for TLS authentication; the device client is issued a unique certificate for payload signing and integrity. Certificates are used to sign API payloads, ensuring authenticity and integrity. Private keys are securely stored and used for signing operations. +Both the WFM server and device clients use X.509 certificates for identity and secure communication. The WFM's certificate authenticates the server during TLS sessions, while each device's client is issued a unique certificate for signing payloads. These certificates ensure that every interaction is verifiable and tamper-proof. Private keys remain securely stored on the device, and all signing operations occur locally, reducing exposure to key compromise. ## Unique Identifiers -The Workload Fleet Manager assigns a unique identifier to the device's management client during the onboarding process. This is needed to ensure unique interactions between each device with the Fleet Manager. Unique identifiers +The Workload Fleet Manager assigns a globally unique identifier to the device's management client during the onboarding process. This is needed to ensure unique interactions between each device with the Fleet Manager. ## Device Capability Reporting -After onboarding, the device client reports its capabilities to the WFM server using the Device API. The API operates over REST/HTTP1.1, exclusively on port 443. -Payloads are signed using the device’s X.509 certificate: -- The client creates a SHA256 hash of the base64-encoded payload (Content-Digest). -- A signature base string is constructed and signed with the client’s private key. -- The signature and digest are included in the HTTP headers. +After onboarding, the device client reports its capabilities to the WFM server using the device capability reporting API. -The WFM server verifies the signature using the client’s public key before processing the payload. -## The following pages provide further details on the concepts described above: +## The following pages provide further specification details on the concepts described above: - [API Security Details](../../specification/margo-management-interface/api-requirements-and-security.md) - [Certificate API](../../specification/margo-management-interface/certificate-api.md) - [Device Onboarding API](../../specification/margo-management-interface/device-onboarding.md) diff --git a/system-design/concepts/workload-fleet-managers/device-capabilities.md b/system-design/concepts/workload-fleet-managers/device-capabilities.md index 4810ce1..a5d8b13 100644 --- a/system-design/concepts/workload-fleet-managers/device-capabilities.md +++ b/system-design/concepts/workload-fleet-managers/device-capabilities.md @@ -1,12 +1,12 @@ # Device Capabilities -The purpose of device capabilities reporting is to ensure the Workload Fleet Management (WFM) solution has the information needed to pair workloads with compatible edge devices. The device's capabilities are reported to the WFM web service using the Margo Management API. +The purpose of device capabilities reporting is to ensure the Workload Fleet Management (WFM) solution has the information needed to pair workloads with compatible edge devices. The device's capabilities are reported to the WFM web service using the [Device Capabilities API](../../specification/margo-management-interface/device-capabilities.md). ### Device Capability Reporting -The device owner MUST report their device's capabilities and characteristics, via the device API, when onboarding the device with the Workload Fleet Management solution. Additionally, during the lifecycle of the edge device, if there is a change that impacts the reported characteristics, the device MUST update the Workload Fleet Manager with the latest information via the management API. +The device owner reports their device's capabilities and characteristics, via the device API, when onboarding the device with the Workload Fleet Management solution. Additionally, during the lifecycle of the edge device, if there is a change that impacts the reported characteristics, the device updates the Workload Fleet Manager with the latest information via the [Device Capabilities API](../../specification/margo-management-interface/device-capabilities.md). -The following information MUST be provided: +The following information is exchanged: - Device Id - Device Vendor diff --git a/system-design/specification/margo-management-interface/certificate-api.md b/system-design/specification/margo-management-interface/certificate-api.md index 9889673..e6fc102 100644 --- a/system-design/specification/margo-management-interface/certificate-api.md +++ b/system-design/specification/margo-management-interface/certificate-api.md @@ -2,7 +2,7 @@ In order to facilitate secure communication between the device's management client and the Workload Fleet Manager, the device must first retrieve the root CA certificate using the Onboarding API's `certificate` endpoint. -### Route and HTTP Methods +## Route and HTTP Methods ```http GET /api/v1/onboarding/certificate @@ -11,9 +11,9 @@ GET /api/v1/onboarding/certificate | Code | Description | |------|-------------| -| 200 OK | Root CA provided in response | +| 200 OK | Root CA certificate | -### Response Body +## Example Response Body ```json { diff --git a/system-design/specification/margo-management-interface/deployment-status.md b/system-design/specification/margo-management-interface/deployment-status.md index 755f849..2716c56 100644 --- a/system-design/specification/margo-management-interface/deployment-status.md +++ b/system-design/specification/margo-management-interface/deployment-status.md @@ -2,10 +2,10 @@ While applying a new desired state, the device's management client MUST provide the Workload Fleet Manager service with an indication of the current workload deployment status. This is done by calling the Device API's `deployment status` endpoint. -### Route and HTTP Methods +## Route and HTTP Methods ```https -POST /api/v1/client/{clientId}/deployment/{deploymentId}/status +POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status ``` ### Route Parameters @@ -15,7 +15,7 @@ POST /api/v1/client/{clientId}/deployment/{deploymentId}/status | {clientId} | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | | {deploymentId} | string | Y | The UUID of the `ApplicationDeployment` YAML being reported. -### Response Code +### Response Codes | Code | Description | |------|-------------| @@ -26,24 +26,24 @@ POST /api/v1/client/{clientId}/deployment/{deploymentId}/status | 422 Unprocessable Content | Request body includes a semantic error. | -### Request Body Fields +## Request Body Attributes | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| -| apiVersion | string | Y | Identifier of the version of the API the object definition follows.| -| kind | string | Y | Must be `DeploymentStatus`.| +| apiVersion | string | Y | Identifier of the version the API resource follows.| +| kind | string | Y | Must be `DeploymentStatusManifest`.| | deploymentId | string | Y | The unique identifier UUID of the deployment specification. Needs to be assigned by the Workload Fleet Management Software. | | status | []status | Y | Element that defines overall deployment status. See the [Status Fields](#status-fields) section below.| | components | []components | Y | Element that defines the individual component's deployment status. See the [Component Fields](#component-fields) section below.| -#### Status Fields +#### Status Attributes | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| | state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: Pending, Installing, Installed, Removing, Removed, Failed. The overall deployment status MUST inherit the current component's status until it has gone through installing each component.| | error | Error | N | Element that defines the overall installation error if one occured. See the [Error Fields](#error-fields) section below.| -#### Component Fields +#### Component Attributes | Attribute | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| @@ -51,19 +51,19 @@ POST /api/v1/client/{clientId}/deployment/{deploymentId}/status | state | string | Y | The component's current deployment state of the component. MUST be one of the following options: Pending, Installing, Installed, Removing, Removed, Failed | | error | Error | N | Element that defines the components installation error if one occured. See the [Error Fields](#error-fields) section below. | -#### Error Fields +#### Error Attributes | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| | code | string | Y | Associated error code following a component failure during installation. | | message | string | Y | Associated error message that provides further details to the WOS about the error that was encountered. | -### Example Request +## Example Deployment Status Manifest Request ```json { - "apiVersion": "deployment.margo/v1", - "kind": "DeploymentStatus", + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", "status": { "state": "pending", diff --git a/system-design/specification/margo-management-interface/device-capabilities.md b/system-design/specification/margo-management-interface/device-capabilities.md index 380f7ad..da51f37 100644 --- a/system-design/specification/margo-management-interface/device-capabilities.md +++ b/system-design/specification/margo-management-interface/device-capabilities.md @@ -1,14 +1,14 @@ # Device Capabilities -Devices MUST provide the Workload Fleet Management service with its capabilities and characteristics. This is done by calling the Device API's `device capabilities` endpoint. +Devices MUST provide the Workload Fleet Management service with its capabilities and characteristics. This is done by calling the Device API's `device capabilities` endpoint. Reporting the device capabilities is the final step in the onboarding of the device's client. To ensure the WFM is kept up to date, the device's client MUST send updated capabilities information if any changes occur to the information originally provided (i.e., additional memory is added to the device). -### Route and HTTP Methods +## Route and HTTP Methods ```https -POST /api/v1/client/{clientId}/capabilities -PUT /api/v1/client/{clientId}/capabilities +POST /api/v1/clients/{clientId}/capabilities +PUT /api/v1/clients/{clientId}/capabilities ``` ### Route Parameters @@ -17,7 +17,7 @@ PUT /api/v1/client/{clientId}/capabilities |----------|------|-----------|------------| | {clientId} | string | Y | The unique identifier of the (device) client registered with the WFM during onboarding. | -### Response Code +### Response Codes | Code | Description | |------|-------------| @@ -27,12 +27,12 @@ PUT /api/v1/client/{clientId}/capabilities | 403 Forbidden | Client certificate is not trusted or has been revoked. | | 422 Unprocessable Content | Request body includes a semantic error. | -### Request Body Attributes +## Request Body Attributes | Field | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| -| apiVersion | string | Y | Identifier of the version of the API the object definition follows.| -| kind | string | Y | Must be `DeviceCapabilities`.| +| apiVersion | string | Y | Identifier of the version the API resource follows.| +| kind | string | Y | Must be `DeviceCapabilitiesManifest`.| | properties | Properties | Y | Element that defines characteristics about the device. See the [Properties Fields](#properties-fields) section below. | ### Properties Attributes @@ -84,10 +84,10 @@ Communication interface of a device. | --- | --- | --- | --- | | type | CommunicationInterfaceType | Y | The type of a communication interface. This can be e.g. Ethernet, WiFi, Cellular, Bluetooth, USB, CANBus, RS232. See the [CommunicationInterfaceType](#communicationinterfacetype) definition for all permissible values.| -## Enumerations +### Enumerations These enumerations are used as vocabularies for attribute values of the `DeviceCapabilities`. -### CpuArchitectureType +#### CpuArchitectureType | Permissible Values | Description | | --- | --- | @@ -96,7 +96,7 @@ These enumerations are used as vocabularies for attribute values of the `DeviceC | arm64 | ARM 64-bit architecture.| | arm | ARM 32-bit architecture. | -### CommunicationInterfaceType +#### CommunicationInterfaceType | Permissible Values | Description | | --- | --- | @@ -108,7 +108,7 @@ These enumerations are used as vocabularies for attribute values of the `DeviceC | canbus | This type stands for a CANBus interface.| | rs232 | This type stands for a RS232 interface. | -### PeripheralType +#### PeripheralType | Permissible Values | Description | | --- | --- | @@ -119,12 +119,12 @@ These enumerations are used as vocabularies for attribute values of the `DeviceC | speaker | This type stands for a speaker peripheral. | -### Example Request +## Example Device Capabilities Manifest Request ```json { - "apiVersion": "device.margo/v1", - "kind": "DeviceCapabilities", + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", "properties": { "id": "northstarida.xtapro.k8s.edge", "vendor": "Northstar Industrial devices", diff --git a/system-design/specification/margo-management-interface/device-onboarding.md b/system-design/specification/margo-management-interface/device-onboarding.md index e2d24af..249073c 100644 --- a/system-design/specification/margo-management-interface/device-onboarding.md +++ b/system-design/specification/margo-management-interface/device-onboarding.md @@ -3,21 +3,20 @@ In order for the Workload Fleet Management software to manage the edge device's ## Onboarding API Details -### Route and HTTP Methods +## Route and HTTP Methods ```https POST /api/v1/onboarding ``` -### Response Code +### Response Codes | Code | Description | |------|-------------| -| 200 OK | Certificate already present, onboarding successful. | | 201 Created | New client onboarded successfully. | | 400 Invalid Certificate | Invalid certificate format or structure. | -| 403 Forbidden | Client certificate is not trusted or has been rejected. | +| 403 Forbidden | Client certificate is not trusted or client rejected. | -### Response Body +## Example Response Body ```json { @@ -76,12 +75,4 @@ sequenceDiagram Note over Client,Server: 📡 Secure API Usage with Signed Payloads Client->>Server: POST /client/{clientId}/deployment/{deploymentId}/status Server-->>Client: 201 Created -``` - -#### Sequence Diagram Notes -- Following Step 3: Root CA is now trusted in the TLS handshake -- Diagram depicts a standard TLS flow, but additional steps in the handshake can occur. -- (After post /onboarding) - - Verification of client cert out of scope of this. Pre specify - - Step approves the client can join the server. Additional information can be tied to the certificate but are not required in this SUP. supporting information can also be transferred during this step approving this client can join the server. other things could be tied to the certificate. i.e. Cert supplied via Dell / serial number of device / - - FDO bootstrapping off of ownership vouchers could be integrated here as well. \ No newline at end of file +``` \ No newline at end of file From e99403c04a3aad73def7d61813089dc019cae025 Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Mon, 24 Nov 2025 15:41:03 -0500 Subject: [PATCH 10/25] Addressed feedback received via internal review. Signed-off-by: Armand Craig --- .../client-onboarding.md | 13 ++- .../api-requirements-and-security.md | 70 ++++++++++------ .../certificate-api.md | 4 + .../deployment-status.md | 16 ++-- .../device-capabilities.md | 2 + .../device-onboarding.md | 82 ++++++++++++------- 6 files changed, 124 insertions(+), 63 deletions(-) diff --git a/system-design/concepts/workload-fleet-managers/client-onboarding.md b/system-design/concepts/workload-fleet-managers/client-onboarding.md index 4bde8a8..7c79474 100644 --- a/system-design/concepts/workload-fleet-managers/client-onboarding.md +++ b/system-design/concepts/workload-fleet-managers/client-onboarding.md @@ -10,11 +10,20 @@ The onboarding process includes several core functions: ## Trust Establishment -Initial trust is established between the device’s management client and the Workload Fleet Management (WFM) web service using server-side TLS. The device downloads the WFM’s public root CA certificate via the onboarding API, or receives it via out-of-band strategies and injects into it's trusted certificate store. This enables secure TLS handshakes and certificate validation without requiring mutual TLS (mTLS), which was deliberately avoided due to infrastructure compatibility constraints. Instead, Margo relies on certificate-based trust, balancing security with operational simplicity. +Initial trust is established between the device's Workload Fleet Management (WFM) Client and the WFM using server-side TLS. +Before the WFM Client can connect securely, it must obtain the WFM's root CA certificate. This trust anchor may be: + +- downloaded via the Certificate API, provided that an existing trusted channel is available, or +- delivered out-of-band (e.g. preloaded by the device owner or transferred via USB) + +Importing the WFM's root CA certificate enables the WFM Client to authenticate the WFM during TLS connections. Mutual TLS (mTLS) is deliberately avoided, as some deployment environments include network components or intermediaries that may not support or forward client-certificate authentication. +Instead, transport security and server authentication are provided by server-side TLS, while client authentication and request integrity are performed at the application layer: the WFM Client uses its own X.509 certificate to create HTTP message signatures for each request. This approach maintains strong, certificate-based authenticity and integrity while accommodating a wide range of network architectures. + ## Certificates required -Both the WFM server and device clients use X.509 certificates for identity and secure communication. The WFM's certificate authenticates the server during TLS sessions, while each device's client is issued a unique certificate for signing payloads. These certificates ensure that every interaction is verifiable and tamper-proof. Private keys remain securely stored on the device, and all signing operations occur locally, reducing exposure to key compromise. +Both the WFM server and the WFM Client use X.509 certificates, but for different purposes. The WFM's certificate authenticates the server during TLS sessions. Each device client possesses a unique X.509 certificate used to sign its HTTP requests, enabling the WFM to verify the origin and integrity of every message. These certificates provide complementary security properties: TLS ensures transport confidentiality and server authenticity, while application-layer signatures provide client authentication and payload integrity. Private keys remain securely stored on the device, and all signing operations occur locally, reducing exposure to key compromise. + ## Unique Identifiers diff --git a/system-design/specification/margo-management-interface/api-requirements-and-security.md b/system-design/specification/margo-management-interface/api-requirements-and-security.md index e0489c4..9aea7fd 100644 --- a/system-design/specification/margo-management-interface/api-requirements-and-security.md +++ b/system-design/specification/margo-management-interface/api-requirements-and-security.md @@ -1,7 +1,7 @@ # API Requirements and Security Details ## General Requirements - The Workload Fleet Management supplier MUST implement the server side of the API specification contract. -- The Device Owner MUST implement the client side of the API specification contract. +- The Device supplier, via it's WFM Client, MUST implement the client side of the API specification contract. Below is a breakdown of the three major categories these requirements fall under: @@ -26,13 +26,15 @@ Server-side TLS REST API MUST be utilized operating over HTTP1.1. - The motivation to utilize HTTP1.1 is to ensure maximum support for existing infrastructure within our install base. - Server-side tls is utilized instead of mTLS due to possible issues with TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection. See [Security and Integrity](#security-and-integrity-information) section for more details. -- This REST API should utilize a known root CA the client can download, which enables the TLS handshake and other onboarding credentials. +- The client MUST trust the WFM's server certificate through a pre-provisioned or securely obtained root CA. + - The Certificate API MAY be used to retrieve this CA over an already trusted channel. #### Authentication Mechanism Initial trust is accomplished via TLS version 1.3 or greater - The device establishes a secure HTTPS connection using server-side TLS. - It validates the server’s identity using the public root CA certificate. +- Client authentication is achieved using application-layer HTTP Message Signatures (RFC 9421), as defined in the [Payload Security](#payload-security-method) section. #### API Port Details @@ -51,8 +53,16 @@ The WFM MUST create create a URL safe client id to uniquely identify each client #### Certificate Information Both the WFM and Device client MUST utilize a x.509 certificates to represent themselves within the API interactions. -- These certificates are utilized to prove each participants identity, establish secure TLS session, and securely transport information in secure envelopes. -- This proposal supports client authentication using X.509 certificates conforming to RFC 5280. Both RSA and ECC-based public key algorithms are accepted. +- The WFM's certificate is used to authenticate the server during TLS. The WFM Client’s certificate is used to authenticate the client and sign request payloads at the application layer, not during the TLS handshake. +- All client certificates MUST conform to RFC 5280 standards. +- Signature algorithm requirements: + - Implementations MUST support the following set of allowable signature algorithms: + - ecdsa-p256-sha256 + - ecdsa-p384-sha384 + - rsa-v1_5-sha256 + - rsa-pss-sha256 + - Additional algorithms MAY be supported, but the above list defines the minimum baseline for interoperability. + - The server MUST support all required algorithms (see above), so it can verify any compliant client, while clients MAY choose any of the required algorithms that fits their hardware capabilities. > Note: Further investigation and clarity to come regarding Margo's position on the root CA mentioned. @@ -67,34 +77,40 @@ Interface patterns MUST support extended device communication downtime. ### Payload Security Method #### Security and Integrity Information -- Due to the limitations of utilizing mTLS with common OT infrastructure components, such as TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection, Margo has adopted a certificate-based payload signing approach to protect payloads from being tampered with. By utilizing the certificates to create payload envelopes (HTTP Request body), the device's management client can ensure secure transport between the device's management client and the Workload Fleet Management's web service. - - For API security, Server side TLS 1.3 (minimum) is used, where the keys are obtained from the Server's X.509 Certificate as defined in standard HTTP over TLS - - For API integrity, the device's management client is issued a client specific X.509 certificate. - - The issuer of the client X.509 certificate is trusted under the assumption that the root CA download to the Workload Fleet Management server occurs as a precondition to onboarding the devices - - Similarly the issuer of the server X.509 certificate is trusted under the assumption that the root CA download to the device's management client occurs over a "protected" connection as part of the yet to be defined device onboarding procedure +Due to the limitations of utilizing mTLS with common OT infrastructure components, such as TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection, Margo has adopted a certificate-based payload signing approach to protect payloads from being tampered with. By utilizing the certificates to create payload envelopes (HTTP Request body), the device's management client can ensure secure transport between the device's management client and the Workload Fleet Management's web service. + +- For API security, Server side TLS 1.3 (minimum) is used, where the keys are obtained from the Server's X.509 Certificate as defined in standard HTTP over TLS +- For API integrity, the device's management client is issued a client specific X.509 certificate. +- The issuer of the client X.509 certificate is trusted under the assumption that the root CA download to the Workload Fleet Management server occurs as a precondition to onboarding the devices +- Similarly the issuer of the server X.509 certificate is trusted under the assumption that the root CA download to the device's management client occurs over a "protected" connection as part of the yet to be defined device onboarding procedure #### Device Management Client -- Once the device management client has a message prepared for the Workload Fleet Management's web service, it MUST complete the following to establish the integrity of the message as defined in RFC 9421 : - - The device's management client MUST create SHA256 hash Message-Digest of the base64 encoded payload (HTTP Request Body). This forms the 'Content-Digest' parameter in the HTTP Header. +Once the device management client has a message prepared for the Workload Fleet Management's web service, it MUST establish message integrity as defined in RFC 9421 by performing the following steps: + +- The device's management client MUST generate a SHA256 digest of the HTTP request body. Encode the digest in Base64 and include in the Content-Digest header. +``` + Content-Digest: sha-256=:: +``` +- The device management client MUST create a Signature Base String including @method, @target-uri, and Content-Digest. An example is given below. +``` + @method: POST + @target-uri: https://api.example.com/resource + Content-Digest: sha-256=:: + @signature-params: ("@method" "@target-uri" "Content-Digest");created=1680575171;keyid="my-rsa-key" +``` +- The device management client MUST generate the Signature field by signing the raw byte array of the Signature Base String using the clients X.509 private key. The resulting signature in Base64 is included in the Signature header. +- The devices's management client MUST insert the following in the HTTP1.1 Header: + - Content-Digest as formed above + - Signature-Input as given below, replacing the created and keyid parts appropriately: ``` - Content-Digest: sha-256=:: + sig1=("@method" "@target-uri" "Content-Digest");created=;keyid="" ``` - - The device management client MUST create a Signature Base String embedding the content-digest. An example is given below. + - Signature: ``` - @method: POST - @target-uri: https://api.example.com/resource - Content-Digest: sha-256=:: - @signature-params: ("@method" "@target-uri" "Content-Digest");created=1680575171;keyid="my-rsa-key" + sig1=:: ``` - - The device management client MUST create the Signature field by signing the SHA256 hash of the Base64 encoded Signature Base String, using the client X.509 RSA Private Key - - The devices's management client MUST insert the following in the HTTP1.1 Header : - - Content-Digest as formed above - - Signature-Input as given below, replacing the created and keyid parts appropriately : - ``` - sig1=("@method" "@target-uri" "Content-Digest");created=;keyid="" - ``` - - Signature as explained above - - The base64 encoded signature of the SHA256 has of the payload, signed with the private-key of the Client X.509 certificate - Note: The private-key is not stored in the X.509 certificate, it may be stored in a .pem file and this information is used while generating the X.509 certificate for the client + +> Note: The server MUST use the 'created' value to detect and prevent replay attacks. + #### Workload Fleet Manager Web-Service - On receiving the message from the Device Client, The Workload Fleet Management's web service MUST do the following : - It looks up the client certificate from the Client-ID in the API Request URL diff --git a/system-design/specification/margo-management-interface/certificate-api.md b/system-design/specification/margo-management-interface/certificate-api.md index e6fc102..1c03fc5 100644 --- a/system-design/specification/margo-management-interface/certificate-api.md +++ b/system-design/specification/margo-management-interface/certificate-api.md @@ -2,6 +2,10 @@ In order to facilitate secure communication between the device's management client and the Workload Fleet Manager, the device must first retrieve the root CA certificate using the Onboarding API's `certificate` endpoint. +- This endpoint MAY only be used to retrieve the root CA over an already trusted channel. +- If no trusted channel exists, the root CA MUST be provided via out-of-band method. +- In the response body, the certificate field MUST contain the PEM-encoded X.509 root CA certificate, Base64 without line breaks. + ## Route and HTTP Methods ```http diff --git a/system-design/specification/margo-management-interface/deployment-status.md b/system-design/specification/margo-management-interface/deployment-status.md index 2716c56..65a1f71 100644 --- a/system-design/specification/margo-management-interface/deployment-status.md +++ b/system-design/specification/margo-management-interface/deployment-status.md @@ -2,10 +2,12 @@ While applying a new desired state, the device's management client MUST provide the Workload Fleet Manager service with an indication of the current workload deployment status. This is done by calling the Device API's `deployment status` endpoint. +- Requests to this endpoint MUST be authenticated using the HTTP Message Signature method as defined in the [Payload Security](../margo-management-interface/api-requirements-and-security.md#payload-security-method) section. + ## Route and HTTP Methods ```https -POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status +POST /api/v1/clients/{clientId}/deployments/{deploymentId}/status ``` ### Route Parameters @@ -40,7 +42,7 @@ POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| -| state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: Pending, Installing, Installed, Removing, Removed, Failed. The overall deployment status MUST inherit the current component's status until it has gone through installing each component.| +| state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: pending, installing, installed, removing, removed, failed. The overall deployment status MUST reflect the most severe of the components states, following this precedence: failed > removing > installing > pending > removing > installed.| | error | Error | N | Element that defines the overall installation error if one occured. See the [Error Fields](#error-fields) section below.| #### Component Attributes @@ -48,15 +50,19 @@ POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status | Attribute | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| | name | string | Y | Name of the deployment component, inherited via the deployment specification | -| state | string | Y | The component's current deployment state of the component. MUST be one of the following options: Pending, Installing, Installed, Removing, Removed, Failed | +| state | string | Y | The component's current deployment state of the component. MUST be one of the following options: pending, installing, installed, removing, removed, failed | | error | Error | N | Element that defines the components installation error if one occured. See the [Error Fields](#error-fields) section below. | +> Note: The components array MUST contain one entry for each "component" defined in the referenced ApplicationDeployment manifest. + #### Error Attributes | Fields | Type | Required? | Description | |-----------------|-----------------|-----------------|-----------------| | code | string | Y | Associated error code following a component failure during installation. | -| message | string | Y | Associated error message that provides further details to the WOS about the error that was encountered. | +| message | string | Y | Associated error message that provides further details to the WFM about the error that was encountered. | + +> Note: Error codes adn messages are implementation specific. ## Example Deployment Status Manifest Request @@ -86,7 +92,7 @@ POST /api/v1/clients/{clientId}/deployment/{deploymentId}/status "state": "pending", "error": { "code": "", - "message ": "" + "message": "" } } ] diff --git a/system-design/specification/margo-management-interface/device-capabilities.md b/system-design/specification/margo-management-interface/device-capabilities.md index da51f37..e8055f4 100644 --- a/system-design/specification/margo-management-interface/device-capabilities.md +++ b/system-design/specification/margo-management-interface/device-capabilities.md @@ -4,6 +4,8 @@ Devices MUST provide the Workload Fleet Management service with its capabilities To ensure the WFM is kept up to date, the device's client MUST send updated capabilities information if any changes occur to the information originally provided (i.e., additional memory is added to the device). +- Requests to this endpoint MUST be authenticated using the HTTP Message Signature method as defined in the [Payload Security](../margo-management-interface/api-requirements-and-security.md#payload-security-method) section. + ## Route and HTTP Methods ```https diff --git a/system-design/specification/margo-management-interface/device-onboarding.md b/system-design/specification/margo-management-interface/device-onboarding.md index 249073c..32d4dba 100644 --- a/system-design/specification/margo-management-interface/device-onboarding.md +++ b/system-design/specification/margo-management-interface/device-onboarding.md @@ -1,33 +1,12 @@ # Device Onboarding In order for the Workload Fleet Management software to manage the edge device's workloads, the device's management client must first complete onboarding. -## Onboarding API Details - -## Route and HTTP Methods - -```https -POST /api/v1/onboarding -``` -### Response Codes - -| Code | Description | -|------|-------------| -| 201 Created | New client onboarded successfully. | -| 400 Invalid Certificate | Invalid certificate format or structure. | -| 403 Forbidden | Client certificate is not trusted or client rejected. | - -## Example Response Body - -```json -{ - "client_id": "" -} -``` +- Requests to this endpoint MUST be authenticated using the HTTP Message Signature method as defined in the [Payload Security](../margo-management-interface/api-requirements-and-security.md#payload-security-method) section. ## Onboarding Sequence - The end user provides the the Workload Fleet Management web service's root URL to the device's management client -- The device's management client downloads the Workload Fleet Manager's public root CA certificate using the [Onboarding API](../../specification/margo-management-interface/certificate-api.md) +- The device's management client downloads the Workload Fleet Manager's public root CA certificate using the [Certificate API](../../specification/margo-management-interface/certificate-api.md) - Context and trust is established between the device's management client and the Workload Fleet Management web service - The device's management client uses the [Onboarding API](../../specification/margo-management-interface/certificate-api.md) to onboard with the Workload Fleet Management service by providing it's x.509 certificate - The device's management client receives it's unique client Id assigned via the Workload Fleet Manager @@ -42,7 +21,7 @@ sequenceDiagram participant Server Note over Client,Server: 🔐 Initial Trust Establishment. - Note over Client,Server: This root CA certificate could alternatively been provided out of band.
e.g.: USB Stick, from Device Fleet management onboarding, FDO workflow. + Note over Client,Server: The device's management client obtains the WFM's root CA certificate either out-of-band or via the Certificate API over an existing trusted channel. Client->>Server: GET /onboarding/certificate Server-->>Client: base64-encoded Root CA certificate Client-->>Client: injecting Root CA into trusted store @@ -59,20 +38,65 @@ sequenceDiagram WFMUser->>Server: Opportunity for user to approve or reject client onboarding alt Public key trusted/user approved Note over Server: Server verifies client certificate and assigns UUID - Server-->>Client: 201 Created { client_id } - else Public key invalid/Client rejected + Server-->>Client: 201 Created { clientId } + else Client rejected Server-->>Client: 400 Bad Request {error: "Invalid certificate"} + else Client rejected Server-->>Client: 403 Forbidden{ error: "Client rejected"} end + Note over Client,Server: Device Client onboarding Ends Note over Client,Server: 📡 Secure API Usage with Signed Payloads can now begin - Client->>Server: POST /client/{clientId}/capabilities + Client->>Server: POST /clients/{clientId}/capabilities Server-->>Client: 201 Created Note over Client,Server: Enrollment is complete Note over Client,Server: Assumed Desired state has been transmitted via WFM(out of scope for this SUP) Note over Client,Server: 📡 Secure API Usage with Signed Payloads - Client->>Server: POST /client/{clientId}/deployment/{deploymentId}/status + Client->>Server: POST /clients/{clientId}/deployments/{deploymentId}/status Server-->>Client: 201 Created -``` \ No newline at end of file +``` + +## Onboarding API Details + +## Route and HTTP Methods + +```https +POST /api/v1/onboarding +``` +## Request Body Attributes + +| Fields | Type | Required? | Description | +|-----------------|-----------------|-----------------|-----------------| +| apiVersion | string | Y | Identifier of the version the API resource follows.| +| kind | string | Y | Must be `OnboardingRequest`.| +| certificate | string | Y | Base64-encoded X.509 certificate of the client. | + +### Example Request Body + +```json +{ + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "MIIDdzCCAl+gAwIBAgIEb1......." +} +``` + +### Response Codes + +| Code | Description | +|------|-------------| +| 201 Created | New client onboarded successfully. | +| 400 Invalid Certificate | Invalid certificate format or structure. | +| 403 Forbidden | Client certificate is not trusted or client rejected. | + +## Example Response Body + +```json +{ + "clientId": "" +} +``` + + From 88df26104de47d88c6a9c330e9c56fc69a077eba Mon Sep 17 00:00:00 2001 From: Armand Craig Date: Tue, 25 Nov 2025 10:45:54 -0500 Subject: [PATCH 11/25] Embedded the management interface swagger definition. Signed-off-by: Armand Craig --- mkdocs.yml | 8 + system-design/assets/swagger-ui-bundle.js | 2 + .../assets/swagger-ui-standalone-preset.js | 2 + system-design/assets/swagger-ui.css | 3 + .../api-definition-swagger.md | 10 + .../workload-management-api-0.0.1.yaml | 657 ++++++++++++++++++ 6 files changed, 682 insertions(+) create mode 100644 system-design/assets/swagger-ui-bundle.js create mode 100644 system-design/assets/swagger-ui-standalone-preset.js create mode 100644 system-design/assets/swagger-ui.css create mode 100644 system-design/specification/margo-management-interface/api-definition-swagger.md create mode 100644 system-design/specification/margo-management-interface/workload-management-api-0.0.1.yaml diff --git a/mkdocs.yml b/mkdocs.yml index 94bd622..cfeb3c4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,6 +33,7 @@ nav: - specification/margo-management-interface/device-capabilities.md - specification/margo-management-interface/desired-state.md - specification/margo-management-interface/deployment-status.md + - specification/margo-management-interface/api-definition-swagger.md - Application Package: - specification/application-package/application-description.md - Margo Devices: @@ -80,6 +81,12 @@ markdown_extensions: extra_css: - css/margo.css + - assets/swagger-ui.css + +extra_javascript: + - assets/swagger-ui-bundle.js + - assets/swagger-ui-standalone-preset.js + extra: # https://squidfunk.github.io/mkdocs-material/setup/setting-up-the-footer/#generator-notice @@ -107,3 +114,4 @@ plugins: variable_start_string: =@= variable_end_string: =@= - privacy + diff --git a/system-design/assets/swagger-ui-bundle.js b/system-design/assets/swagger-ui-bundle.js new file mode 100644 index 0000000..27bd9ca --- /dev/null +++ b/system-design/assets/swagger-ui-bundle.js @@ -0,0 +1,2 @@ +/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ +!function webpackUniversalModuleDefinition(s,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.SwaggerUIBundle=o():s.SwaggerUIBundle=o()}(this,(()=>(()=>{var s={251:(s,o)=>{o.read=function(s,o,i,a,u){var _,w,x=8*u-a-1,C=(1<>1,L=-7,B=i?u-1:0,$=i?-1:1,V=s[o+B];for(B+=$,_=V&(1<<-L)-1,V>>=-L,L+=x;L>0;_=256*_+s[o+B],B+=$,L-=8);for(w=_&(1<<-L)-1,_>>=-L,L+=a;L>0;w=256*w+s[o+B],B+=$,L-=8);if(0===_)_=1-j;else{if(_===C)return w?NaN:1/0*(V?-1:1);w+=Math.pow(2,a),_-=j}return(V?-1:1)*w*Math.pow(2,_-a)},o.write=function(s,o,i,a,u,_){var w,x,C,j=8*_-u-1,L=(1<>1,$=23===u?Math.pow(2,-24)-Math.pow(2,-77):0,V=a?0:_-1,U=a?1:-1,z=o<0||0===o&&1/o<0?1:0;for(o=Math.abs(o),isNaN(o)||o===1/0?(x=isNaN(o)?1:0,w=L):(w=Math.floor(Math.log(o)/Math.LN2),o*(C=Math.pow(2,-w))<1&&(w--,C*=2),(o+=w+B>=1?$/C:$*Math.pow(2,1-B))*C>=2&&(w++,C/=2),w+B>=L?(x=0,w=L):w+B>=1?(x=(o*C-1)*Math.pow(2,u),w+=B):(x=o*Math.pow(2,B-1)*Math.pow(2,u),w=0));u>=8;s[i+V]=255&x,V+=U,x/=256,u-=8);for(w=w<0;s[i+V]=255&w,V+=U,w/=256,j-=8);s[i+V-U]|=128*z}},462:(s,o,i)=>{"use strict";var a=i(40975);s.exports=a},659:(s,o,i)=>{var a=i(51873),u=Object.prototype,_=u.hasOwnProperty,w=u.toString,x=a?a.toStringTag:void 0;s.exports=function getRawTag(s){var o=_.call(s,x),i=s[x];try{s[x]=void 0;var a=!0}catch(s){}var u=w.call(s);return a&&(o?s[x]=i:delete s[x]),u}},694:(s,o,i)=>{"use strict";i(91599);var a=i(37257);i(12560),s.exports=a},953:(s,o,i)=>{"use strict";s.exports=i(53375)},1733:s=>{var o=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;s.exports=function asciiWords(s){return s.match(o)||[]}},1882:(s,o,i)=>{var a=i(72552),u=i(23805);s.exports=function isFunction(s){if(!u(s))return!1;var o=a(s);return"[object Function]"==o||"[object GeneratorFunction]"==o||"[object AsyncFunction]"==o||"[object Proxy]"==o}},1907:(s,o,i)=>{"use strict";var a=i(41505),u=Function.prototype,_=u.call,w=a&&u.bind.bind(_,_);s.exports=a?w:function(s){return function(){return _.apply(s,arguments)}}},2205:function(s,o,i){var a;a=void 0!==i.g?i.g:this,s.exports=function(s){if(s.CSS&&s.CSS.escape)return s.CSS.escape;var cssEscape=function(s){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var o,i=String(s),a=i.length,u=-1,_="",w=i.charCodeAt(0);++u=1&&o<=31||127==o||0==u&&o>=48&&o<=57||1==u&&o>=48&&o<=57&&45==w?"\\"+o.toString(16)+" ":0==u&&1==a&&45==o||!(o>=128||45==o||95==o||o>=48&&o<=57||o>=65&&o<=90||o>=97&&o<=122)?"\\"+i.charAt(u):i.charAt(u):_+="�";return _};return s.CSS||(s.CSS={}),s.CSS.escape=cssEscape,cssEscape}(a)},2209:(s,o,i)=>{"use strict";var a,u=i(9404),_=function productionTypeChecker(){invariant(!1,"ImmutablePropTypes type checking code is stripped in production.")};_.isRequired=_;var w=function getProductionTypeChecker(){return _};function getPropType(s){var o=typeof s;return Array.isArray(s)?"array":s instanceof RegExp?"object":s instanceof u.Iterable?"Immutable."+s.toSource().split(" ")[0]:o}function createChainableTypeChecker(s){function checkType(o,i,a,u,_,w){for(var x=arguments.length,C=Array(x>6?x-6:0),j=6;j>",null!=i[a]?s.apply(void 0,[i,a,u,_,w].concat(C)):o?new Error("Required "+_+" `"+w+"` was not specified in `"+u+"`."):void 0}var o=checkType.bind(null,!1);return o.isRequired=checkType.bind(null,!0),o}function createIterableSubclassTypeChecker(s,o){return function createImmutableTypeChecker(s,o){return createChainableTypeChecker((function validate(i,a,u,_,w){var x=i[a];if(!o(x)){var C=getPropType(x);return new Error("Invalid "+_+" `"+w+"` of type `"+C+"` supplied to `"+u+"`, expected `"+s+"`.")}return null}))}("Iterable."+s,(function(s){return u.Iterable.isIterable(s)&&o(s)}))}(a={listOf:w,mapOf:w,orderedMapOf:w,setOf:w,orderedSetOf:w,stackOf:w,iterableOf:w,recordOf:w,shape:w,contains:w,mapContains:w,orderedMapContains:w,list:_,map:_,orderedMap:_,set:_,orderedSet:_,stack:_,seq:_,record:_,iterable:_}).iterable.indexed=createIterableSubclassTypeChecker("Indexed",u.Iterable.isIndexed),a.iterable.keyed=createIterableSubclassTypeChecker("Keyed",u.Iterable.isKeyed),s.exports=a},2404:(s,o,i)=>{var a=i(60270);s.exports=function isEqual(s,o){return a(s,o)}},2523:s=>{s.exports=function baseFindIndex(s,o,i,a){for(var u=s.length,_=i+(a?1:-1);a?_--:++_{"use strict";var a=i(45951),u=Object.defineProperty;s.exports=function(s,o){try{u(a,s,{value:o,configurable:!0,writable:!0})}catch(i){a[s]=o}return o}},2694:(s,o,i)=>{"use strict";var a=i(6925);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,s.exports=function(){function shim(s,o,i,u,_,w){if(w!==a){var x=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw x.name="Invariant Violation",x}}function getShim(){return shim}shim.isRequired=shim;var s={array:shim,bigint:shim,bool:shim,func:shim,number:shim,object:shim,string:shim,symbol:shim,any:shim,arrayOf:getShim,element:shim,elementType:shim,instanceOf:getShim,node:shim,objectOf:getShim,oneOf:getShim,oneOfType:getShim,shape:getShim,exact:getShim,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return s.PropTypes=s,s}},2874:s=>{s.exports={}},2875:(s,o,i)=>{"use strict";var a=i(23045),u=i(80376);s.exports=Object.keys||function keys(s){return a(s,u)}},2955:(s,o,i)=>{"use strict";var a,u=i(65606);function _defineProperty(s,o,i){return(o=function _toPropertyKey(s){var o=function _toPrimitive(s,o){if("object"!=typeof s||null===s)return s;var i=s[Symbol.toPrimitive];if(void 0!==i){var a=i.call(s,o||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===o?String:Number)(s)}(s,"string");return"symbol"==typeof o?o:String(o)}(o))in s?Object.defineProperty(s,o,{value:i,enumerable:!0,configurable:!0,writable:!0}):s[o]=i,s}var _=i(86238),w=Symbol("lastResolve"),x=Symbol("lastReject"),C=Symbol("error"),j=Symbol("ended"),L=Symbol("lastPromise"),B=Symbol("handlePromise"),$=Symbol("stream");function createIterResult(s,o){return{value:s,done:o}}function readAndResolve(s){var o=s[w];if(null!==o){var i=s[$].read();null!==i&&(s[L]=null,s[w]=null,s[x]=null,o(createIterResult(i,!1)))}}function onReadable(s){u.nextTick(readAndResolve,s)}var V=Object.getPrototypeOf((function(){})),U=Object.setPrototypeOf((_defineProperty(a={get stream(){return this[$]},next:function next(){var s=this,o=this[C];if(null!==o)return Promise.reject(o);if(this[j])return Promise.resolve(createIterResult(void 0,!0));if(this[$].destroyed)return new Promise((function(o,i){u.nextTick((function(){s[C]?i(s[C]):o(createIterResult(void 0,!0))}))}));var i,a=this[L];if(a)i=new Promise(function wrapForNext(s,o){return function(i,a){s.then((function(){o[j]?i(createIterResult(void 0,!0)):o[B](i,a)}),a)}}(a,this));else{var _=this[$].read();if(null!==_)return Promise.resolve(createIterResult(_,!1));i=new Promise(this[B])}return this[L]=i,i}},Symbol.asyncIterator,(function(){return this})),_defineProperty(a,"return",(function _return(){var s=this;return new Promise((function(o,i){s[$].destroy(null,(function(s){s?i(s):o(createIterResult(void 0,!0))}))}))})),a),V);s.exports=function createReadableStreamAsyncIterator(s){var o,i=Object.create(U,(_defineProperty(o={},$,{value:s,writable:!0}),_defineProperty(o,w,{value:null,writable:!0}),_defineProperty(o,x,{value:null,writable:!0}),_defineProperty(o,C,{value:null,writable:!0}),_defineProperty(o,j,{value:s._readableState.endEmitted,writable:!0}),_defineProperty(o,B,{value:function value(s,o){var a=i[$].read();a?(i[L]=null,i[w]=null,i[x]=null,s(createIterResult(a,!1))):(i[w]=s,i[x]=o)},writable:!0}),o));return i[L]=null,_(s,(function(s){if(s&&"ERR_STREAM_PREMATURE_CLOSE"!==s.code){var o=i[x];return null!==o&&(i[L]=null,i[w]=null,i[x]=null,o(s)),void(i[C]=s)}var a=i[w];null!==a&&(i[L]=null,i[w]=null,i[x]=null,a(createIterResult(void 0,!0))),i[j]=!0})),s.on("readable",onReadable.bind(null,i)),i}},3110:(s,o,i)=>{const a=i(5187),u=i(85015),_=i(98023),w=i(53812),x=i(23805),C=i(85105),j=i(86804);class Namespace{constructor(s){this.elementMap={},this.elementDetection=[],this.Element=j.Element,this.KeyValuePair=j.KeyValuePair,s&&s.noDefault||this.useDefault(),this._attributeElementKeys=[],this._attributeElementArrayKeys=[]}use(s){return s.namespace&&s.namespace({base:this}),s.load&&s.load({base:this}),this}useDefault(){return this.register("null",j.NullElement).register("string",j.StringElement).register("number",j.NumberElement).register("boolean",j.BooleanElement).register("array",j.ArrayElement).register("object",j.ObjectElement).register("member",j.MemberElement).register("ref",j.RefElement).register("link",j.LinkElement),this.detect(a,j.NullElement,!1).detect(u,j.StringElement,!1).detect(_,j.NumberElement,!1).detect(w,j.BooleanElement,!1).detect(Array.isArray,j.ArrayElement,!1).detect(x,j.ObjectElement,!1),this}register(s,o){return this._elements=void 0,this.elementMap[s]=o,this}unregister(s){return this._elements=void 0,delete this.elementMap[s],this}detect(s,o,i){return void 0===i||i?this.elementDetection.unshift([s,o]):this.elementDetection.push([s,o]),this}toElement(s){if(s instanceof this.Element)return s;let o;for(let i=0;i{const o=s[0].toUpperCase()+s.substr(1);this._elements[o]=this.elementMap[s]}))),this._elements}get serialiser(){return new C(this)}}C.prototype.Namespace=Namespace,s.exports=Namespace},3121:(s,o,i)=>{"use strict";var a=i(65482),u=Math.min;s.exports=function(s){var o=a(s);return o>0?u(o,9007199254740991):0}},3209:(s,o,i)=>{var a=i(91596),u=i(53320),_=i(36306),w="__lodash_placeholder__",x=128,C=Math.min;s.exports=function mergeData(s,o){var i=s[1],j=o[1],L=i|j,B=L<131,$=j==x&&8==i||j==x&&256==i&&s[7].length<=o[8]||384==j&&o[7].length<=o[8]&&8==i;if(!B&&!$)return s;1&j&&(s[2]=o[2],L|=1&i?0:4);var V=o[3];if(V){var U=s[3];s[3]=U?a(U,V,o[4]):V,s[4]=U?_(s[3],w):o[4]}return(V=o[5])&&(U=s[5],s[5]=U?u(U,V,o[6]):V,s[6]=U?_(s[5],w):o[6]),(V=o[7])&&(s[7]=V),j&x&&(s[8]=null==s[8]?o[8]:C(s[8],o[8])),null==s[9]&&(s[9]=o[9]),s[0]=o[0],s[1]=L,s}},3650:(s,o,i)=>{var a=i(74335)(Object.keys,Object);s.exports=a},3656:(s,o,i)=>{s=i.nmd(s);var a=i(9325),u=i(89935),_=o&&!o.nodeType&&o,w=_&&s&&!s.nodeType&&s,x=w&&w.exports===_?a.Buffer:void 0,C=(x?x.isBuffer:void 0)||u;s.exports=C},4509:(s,o,i)=>{var a=i(12651);s.exports=function mapCacheHas(s){return a(this,s).has(s)}},4640:s=>{"use strict";var o=String;s.exports=function(s){try{return o(s)}catch(s){return"Object"}}},4664:(s,o,i)=>{var a=i(79770),u=i(63345),_=Object.prototype.propertyIsEnumerable,w=Object.getOwnPropertySymbols,x=w?function(s){return null==s?[]:(s=Object(s),a(w(s),(function(o){return _.call(s,o)})))}:u;s.exports=x},4901:(s,o,i)=>{var a=i(72552),u=i(30294),_=i(40346),w={};w["[object Float32Array]"]=w["[object Float64Array]"]=w["[object Int8Array]"]=w["[object Int16Array]"]=w["[object Int32Array]"]=w["[object Uint8Array]"]=w["[object Uint8ClampedArray]"]=w["[object Uint16Array]"]=w["[object Uint32Array]"]=!0,w["[object Arguments]"]=w["[object Array]"]=w["[object ArrayBuffer]"]=w["[object Boolean]"]=w["[object DataView]"]=w["[object Date]"]=w["[object Error]"]=w["[object Function]"]=w["[object Map]"]=w["[object Number]"]=w["[object Object]"]=w["[object RegExp]"]=w["[object Set]"]=w["[object String]"]=w["[object WeakMap]"]=!1,s.exports=function baseIsTypedArray(s){return _(s)&&u(s.length)&&!!w[a(s)]}},4993:(s,o,i)=>{"use strict";var a=i(16946),u=i(74239);s.exports=function(s){return a(u(s))}},5187:s=>{s.exports=function isNull(s){return null===s}},5419:s=>{s.exports=function(s,o,i,a){var u=new Blob(void 0!==a?[a,s]:[s],{type:i||"application/octet-stream"});if(void 0!==window.navigator.msSaveBlob)window.navigator.msSaveBlob(u,o);else{var _=window.URL&&window.URL.createObjectURL?window.URL.createObjectURL(u):window.webkitURL.createObjectURL(u),w=document.createElement("a");w.style.display="none",w.href=_,w.setAttribute("download",o),void 0===w.download&&w.setAttribute("target","_blank"),document.body.appendChild(w),w.click(),setTimeout((function(){document.body.removeChild(w),window.URL.revokeObjectURL(_)}),200)}}},5556:(s,o,i)=>{s.exports=i(2694)()},5861:(s,o,i)=>{var a=i(55580),u=i(68223),_=i(32804),w=i(76545),x=i(28303),C=i(72552),j=i(47473),L="[object Map]",B="[object Promise]",$="[object Set]",V="[object WeakMap]",U="[object DataView]",z=j(a),Y=j(u),Z=j(_),ee=j(w),ie=j(x),ae=C;(a&&ae(new a(new ArrayBuffer(1)))!=U||u&&ae(new u)!=L||_&&ae(_.resolve())!=B||w&&ae(new w)!=$||x&&ae(new x)!=V)&&(ae=function(s){var o=C(s),i="[object Object]"==o?s.constructor:void 0,a=i?j(i):"";if(a)switch(a){case z:return U;case Y:return L;case Z:return B;case ee:return $;case ie:return V}return o}),s.exports=ae},6048:s=>{s.exports=function negate(s){if("function"!=typeof s)throw new TypeError("Expected a function");return function(){var o=arguments;switch(o.length){case 0:return!s.call(this);case 1:return!s.call(this,o[0]);case 2:return!s.call(this,o[0],o[1]);case 3:return!s.call(this,o[0],o[1],o[2])}return!s.apply(this,o)}}},6205:s=>{s.exports={ROOT:0,GROUP:1,POSITION:2,SET:3,RANGE:4,REPETITION:5,REFERENCE:6,CHAR:7}},6233:(s,o,i)=>{const a=i(6048),u=i(10316),_=i(92340);class ArrayElement extends u{constructor(s,o,i){super(s||[],o,i),this.element="array"}primitive(){return"array"}get(s){return this.content[s]}getValue(s){const o=this.get(s);if(o)return o.toValue()}getIndex(s){return this.content[s]}set(s,o){return this.content[s]=this.refract(o),this}remove(s){const o=this.content.splice(s,1);return o.length?o[0]:null}map(s,o){return this.content.map(s,o)}flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(a);u&&i.push(u)})),i}filter(s,o){return new _(this.content.filter(s,o))}reject(s,o){return this.filter(a(s),o)}reduce(s,o){let i,a;void 0!==o?(i=0,a=this.refract(o)):(i=1,a="object"===this.primitive()?this.first.value:this.first);for(let o=i;o{s.bind(o)(i,this.refract(a))}))}shift(){return this.content.shift()}unshift(s){this.content.unshift(this.refract(s))}push(s){return this.content.push(this.refract(s)),this}add(s){this.push(s)}findElements(s,o){const i=o||{},a=!!i.recursive,u=void 0===i.results?[]:i.results;return this.forEach(((o,i,_)=>{a&&void 0!==o.findElements&&o.findElements(s,{results:u,recursive:a}),s(o,i,_)&&u.push(o)})),u}find(s){return new _(this.findElements(s,{recursive:!0}))}findByElement(s){return this.find((o=>o.element===s))}findByClass(s){return this.find((o=>o.classes.includes(s)))}getById(s){return this.find((o=>o.id.toValue()===s)).first}includes(s){return this.content.some((o=>o.equals(s)))}contains(s){return this.includes(s)}empty(){return new this.constructor([])}"fantasy-land/empty"(){return this.empty()}concat(s){return new this.constructor(this.content.concat(s.content))}"fantasy-land/concat"(s){return this.concat(s)}"fantasy-land/map"(s){return new this.constructor(this.map(s))}"fantasy-land/chain"(s){return this.map((o=>s(o)),this).reduce(((s,o)=>s.concat(o)),this.empty())}"fantasy-land/filter"(s){return new this.constructor(this.content.filter(s))}"fantasy-land/reduce"(s,o){return this.content.reduce(s,o)}get length(){return this.content.length}get isEmpty(){return 0===this.content.length}get first(){return this.getIndex(0)}get second(){return this.getIndex(1)}get last(){return this.getIndex(this.length-1)}}ArrayElement.empty=function empty(){return new this},ArrayElement["fantasy-land/empty"]=ArrayElement.empty,"undefined"!=typeof Symbol&&(ArrayElement.prototype[Symbol.iterator]=function symbol(){return this.content[Symbol.iterator]()}),s.exports=ArrayElement},6499:(s,o,i)=>{"use strict";var a=i(1907),u=0,_=Math.random(),w=a(1..toString);s.exports=function(s){return"Symbol("+(void 0===s?"":s)+")_"+w(++u+_,36)}},6925:s=>{"use strict";s.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},7057:(s,o,i)=>{"use strict";var a=i(11470).charAt,u=i(90160),_=i(64932),w=i(60183),x=i(59550),C="String Iterator",j=_.set,L=_.getterFor(C);w(String,"String",(function(s){j(this,{type:C,string:u(s),index:0})}),(function next(){var s,o=L(this),i=o.string,u=o.index;return u>=i.length?x(void 0,!0):(s=a(i,u),o.index+=s.length,x(s,!1))}))},7309:(s,o,i)=>{var a=i(62006)(i(24713));s.exports=a},7376:s=>{"use strict";s.exports=!0},7463:(s,o,i)=>{"use strict";var a=i(98828),u=i(62250),_=/#|\.prototype\./,isForced=function(s,o){var i=x[w(s)];return i===j||i!==C&&(u(o)?a(o):!!o)},w=isForced.normalize=function(s){return String(s).replace(_,".").toLowerCase()},x=isForced.data={},C=isForced.NATIVE="N",j=isForced.POLYFILL="P";s.exports=isForced},7666:(s,o,i)=>{var a=i(84851),u=i(953);function _extends(){var o;return s.exports=_extends=a?u(o=a).call(o):function(s){for(var o=1;o{const a=i(6205);o.wordBoundary=()=>({type:a.POSITION,value:"b"}),o.nonWordBoundary=()=>({type:a.POSITION,value:"B"}),o.begin=()=>({type:a.POSITION,value:"^"}),o.end=()=>({type:a.POSITION,value:"$"})},8068:s=>{"use strict";var o=(()=>{var s=Object.defineProperty,o=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getOwnPropertySymbols,u=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable,__defNormalProp=(o,i,a)=>i in o?s(o,i,{enumerable:!0,configurable:!0,writable:!0,value:a}):o[i]=a,__spreadValues=(s,o)=>{for(var i in o||(o={}))u.call(o,i)&&__defNormalProp(s,i,o[i]);if(a)for(var i of a(o))_.call(o,i)&&__defNormalProp(s,i,o[i]);return s},__publicField=(s,o,i)=>(__defNormalProp(s,"symbol"!=typeof o?o+"":o,i),i),w={};((o,i)=>{for(var a in i)s(o,a,{get:i[a],enumerable:!0})})(w,{DEFAULT_OPTIONS:()=>C,DEFAULT_UUID_LENGTH:()=>x,default:()=>B});var x=6,C={dictionary:"alphanum",shuffle:!0,debug:!1,length:x,counter:0},j=class _ShortUniqueId{constructor(s={}){__publicField(this,"counter"),__publicField(this,"debug"),__publicField(this,"dict"),__publicField(this,"version"),__publicField(this,"dictIndex",0),__publicField(this,"dictRange",[]),__publicField(this,"lowerBound",0),__publicField(this,"upperBound",0),__publicField(this,"dictLength",0),__publicField(this,"uuidLength"),__publicField(this,"_digit_first_ascii",48),__publicField(this,"_digit_last_ascii",58),__publicField(this,"_alpha_lower_first_ascii",97),__publicField(this,"_alpha_lower_last_ascii",123),__publicField(this,"_hex_last_ascii",103),__publicField(this,"_alpha_upper_first_ascii",65),__publicField(this,"_alpha_upper_last_ascii",91),__publicField(this,"_number_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii]}),__publicField(this,"_alpha_dict_ranges",{lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alpha_lower_dict_ranges",{lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii]}),__publicField(this,"_alpha_upper_dict_ranges",{upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alphanum_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alphanum_lower_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii]}),__publicField(this,"_alphanum_upper_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_hex_dict_ranges",{decDigits:[this._digit_first_ascii,this._digit_last_ascii],alphaDigits:[this._alpha_lower_first_ascii,this._hex_last_ascii]}),__publicField(this,"_dict_ranges",{_number_dict_ranges:this._number_dict_ranges,_alpha_dict_ranges:this._alpha_dict_ranges,_alpha_lower_dict_ranges:this._alpha_lower_dict_ranges,_alpha_upper_dict_ranges:this._alpha_upper_dict_ranges,_alphanum_dict_ranges:this._alphanum_dict_ranges,_alphanum_lower_dict_ranges:this._alphanum_lower_dict_ranges,_alphanum_upper_dict_ranges:this._alphanum_upper_dict_ranges,_hex_dict_ranges:this._hex_dict_ranges}),__publicField(this,"log",((...s)=>{const o=[...s];if(o[0]=`[short-unique-id] ${s[0]}`,!0===this.debug&&"undefined"!=typeof console&&null!==console)return console.log(...o)})),__publicField(this,"_normalizeDictionary",((s,o)=>{let i;if(s&&Array.isArray(s)&&s.length>1)i=s;else{let o;i=[],this.dictIndex=o=0;const a=`_${s}_dict_ranges`,u=this._dict_ranges[a];Object.keys(u).forEach((s=>{const a=s;for(this.dictRange=u[a],this.lowerBound=this.dictRange[0],this.upperBound=this.dictRange[1],this.dictIndex=o=this.lowerBound;this.lowerBound<=this.upperBound?othis.upperBound;this.dictIndex=this.lowerBound<=this.upperBound?o+=1:o-=1)i.push(String.fromCharCode(this.dictIndex))}))}if(o){const s=.5;i=i.sort((()=>Math.random()-s))}return i})),__publicField(this,"setDictionary",((s,o)=>{this.dict=this._normalizeDictionary(s,o),this.dictLength=this.dict.length,this.setCounter(0)})),__publicField(this,"seq",(()=>this.sequentialUUID())),__publicField(this,"sequentialUUID",(()=>{let s,o,i="";s=this.counter;do{o=s%this.dictLength,s=Math.trunc(s/this.dictLength),i+=this.dict[o]}while(0!==s);return this.counter+=1,i})),__publicField(this,"rnd",((s=this.uuidLength||x)=>this.randomUUID(s))),__publicField(this,"randomUUID",((s=this.uuidLength||x)=>{let o,i,a;if(null==s||s<1)throw new Error("Invalid UUID Length Provided");for(o="",a=0;athis.formattedUUID(s,o))),__publicField(this,"formattedUUID",((s,o)=>{const i={$r:this.randomUUID,$s:this.sequentialUUID,$t:this.stamp};return s.replace(/\$[rs]\d{0,}|\$t0|\$t[1-9]\d{1,}/g,(s=>{const a=s.slice(0,2),u=parseInt(s.slice(2),10);return"$s"===a?i[a]().padStart(u,"0"):"$t"===a&&o?i[a](u,o):i[a](u)}))})),__publicField(this,"availableUUIDs",((s=this.uuidLength)=>parseFloat(Math.pow([...new Set(this.dict)].length,s).toFixed(0)))),__publicField(this,"approxMaxBeforeCollision",((s=this.availableUUIDs(this.uuidLength))=>parseFloat(Math.sqrt(Math.PI/2*s).toFixed(20)))),__publicField(this,"collisionProbability",((s=this.availableUUIDs(this.uuidLength),o=this.uuidLength)=>parseFloat((this.approxMaxBeforeCollision(s)/this.availableUUIDs(o)).toFixed(20)))),__publicField(this,"uniqueness",((s=this.availableUUIDs(this.uuidLength))=>{const o=parseFloat((1-this.approxMaxBeforeCollision(s)/s).toFixed(20));return o>1?1:o<0?0:o})),__publicField(this,"getVersion",(()=>this.version)),__publicField(this,"stamp",((s,o)=>{const i=Math.floor(+(o||new Date)/1e3).toString(16);if("number"==typeof s&&0===s)return i;if("number"!=typeof s||s<10)throw new Error(["Param finalLength must be a number greater than or equal to 10,","or 0 if you want the raw hexadecimal timestamp"].join("\n"));const a=s-9,u=Math.round(Math.random()*(a>15?15:a)),_=this.randomUUID(a);return`${_.substring(0,u)}${i}${_.substring(u)}${u.toString(16)}`})),__publicField(this,"parseStamp",((s,o)=>{if(o&&!/t0|t[1-9]\d{1,}/.test(o))throw new Error("Cannot extract date from a formated UUID with no timestamp in the format");const i=o?o.replace(/\$[rs]\d{0,}|\$t0|\$t[1-9]\d{1,}/g,(s=>{const o={$r:s=>[...Array(s)].map((()=>"r")).join(""),$s:s=>[...Array(s)].map((()=>"s")).join(""),$t:s=>[...Array(s)].map((()=>"t")).join("")},i=s.slice(0,2),a=parseInt(s.slice(2),10);return o[i](a)})).replace(/^(.*?)(t{8,})(.*)$/g,((o,i,a)=>s.substring(i.length,i.length+a.length))):s;if(8===i.length)return new Date(1e3*parseInt(i,16));if(i.length<10)throw new Error("Stamp length invalid");const a=parseInt(i.substring(i.length-1),16);return new Date(1e3*parseInt(i.substring(a,a+8),16))})),__publicField(this,"setCounter",(s=>{this.counter=s})),__publicField(this,"validate",((s,o)=>{const i=o?this._normalizeDictionary(o):this.dict;return s.split("").every((s=>i.includes(s)))}));const o=__spreadValues(__spreadValues({},C),s);this.counter=0,this.debug=!1,this.dict=[],this.version="5.2.0";const{dictionary:i,shuffle:a,length:u,counter:_}=o;return this.uuidLength=u,this.setDictionary(i,a),this.setCounter(_),this.debug=o.debug,this.log(this.dict),this.log(`Generator instantiated with Dictionary Size ${this.dictLength} and counter set to ${this.counter}`),this.log=this.log.bind(this),this.setDictionary=this.setDictionary.bind(this),this.setCounter=this.setCounter.bind(this),this.seq=this.seq.bind(this),this.sequentialUUID=this.sequentialUUID.bind(this),this.rnd=this.rnd.bind(this),this.randomUUID=this.randomUUID.bind(this),this.fmt=this.fmt.bind(this),this.formattedUUID=this.formattedUUID.bind(this),this.availableUUIDs=this.availableUUIDs.bind(this),this.approxMaxBeforeCollision=this.approxMaxBeforeCollision.bind(this),this.collisionProbability=this.collisionProbability.bind(this),this.uniqueness=this.uniqueness.bind(this),this.getVersion=this.getVersion.bind(this),this.stamp=this.stamp.bind(this),this.parseStamp=this.parseStamp.bind(this),this}};__publicField(j,"default",j);var L,B=j;return L=w,((a,_,w,x)=>{if(_&&"object"==typeof _||"function"==typeof _)for(let C of i(_))u.call(a,C)||C===w||s(a,C,{get:()=>_[C],enumerable:!(x=o(_,C))||x.enumerable});return a})(s({},"__esModule",{value:!0}),L)})();s.exports=o.default,"undefined"!=typeof window&&(o=o.default)},9325:(s,o,i)=>{var a=i(34840),u="object"==typeof self&&self&&self.Object===Object&&self,_=a||u||Function("return this")();s.exports=_},9404:function(s){s.exports=function(){"use strict";var s=Array.prototype.slice;function createClass(s,o){o&&(s.prototype=Object.create(o.prototype)),s.prototype.constructor=s}function Iterable(s){return isIterable(s)?s:Seq(s)}function KeyedIterable(s){return isKeyed(s)?s:KeyedSeq(s)}function IndexedIterable(s){return isIndexed(s)?s:IndexedSeq(s)}function SetIterable(s){return isIterable(s)&&!isAssociative(s)?s:SetSeq(s)}function isIterable(s){return!(!s||!s[o])}function isKeyed(s){return!(!s||!s[i])}function isIndexed(s){return!(!s||!s[a])}function isAssociative(s){return isKeyed(s)||isIndexed(s)}function isOrdered(s){return!(!s||!s[u])}createClass(KeyedIterable,Iterable),createClass(IndexedIterable,Iterable),createClass(SetIterable,Iterable),Iterable.isIterable=isIterable,Iterable.isKeyed=isKeyed,Iterable.isIndexed=isIndexed,Iterable.isAssociative=isAssociative,Iterable.isOrdered=isOrdered,Iterable.Keyed=KeyedIterable,Iterable.Indexed=IndexedIterable,Iterable.Set=SetIterable;var o="@@__IMMUTABLE_ITERABLE__@@",i="@@__IMMUTABLE_KEYED__@@",a="@@__IMMUTABLE_INDEXED__@@",u="@@__IMMUTABLE_ORDERED__@@",_="delete",w=5,x=1<>>0;if(""+i!==o||4294967295===i)return NaN;o=i}return o<0?ensureSize(s)+o:o}function returnTrue(){return!0}function wholeSlice(s,o,i){return(0===s||void 0!==i&&s<=-i)&&(void 0===o||void 0!==i&&o>=i)}function resolveBegin(s,o){return resolveIndex(s,o,0)}function resolveEnd(s,o){return resolveIndex(s,o,o)}function resolveIndex(s,o,i){return void 0===s?i:s<0?Math.max(0,o+s):void 0===o?s:Math.min(o,s)}var $=0,V=1,U=2,z="function"==typeof Symbol&&Symbol.iterator,Y="@@iterator",Z=z||Y;function Iterator(s){this.next=s}function iteratorValue(s,o,i,a){var u=0===s?o:1===s?i:[o,i];return a?a.value=u:a={value:u,done:!1},a}function iteratorDone(){return{value:void 0,done:!0}}function hasIterator(s){return!!getIteratorFn(s)}function isIterator(s){return s&&"function"==typeof s.next}function getIterator(s){var o=getIteratorFn(s);return o&&o.call(s)}function getIteratorFn(s){var o=s&&(z&&s[z]||s[Y]);if("function"==typeof o)return o}function isArrayLike(s){return s&&"number"==typeof s.length}function Seq(s){return null==s?emptySequence():isIterable(s)?s.toSeq():seqFromValue(s)}function KeyedSeq(s){return null==s?emptySequence().toKeyedSeq():isIterable(s)?isKeyed(s)?s.toSeq():s.fromEntrySeq():keyedSeqFromValue(s)}function IndexedSeq(s){return null==s?emptySequence():isIterable(s)?isKeyed(s)?s.entrySeq():s.toIndexedSeq():indexedSeqFromValue(s)}function SetSeq(s){return(null==s?emptySequence():isIterable(s)?isKeyed(s)?s.entrySeq():s:indexedSeqFromValue(s)).toSetSeq()}Iterator.prototype.toString=function(){return"[Iterator]"},Iterator.KEYS=$,Iterator.VALUES=V,Iterator.ENTRIES=U,Iterator.prototype.inspect=Iterator.prototype.toSource=function(){return this.toString()},Iterator.prototype[Z]=function(){return this},createClass(Seq,Iterable),Seq.of=function(){return Seq(arguments)},Seq.prototype.toSeq=function(){return this},Seq.prototype.toString=function(){return this.__toString("Seq {","}")},Seq.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},Seq.prototype.__iterate=function(s,o){return seqIterate(this,s,o,!0)},Seq.prototype.__iterator=function(s,o){return seqIterator(this,s,o,!0)},createClass(KeyedSeq,Seq),KeyedSeq.prototype.toKeyedSeq=function(){return this},createClass(IndexedSeq,Seq),IndexedSeq.of=function(){return IndexedSeq(arguments)},IndexedSeq.prototype.toIndexedSeq=function(){return this},IndexedSeq.prototype.toString=function(){return this.__toString("Seq [","]")},IndexedSeq.prototype.__iterate=function(s,o){return seqIterate(this,s,o,!1)},IndexedSeq.prototype.__iterator=function(s,o){return seqIterator(this,s,o,!1)},createClass(SetSeq,Seq),SetSeq.of=function(){return SetSeq(arguments)},SetSeq.prototype.toSetSeq=function(){return this},Seq.isSeq=isSeq,Seq.Keyed=KeyedSeq,Seq.Set=SetSeq,Seq.Indexed=IndexedSeq;var ee,ie,ae,ce="@@__IMMUTABLE_SEQ__@@";function ArraySeq(s){this._array=s,this.size=s.length}function ObjectSeq(s){var o=Object.keys(s);this._object=s,this._keys=o,this.size=o.length}function IterableSeq(s){this._iterable=s,this.size=s.length||s.size}function IteratorSeq(s){this._iterator=s,this._iteratorCache=[]}function isSeq(s){return!(!s||!s[ce])}function emptySequence(){return ee||(ee=new ArraySeq([]))}function keyedSeqFromValue(s){var o=Array.isArray(s)?new ArraySeq(s).fromEntrySeq():isIterator(s)?new IteratorSeq(s).fromEntrySeq():hasIterator(s)?new IterableSeq(s).fromEntrySeq():"object"==typeof s?new ObjectSeq(s):void 0;if(!o)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+s);return o}function indexedSeqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(!o)throw new TypeError("Expected Array or iterable object of values: "+s);return o}function seqFromValue(s){var o=maybeIndexedSeqFromValue(s)||"object"==typeof s&&new ObjectSeq(s);if(!o)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+s);return o}function maybeIndexedSeqFromValue(s){return isArrayLike(s)?new ArraySeq(s):isIterator(s)?new IteratorSeq(s):hasIterator(s)?new IterableSeq(s):void 0}function seqIterate(s,o,i,a){var u=s._cache;if(u){for(var _=u.length-1,w=0;w<=_;w++){var x=u[i?_-w:w];if(!1===o(x[1],a?x[0]:w,s))return w+1}return w}return s.__iterateUncached(o,i)}function seqIterator(s,o,i,a){var u=s._cache;if(u){var _=u.length-1,w=0;return new Iterator((function(){var s=u[i?_-w:w];return w++>_?iteratorDone():iteratorValue(o,a?s[0]:w-1,s[1])}))}return s.__iteratorUncached(o,i)}function fromJS(s,o){return o?fromJSWith(o,s,"",{"":s}):fromJSDefault(s)}function fromJSWith(s,o,i,a){return Array.isArray(o)?s.call(a,i,IndexedSeq(o).map((function(i,a){return fromJSWith(s,i,a,o)}))):isPlainObj(o)?s.call(a,i,KeyedSeq(o).map((function(i,a){return fromJSWith(s,i,a,o)}))):o}function fromJSDefault(s){return Array.isArray(s)?IndexedSeq(s).map(fromJSDefault).toList():isPlainObj(s)?KeyedSeq(s).map(fromJSDefault).toMap():s}function isPlainObj(s){return s&&(s.constructor===Object||void 0===s.constructor)}function is(s,o){if(s===o||s!=s&&o!=o)return!0;if(!s||!o)return!1;if("function"==typeof s.valueOf&&"function"==typeof o.valueOf){if((s=s.valueOf())===(o=o.valueOf())||s!=s&&o!=o)return!0;if(!s||!o)return!1}return!("function"!=typeof s.equals||"function"!=typeof o.equals||!s.equals(o))}function deepEqual(s,o){if(s===o)return!0;if(!isIterable(o)||void 0!==s.size&&void 0!==o.size&&s.size!==o.size||void 0!==s.__hash&&void 0!==o.__hash&&s.__hash!==o.__hash||isKeyed(s)!==isKeyed(o)||isIndexed(s)!==isIndexed(o)||isOrdered(s)!==isOrdered(o))return!1;if(0===s.size&&0===o.size)return!0;var i=!isAssociative(s);if(isOrdered(s)){var a=s.entries();return o.every((function(s,o){var u=a.next().value;return u&&is(u[1],s)&&(i||is(u[0],o))}))&&a.next().done}var u=!1;if(void 0===s.size)if(void 0===o.size)"function"==typeof s.cacheResult&&s.cacheResult();else{u=!0;var _=s;s=o,o=_}var w=!0,x=o.__iterate((function(o,a){if(i?!s.has(o):u?!is(o,s.get(a,j)):!is(s.get(a,j),o))return w=!1,!1}));return w&&s.size===x}function Repeat(s,o){if(!(this instanceof Repeat))return new Repeat(s,o);if(this._value=s,this.size=void 0===o?1/0:Math.max(0,o),0===this.size){if(ie)return ie;ie=this}}function invariant(s,o){if(!s)throw new Error(o)}function Range(s,o,i){if(!(this instanceof Range))return new Range(s,o,i);if(invariant(0!==i,"Cannot step a Range by 0"),s=s||0,void 0===o&&(o=1/0),i=void 0===i?1:Math.abs(i),oa?iteratorDone():iteratorValue(s,u,i[o?a-u++:u++])}))},createClass(ObjectSeq,KeyedSeq),ObjectSeq.prototype.get=function(s,o){return void 0===o||this.has(s)?this._object[s]:o},ObjectSeq.prototype.has=function(s){return this._object.hasOwnProperty(s)},ObjectSeq.prototype.__iterate=function(s,o){for(var i=this._object,a=this._keys,u=a.length-1,_=0;_<=u;_++){var w=a[o?u-_:_];if(!1===s(i[w],w,this))return _+1}return _},ObjectSeq.prototype.__iterator=function(s,o){var i=this._object,a=this._keys,u=a.length-1,_=0;return new Iterator((function(){var w=a[o?u-_:_];return _++>u?iteratorDone():iteratorValue(s,w,i[w])}))},ObjectSeq.prototype[u]=!0,createClass(IterableSeq,IndexedSeq),IterableSeq.prototype.__iterateUncached=function(s,o){if(o)return this.cacheResult().__iterate(s,o);var i=getIterator(this._iterable),a=0;if(isIterator(i))for(var u;!(u=i.next()).done&&!1!==s(u.value,a++,this););return a},IterableSeq.prototype.__iteratorUncached=function(s,o){if(o)return this.cacheResult().__iterator(s,o);var i=getIterator(this._iterable);if(!isIterator(i))return new Iterator(iteratorDone);var a=0;return new Iterator((function(){var o=i.next();return o.done?o:iteratorValue(s,a++,o.value)}))},createClass(IteratorSeq,IndexedSeq),IteratorSeq.prototype.__iterateUncached=function(s,o){if(o)return this.cacheResult().__iterate(s,o);for(var i,a=this._iterator,u=this._iteratorCache,_=0;_=a.length){var o=i.next();if(o.done)return o;a[u]=o.value}return iteratorValue(s,u,a[u++])}))},createClass(Repeat,IndexedSeq),Repeat.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Repeat.prototype.get=function(s,o){return this.has(s)?this._value:o},Repeat.prototype.includes=function(s){return is(this._value,s)},Repeat.prototype.slice=function(s,o){var i=this.size;return wholeSlice(s,o,i)?this:new Repeat(this._value,resolveEnd(o,i)-resolveBegin(s,i))},Repeat.prototype.reverse=function(){return this},Repeat.prototype.indexOf=function(s){return is(this._value,s)?0:-1},Repeat.prototype.lastIndexOf=function(s){return is(this._value,s)?this.size:-1},Repeat.prototype.__iterate=function(s,o){for(var i=0;i=0&&o=0&&ii?iteratorDone():iteratorValue(s,_++,w)}))},Range.prototype.equals=function(s){return s instanceof Range?this._start===s._start&&this._end===s._end&&this._step===s._step:deepEqual(this,s)},createClass(Collection,Iterable),createClass(KeyedCollection,Collection),createClass(IndexedCollection,Collection),createClass(SetCollection,Collection),Collection.Keyed=KeyedCollection,Collection.Indexed=IndexedCollection,Collection.Set=SetCollection;var le="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function imul(s,o){var i=65535&(s|=0),a=65535&(o|=0);return i*a+((s>>>16)*a+i*(o>>>16)<<16>>>0)|0};function smi(s){return s>>>1&1073741824|3221225471&s}function hash(s){if(!1===s||null==s)return 0;if("function"==typeof s.valueOf&&(!1===(s=s.valueOf())||null==s))return 0;if(!0===s)return 1;var o=typeof s;if("number"===o){if(s!=s||s===1/0)return 0;var i=0|s;for(i!==s&&(i^=4294967295*s);s>4294967295;)i^=s/=4294967295;return smi(i)}if("string"===o)return s.length>Se?cachedHashString(s):hashString(s);if("function"==typeof s.hashCode)return s.hashCode();if("object"===o)return hashJSObj(s);if("function"==typeof s.toString)return hashString(s.toString());throw new Error("Value type "+o+" cannot be hashed.")}function cachedHashString(s){var o=Pe[s];return void 0===o&&(o=hashString(s),xe===we&&(xe=0,Pe={}),xe++,Pe[s]=o),o}function hashString(s){for(var o=0,i=0;i0)switch(s.nodeType){case 1:return s.uniqueID;case 9:return s.documentElement&&s.documentElement.uniqueID}}var fe,ye="function"==typeof WeakMap;ye&&(fe=new WeakMap);var be=0,_e="__immutablehash__";"function"==typeof Symbol&&(_e=Symbol(_e));var Se=16,we=255,xe=0,Pe={};function assertNotInfinite(s){invariant(s!==1/0,"Cannot perform this action with an infinite size.")}function Map(s){return null==s?emptyMap():isMap(s)&&!isOrdered(s)?s:emptyMap().withMutations((function(o){var i=KeyedIterable(s);assertNotInfinite(i.size),i.forEach((function(s,i){return o.set(i,s)}))}))}function isMap(s){return!(!s||!s[Re])}createClass(Map,KeyedCollection),Map.of=function(){var o=s.call(arguments,0);return emptyMap().withMutations((function(s){for(var i=0;i=o.length)throw new Error("Missing value for key: "+o[i]);s.set(o[i],o[i+1])}}))},Map.prototype.toString=function(){return this.__toString("Map {","}")},Map.prototype.get=function(s,o){return this._root?this._root.get(0,void 0,s,o):o},Map.prototype.set=function(s,o){return updateMap(this,s,o)},Map.prototype.setIn=function(s,o){return this.updateIn(s,j,(function(){return o}))},Map.prototype.remove=function(s){return updateMap(this,s,j)},Map.prototype.deleteIn=function(s){return this.updateIn(s,(function(){return j}))},Map.prototype.update=function(s,o,i){return 1===arguments.length?s(this):this.updateIn([s],o,i)},Map.prototype.updateIn=function(s,o,i){i||(i=o,o=void 0);var a=updateInDeepMap(this,forceIterator(s),o,i);return a===j?void 0:a},Map.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):emptyMap()},Map.prototype.merge=function(){return mergeIntoMapWith(this,void 0,arguments)},Map.prototype.mergeWith=function(o){return mergeIntoMapWith(this,o,s.call(arguments,1))},Map.prototype.mergeIn=function(o){var i=s.call(arguments,1);return this.updateIn(o,emptyMap(),(function(s){return"function"==typeof s.merge?s.merge.apply(s,i):i[i.length-1]}))},Map.prototype.mergeDeep=function(){return mergeIntoMapWith(this,deepMerger,arguments)},Map.prototype.mergeDeepWith=function(o){var i=s.call(arguments,1);return mergeIntoMapWith(this,deepMergerWith(o),i)},Map.prototype.mergeDeepIn=function(o){var i=s.call(arguments,1);return this.updateIn(o,emptyMap(),(function(s){return"function"==typeof s.mergeDeep?s.mergeDeep.apply(s,i):i[i.length-1]}))},Map.prototype.sort=function(s){return OrderedMap(sortFactory(this,s))},Map.prototype.sortBy=function(s,o){return OrderedMap(sortFactory(this,o,s))},Map.prototype.withMutations=function(s){var o=this.asMutable();return s(o),o.wasAltered()?o.__ensureOwner(this.__ownerID):this},Map.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new OwnerID)},Map.prototype.asImmutable=function(){return this.__ensureOwner()},Map.prototype.wasAltered=function(){return this.__altered},Map.prototype.__iterator=function(s,o){return new MapIterator(this,s,o)},Map.prototype.__iterate=function(s,o){var i=this,a=0;return this._root&&this._root.iterate((function(o){return a++,s(o[1],o[0],i)}),o),a},Map.prototype.__ensureOwner=function(s){return s===this.__ownerID?this:s?makeMap(this.size,this._root,s,this.__hash):(this.__ownerID=s,this.__altered=!1,this)},Map.isMap=isMap;var Te,Re="@@__IMMUTABLE_MAP__@@",qe=Map.prototype;function ArrayMapNode(s,o){this.ownerID=s,this.entries=o}function BitmapIndexedNode(s,o,i){this.ownerID=s,this.bitmap=o,this.nodes=i}function HashArrayMapNode(s,o,i){this.ownerID=s,this.count=o,this.nodes=i}function HashCollisionNode(s,o,i){this.ownerID=s,this.keyHash=o,this.entries=i}function ValueNode(s,o,i){this.ownerID=s,this.keyHash=o,this.entry=i}function MapIterator(s,o,i){this._type=o,this._reverse=i,this._stack=s._root&&mapIteratorFrame(s._root)}function mapIteratorValue(s,o){return iteratorValue(s,o[0],o[1])}function mapIteratorFrame(s,o){return{node:s,index:0,__prev:o}}function makeMap(s,o,i,a){var u=Object.create(qe);return u.size=s,u._root=o,u.__ownerID=i,u.__hash=a,u.__altered=!1,u}function emptyMap(){return Te||(Te=makeMap(0))}function updateMap(s,o,i){var a,u;if(s._root){var _=MakeRef(L),w=MakeRef(B);if(a=updateNode(s._root,s.__ownerID,0,void 0,o,i,_,w),!w.value)return s;u=s.size+(_.value?i===j?-1:1:0)}else{if(i===j)return s;u=1,a=new ArrayMapNode(s.__ownerID,[[o,i]])}return s.__ownerID?(s.size=u,s._root=a,s.__hash=void 0,s.__altered=!0,s):a?makeMap(u,a):emptyMap()}function updateNode(s,o,i,a,u,_,w,x){return s?s.update(o,i,a,u,_,w,x):_===j?s:(SetRef(x),SetRef(w),new ValueNode(o,a,[u,_]))}function isLeafNode(s){return s.constructor===ValueNode||s.constructor===HashCollisionNode}function mergeIntoNode(s,o,i,a,u){if(s.keyHash===a)return new HashCollisionNode(o,a,[s.entry,u]);var _,x=(0===i?s.keyHash:s.keyHash>>>i)&C,j=(0===i?a:a>>>i)&C;return new BitmapIndexedNode(o,1<>>=1)w[C]=1&i?o[_++]:void 0;return w[a]=u,new HashArrayMapNode(s,_+1,w)}function mergeIntoMapWith(s,o,i){for(var a=[],u=0;u>1&1431655765))+(s>>2&858993459))+(s>>4)&252645135,s+=s>>8,127&(s+=s>>16)}function setIn(s,o,i,a){var u=a?s:arrCopy(s);return u[o]=i,u}function spliceIn(s,o,i,a){var u=s.length+1;if(a&&o+1===u)return s[o]=i,s;for(var _=new Array(u),w=0,x=0;x=$e)return createNodes(s,C,a,u);var V=s&&s===this.ownerID,U=V?C:arrCopy(C);return $?x?L===B-1?U.pop():U[L]=U.pop():U[L]=[a,u]:U.push([a,u]),V?(this.entries=U,this):new ArrayMapNode(s,U)}},BitmapIndexedNode.prototype.get=function(s,o,i,a){void 0===o&&(o=hash(i));var u=1<<((0===s?o:o>>>s)&C),_=this.bitmap;return _&u?this.nodes[popCount(_&u-1)].get(s+w,o,i,a):a},BitmapIndexedNode.prototype.update=function(s,o,i,a,u,_,x){void 0===i&&(i=hash(a));var L=(0===o?i:i>>>o)&C,B=1<=ze)return expandNodes(s,z,$,L,Z);if(V&&!Z&&2===z.length&&isLeafNode(z[1^U]))return z[1^U];if(V&&Z&&1===z.length&&isLeafNode(Z))return Z;var ee=s&&s===this.ownerID,ie=V?Z?$:$^B:$|B,ae=V?Z?setIn(z,U,Z,ee):spliceOut(z,U,ee):spliceIn(z,U,Z,ee);return ee?(this.bitmap=ie,this.nodes=ae,this):new BitmapIndexedNode(s,ie,ae)},HashArrayMapNode.prototype.get=function(s,o,i,a){void 0===o&&(o=hash(i));var u=(0===s?o:o>>>s)&C,_=this.nodes[u];return _?_.get(s+w,o,i,a):a},HashArrayMapNode.prototype.update=function(s,o,i,a,u,_,x){void 0===i&&(i=hash(a));var L=(0===o?i:i>>>o)&C,B=u===j,$=this.nodes,V=$[L];if(B&&!V)return this;var U=updateNode(V,s,o+w,i,a,u,_,x);if(U===V)return this;var z=this.count;if(V){if(!U&&--z0&&a=0&&s>>o&C;if(a>=this.array.length)return new VNode([],s);var u,_=0===a;if(o>0){var x=this.array[a];if((u=x&&x.removeBefore(s,o-w,i))===x&&_)return this}if(_&&!u)return this;var j=editableVNode(this,s);if(!_)for(var L=0;L>>o&C;if(u>=this.array.length)return this;if(o>0){var _=this.array[u];if((a=_&&_.removeAfter(s,o-w,i))===_&&u===this.array.length-1)return this}var x=editableVNode(this,s);return x.array.splice(u+1),a&&(x.array[u]=a),x};var Ye,Qe,et={};function iterateList(s,o){var i=s._origin,a=s._capacity,u=getTailOffset(a),_=s._tail;return iterateNodeOrLeaf(s._root,s._level,0);function iterateNodeOrLeaf(s,o,i){return 0===o?iterateLeaf(s,i):iterateNode(s,o,i)}function iterateLeaf(s,w){var C=w===u?_&&_.array:s&&s.array,j=w>i?0:i-w,L=a-w;return L>x&&(L=x),function(){if(j===L)return et;var s=o?--L:j++;return C&&C[s]}}function iterateNode(s,u,_){var C,j=s&&s.array,L=_>i?0:i-_>>u,B=1+(a-_>>u);return B>x&&(B=x),function(){for(;;){if(C){var s=C();if(s!==et)return s;C=null}if(L===B)return et;var i=o?--B:L++;C=iterateNodeOrLeaf(j&&j[i],u-w,_+(i<=s.size||o<0)return s.withMutations((function(s){o<0?setListBounds(s,o).set(0,i):setListBounds(s,0,o+1).set(o,i)}));o+=s._origin;var a=s._tail,u=s._root,_=MakeRef(B);return o>=getTailOffset(s._capacity)?a=updateVNode(a,s.__ownerID,0,o,i,_):u=updateVNode(u,s.__ownerID,s._level,o,i,_),_.value?s.__ownerID?(s._root=u,s._tail=a,s.__hash=void 0,s.__altered=!0,s):makeList(s._origin,s._capacity,s._level,u,a):s}function updateVNode(s,o,i,a,u,_){var x,j=a>>>i&C,L=s&&j0){var B=s&&s.array[j],$=updateVNode(B,o,i-w,a,u,_);return $===B?s:((x=editableVNode(s,o)).array[j]=$,x)}return L&&s.array[j]===u?s:(SetRef(_),x=editableVNode(s,o),void 0===u&&j===x.array.length-1?x.array.pop():x.array[j]=u,x)}function editableVNode(s,o){return o&&s&&o===s.ownerID?s:new VNode(s?s.array.slice():[],o)}function listNodeFor(s,o){if(o>=getTailOffset(s._capacity))return s._tail;if(o<1<0;)i=i.array[o>>>a&C],a-=w;return i}}function setListBounds(s,o,i){void 0!==o&&(o|=0),void 0!==i&&(i|=0);var a=s.__ownerID||new OwnerID,u=s._origin,_=s._capacity,x=u+o,j=void 0===i?_:i<0?_+i:u+i;if(x===u&&j===_)return s;if(x>=j)return s.clear();for(var L=s._level,B=s._root,$=0;x+$<0;)B=new VNode(B&&B.array.length?[void 0,B]:[],a),$+=1<<(L+=w);$&&(x+=$,u+=$,j+=$,_+=$);for(var V=getTailOffset(_),U=getTailOffset(j);U>=1<V?new VNode([],a):z;if(z&&U>V&&x<_&&z.array.length){for(var Z=B=editableVNode(B,a),ee=L;ee>w;ee-=w){var ie=V>>>ee&C;Z=Z.array[ie]=editableVNode(Z.array[ie],a)}Z.array[V>>>w&C]=z}if(j<_&&(Y=Y&&Y.removeAfter(a,0,j)),x>=U)x-=U,j-=U,L=w,B=null,Y=Y&&Y.removeBefore(a,0,x);else if(x>u||U>>L&C;if(ae!==U>>>L&C)break;ae&&($+=(1<u&&(B=B.removeBefore(a,L,x-$)),B&&Uu&&(u=x.size),isIterable(w)||(x=x.map((function(s){return fromJS(s)}))),a.push(x)}return u>s.size&&(s=s.setSize(u)),mergeIntoCollectionWith(s,o,a)}function getTailOffset(s){return s>>w<=x&&w.size>=2*_.size?(a=(u=w.filter((function(s,o){return void 0!==s&&C!==o}))).toKeyedSeq().map((function(s){return s[0]})).flip().toMap(),s.__ownerID&&(a.__ownerID=u.__ownerID=s.__ownerID)):(a=_.remove(o),u=C===w.size-1?w.pop():w.set(C,void 0))}else if(L){if(i===w.get(C)[1])return s;a=_,u=w.set(C,[o,i])}else a=_.set(o,w.size),u=w.set(w.size,[o,i]);return s.__ownerID?(s.size=a.size,s._map=a,s._list=u,s.__hash=void 0,s):makeOrderedMap(a,u)}function ToKeyedSequence(s,o){this._iter=s,this._useKeys=o,this.size=s.size}function ToIndexedSequence(s){this._iter=s,this.size=s.size}function ToSetSequence(s){this._iter=s,this.size=s.size}function FromEntriesSequence(s){this._iter=s,this.size=s.size}function flipFactory(s){var o=makeSequence(s);return o._iter=s,o.size=s.size,o.flip=function(){return s},o.reverse=function(){var o=s.reverse.apply(this);return o.flip=function(){return s.reverse()},o},o.has=function(o){return s.includes(o)},o.includes=function(o){return s.has(o)},o.cacheResult=cacheResultThrough,o.__iterateUncached=function(o,i){var a=this;return s.__iterate((function(s,i){return!1!==o(i,s,a)}),i)},o.__iteratorUncached=function(o,i){if(o===U){var a=s.__iterator(o,i);return new Iterator((function(){var s=a.next();if(!s.done){var o=s.value[0];s.value[0]=s.value[1],s.value[1]=o}return s}))}return s.__iterator(o===V?$:V,i)},o}function mapFactory(s,o,i){var a=makeSequence(s);return a.size=s.size,a.has=function(o){return s.has(o)},a.get=function(a,u){var _=s.get(a,j);return _===j?u:o.call(i,_,a,s)},a.__iterateUncached=function(a,u){var _=this;return s.__iterate((function(s,u,w){return!1!==a(o.call(i,s,u,w),u,_)}),u)},a.__iteratorUncached=function(a,u){var _=s.__iterator(U,u);return new Iterator((function(){var u=_.next();if(u.done)return u;var w=u.value,x=w[0];return iteratorValue(a,x,o.call(i,w[1],x,s),u)}))},a}function reverseFactory(s,o){var i=makeSequence(s);return i._iter=s,i.size=s.size,i.reverse=function(){return s},s.flip&&(i.flip=function(){var o=flipFactory(s);return o.reverse=function(){return s.flip()},o}),i.get=function(i,a){return s.get(o?i:-1-i,a)},i.has=function(i){return s.has(o?i:-1-i)},i.includes=function(o){return s.includes(o)},i.cacheResult=cacheResultThrough,i.__iterate=function(o,i){var a=this;return s.__iterate((function(s,i){return o(s,i,a)}),!i)},i.__iterator=function(o,i){return s.__iterator(o,!i)},i}function filterFactory(s,o,i,a){var u=makeSequence(s);return a&&(u.has=function(a){var u=s.get(a,j);return u!==j&&!!o.call(i,u,a,s)},u.get=function(a,u){var _=s.get(a,j);return _!==j&&o.call(i,_,a,s)?_:u}),u.__iterateUncached=function(u,_){var w=this,x=0;return s.__iterate((function(s,_,C){if(o.call(i,s,_,C))return x++,u(s,a?_:x-1,w)}),_),x},u.__iteratorUncached=function(u,_){var w=s.__iterator(U,_),x=0;return new Iterator((function(){for(;;){var _=w.next();if(_.done)return _;var C=_.value,j=C[0],L=C[1];if(o.call(i,L,j,s))return iteratorValue(u,a?j:x++,L,_)}}))},u}function countByFactory(s,o,i){var a=Map().asMutable();return s.__iterate((function(u,_){a.update(o.call(i,u,_,s),0,(function(s){return s+1}))})),a.asImmutable()}function groupByFactory(s,o,i){var a=isKeyed(s),u=(isOrdered(s)?OrderedMap():Map()).asMutable();s.__iterate((function(_,w){u.update(o.call(i,_,w,s),(function(s){return(s=s||[]).push(a?[w,_]:_),s}))}));var _=iterableClass(s);return u.map((function(o){return reify(s,_(o))}))}function sliceFactory(s,o,i,a){var u=s.size;if(void 0!==o&&(o|=0),void 0!==i&&(i===1/0?i=u:i|=0),wholeSlice(o,i,u))return s;var _=resolveBegin(o,u),w=resolveEnd(i,u);if(_!=_||w!=w)return sliceFactory(s.toSeq().cacheResult(),o,i,a);var x,C=w-_;C==C&&(x=C<0?0:C);var j=makeSequence(s);return j.size=0===x?x:s.size&&x||void 0,!a&&isSeq(s)&&x>=0&&(j.get=function(o,i){return(o=wrapIndex(this,o))>=0&&ox)return iteratorDone();var s=u.next();return a||o===V?s:iteratorValue(o,C-1,o===$?void 0:s.value[1],s)}))},j}function takeWhileFactory(s,o,i){var a=makeSequence(s);return a.__iterateUncached=function(a,u){var _=this;if(u)return this.cacheResult().__iterate(a,u);var w=0;return s.__iterate((function(s,u,x){return o.call(i,s,u,x)&&++w&&a(s,u,_)})),w},a.__iteratorUncached=function(a,u){var _=this;if(u)return this.cacheResult().__iterator(a,u);var w=s.__iterator(U,u),x=!0;return new Iterator((function(){if(!x)return iteratorDone();var s=w.next();if(s.done)return s;var u=s.value,C=u[0],j=u[1];return o.call(i,j,C,_)?a===U?s:iteratorValue(a,C,j,s):(x=!1,iteratorDone())}))},a}function skipWhileFactory(s,o,i,a){var u=makeSequence(s);return u.__iterateUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterate(u,_);var x=!0,C=0;return s.__iterate((function(s,_,j){if(!x||!(x=o.call(i,s,_,j)))return C++,u(s,a?_:C-1,w)})),C},u.__iteratorUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterator(u,_);var x=s.__iterator(U,_),C=!0,j=0;return new Iterator((function(){var s,_,L;do{if((s=x.next()).done)return a||u===V?s:iteratorValue(u,j++,u===$?void 0:s.value[1],s);var B=s.value;_=B[0],L=B[1],C&&(C=o.call(i,L,_,w))}while(C);return u===U?s:iteratorValue(u,_,L,s)}))},u}function concatFactory(s,o){var i=isKeyed(s),a=[s].concat(o).map((function(s){return isIterable(s)?i&&(s=KeyedIterable(s)):s=i?keyedSeqFromValue(s):indexedSeqFromValue(Array.isArray(s)?s:[s]),s})).filter((function(s){return 0!==s.size}));if(0===a.length)return s;if(1===a.length){var u=a[0];if(u===s||i&&isKeyed(u)||isIndexed(s)&&isIndexed(u))return u}var _=new ArraySeq(a);return i?_=_.toKeyedSeq():isIndexed(s)||(_=_.toSetSeq()),(_=_.flatten(!0)).size=a.reduce((function(s,o){if(void 0!==s){var i=o.size;if(void 0!==i)return s+i}}),0),_}function flattenFactory(s,o,i){var a=makeSequence(s);return a.__iterateUncached=function(a,u){var _=0,w=!1;function flatDeep(s,x){var C=this;s.__iterate((function(s,u){return(!o||x0}function zipWithFactory(s,o,i){var a=makeSequence(s);return a.size=new ArraySeq(i).map((function(s){return s.size})).min(),a.__iterate=function(s,o){for(var i,a=this.__iterator(V,o),u=0;!(i=a.next()).done&&!1!==s(i.value,u++,this););return u},a.__iteratorUncached=function(s,a){var u=i.map((function(s){return s=Iterable(s),getIterator(a?s.reverse():s)})),_=0,w=!1;return new Iterator((function(){var i;return w||(i=u.map((function(s){return s.next()})),w=i.some((function(s){return s.done}))),w?iteratorDone():iteratorValue(s,_++,o.apply(null,i.map((function(s){return s.value}))))}))},a}function reify(s,o){return isSeq(s)?o:s.constructor(o)}function validateEntry(s){if(s!==Object(s))throw new TypeError("Expected [K, V] tuple: "+s)}function resolveSize(s){return assertNotInfinite(s.size),ensureSize(s)}function iterableClass(s){return isKeyed(s)?KeyedIterable:isIndexed(s)?IndexedIterable:SetIterable}function makeSequence(s){return Object.create((isKeyed(s)?KeyedSeq:isIndexed(s)?IndexedSeq:SetSeq).prototype)}function cacheResultThrough(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):Seq.prototype.cacheResult.call(this)}function defaultComparator(s,o){return s>o?1:s=0;i--)o={value:arguments[i],next:o};return this.__ownerID?(this.size=s,this._head=o,this.__hash=void 0,this.__altered=!0,this):makeStack(s,o)},Stack.prototype.pushAll=function(s){if(0===(s=IndexedIterable(s)).size)return this;assertNotInfinite(s.size);var o=this.size,i=this._head;return s.reverse().forEach((function(s){o++,i={value:s,next:i}})),this.__ownerID?(this.size=o,this._head=i,this.__hash=void 0,this.__altered=!0,this):makeStack(o,i)},Stack.prototype.pop=function(){return this.slice(1)},Stack.prototype.unshift=function(){return this.push.apply(this,arguments)},Stack.prototype.unshiftAll=function(s){return this.pushAll(s)},Stack.prototype.shift=function(){return this.pop.apply(this,arguments)},Stack.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):emptyStack()},Stack.prototype.slice=function(s,o){if(wholeSlice(s,o,this.size))return this;var i=resolveBegin(s,this.size);if(resolveEnd(o,this.size)!==this.size)return IndexedCollection.prototype.slice.call(this,s,o);for(var a=this.size-i,u=this._head;i--;)u=u.next;return this.__ownerID?(this.size=a,this._head=u,this.__hash=void 0,this.__altered=!0,this):makeStack(a,u)},Stack.prototype.__ensureOwner=function(s){return s===this.__ownerID?this:s?makeStack(this.size,this._head,s,this.__hash):(this.__ownerID=s,this.__altered=!1,this)},Stack.prototype.__iterate=function(s,o){if(o)return this.reverse().__iterate(s);for(var i=0,a=this._head;a&&!1!==s(a.value,i++,this);)a=a.next;return i},Stack.prototype.__iterator=function(s,o){if(o)return this.reverse().__iterator(s);var i=0,a=this._head;return new Iterator((function(){if(a){var o=a.value;return a=a.next,iteratorValue(s,i++,o)}return iteratorDone()}))},Stack.isStack=isStack;var at,ct="@@__IMMUTABLE_STACK__@@",lt=Stack.prototype;function makeStack(s,o,i,a){var u=Object.create(lt);return u.size=s,u._head=o,u.__ownerID=i,u.__hash=a,u.__altered=!1,u}function emptyStack(){return at||(at=makeStack(0))}function mixin(s,o){var keyCopier=function(i){s.prototype[i]=o[i]};return Object.keys(o).forEach(keyCopier),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(o).forEach(keyCopier),s}lt[ct]=!0,lt.withMutations=qe.withMutations,lt.asMutable=qe.asMutable,lt.asImmutable=qe.asImmutable,lt.wasAltered=qe.wasAltered,Iterable.Iterator=Iterator,mixin(Iterable,{toArray:function(){assertNotInfinite(this.size);var s=new Array(this.size||0);return this.valueSeq().__iterate((function(o,i){s[i]=o})),s},toIndexedSeq:function(){return new ToIndexedSequence(this)},toJS:function(){return this.toSeq().map((function(s){return s&&"function"==typeof s.toJS?s.toJS():s})).__toJS()},toJSON:function(){return this.toSeq().map((function(s){return s&&"function"==typeof s.toJSON?s.toJSON():s})).__toJS()},toKeyedSeq:function(){return new ToKeyedSequence(this,!0)},toMap:function(){return Map(this.toKeyedSeq())},toObject:function(){assertNotInfinite(this.size);var s={};return this.__iterate((function(o,i){s[i]=o})),s},toOrderedMap:function(){return OrderedMap(this.toKeyedSeq())},toOrderedSet:function(){return OrderedSet(isKeyed(this)?this.valueSeq():this)},toSet:function(){return Set(isKeyed(this)?this.valueSeq():this)},toSetSeq:function(){return new ToSetSequence(this)},toSeq:function(){return isIndexed(this)?this.toIndexedSeq():isKeyed(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Stack(isKeyed(this)?this.valueSeq():this)},toList:function(){return List(isKeyed(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(s,o){return 0===this.size?s+o:s+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+o},concat:function(){return reify(this,concatFactory(this,s.call(arguments,0)))},includes:function(s){return this.some((function(o){return is(o,s)}))},entries:function(){return this.__iterator(U)},every:function(s,o){assertNotInfinite(this.size);var i=!0;return this.__iterate((function(a,u,_){if(!s.call(o,a,u,_))return i=!1,!1})),i},filter:function(s,o){return reify(this,filterFactory(this,s,o,!0))},find:function(s,o,i){var a=this.findEntry(s,o);return a?a[1]:i},forEach:function(s,o){return assertNotInfinite(this.size),this.__iterate(o?s.bind(o):s)},join:function(s){assertNotInfinite(this.size),s=void 0!==s?""+s:",";var o="",i=!0;return this.__iterate((function(a){i?i=!1:o+=s,o+=null!=a?a.toString():""})),o},keys:function(){return this.__iterator($)},map:function(s,o){return reify(this,mapFactory(this,s,o))},reduce:function(s,o,i){var a,u;return assertNotInfinite(this.size),arguments.length<2?u=!0:a=o,this.__iterate((function(o,_,w){u?(u=!1,a=o):a=s.call(i,a,o,_,w)})),a},reduceRight:function(s,o,i){var a=this.toKeyedSeq().reverse();return a.reduce.apply(a,arguments)},reverse:function(){return reify(this,reverseFactory(this,!0))},slice:function(s,o){return reify(this,sliceFactory(this,s,o,!0))},some:function(s,o){return!this.every(not(s),o)},sort:function(s){return reify(this,sortFactory(this,s))},values:function(){return this.__iterator(V)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(s,o){return ensureSize(s?this.toSeq().filter(s,o):this)},countBy:function(s,o){return countByFactory(this,s,o)},equals:function(s){return deepEqual(this,s)},entrySeq:function(){var s=this;if(s._cache)return new ArraySeq(s._cache);var o=s.toSeq().map(entryMapper).toIndexedSeq();return o.fromEntrySeq=function(){return s.toSeq()},o},filterNot:function(s,o){return this.filter(not(s),o)},findEntry:function(s,o,i){var a=i;return this.__iterate((function(i,u,_){if(s.call(o,i,u,_))return a=[u,i],!1})),a},findKey:function(s,o){var i=this.findEntry(s,o);return i&&i[0]},findLast:function(s,o,i){return this.toKeyedSeq().reverse().find(s,o,i)},findLastEntry:function(s,o,i){return this.toKeyedSeq().reverse().findEntry(s,o,i)},findLastKey:function(s,o){return this.toKeyedSeq().reverse().findKey(s,o)},first:function(){return this.find(returnTrue)},flatMap:function(s,o){return reify(this,flatMapFactory(this,s,o))},flatten:function(s){return reify(this,flattenFactory(this,s,!0))},fromEntrySeq:function(){return new FromEntriesSequence(this)},get:function(s,o){return this.find((function(o,i){return is(i,s)}),void 0,o)},getIn:function(s,o){for(var i,a=this,u=forceIterator(s);!(i=u.next()).done;){var _=i.value;if((a=a&&a.get?a.get(_,j):j)===j)return o}return a},groupBy:function(s,o){return groupByFactory(this,s,o)},has:function(s){return this.get(s,j)!==j},hasIn:function(s){return this.getIn(s,j)!==j},isSubset:function(s){return s="function"==typeof s.includes?s:Iterable(s),this.every((function(o){return s.includes(o)}))},isSuperset:function(s){return(s="function"==typeof s.isSubset?s:Iterable(s)).isSubset(this)},keyOf:function(s){return this.findKey((function(o){return is(o,s)}))},keySeq:function(){return this.toSeq().map(keyMapper).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(s){return this.toKeyedSeq().reverse().keyOf(s)},max:function(s){return maxFactory(this,s)},maxBy:function(s,o){return maxFactory(this,o,s)},min:function(s){return maxFactory(this,s?neg(s):defaultNegComparator)},minBy:function(s,o){return maxFactory(this,o?neg(o):defaultNegComparator,s)},rest:function(){return this.slice(1)},skip:function(s){return this.slice(Math.max(0,s))},skipLast:function(s){return reify(this,this.toSeq().reverse().skip(s).reverse())},skipWhile:function(s,o){return reify(this,skipWhileFactory(this,s,o,!0))},skipUntil:function(s,o){return this.skipWhile(not(s),o)},sortBy:function(s,o){return reify(this,sortFactory(this,o,s))},take:function(s){return this.slice(0,Math.max(0,s))},takeLast:function(s){return reify(this,this.toSeq().reverse().take(s).reverse())},takeWhile:function(s,o){return reify(this,takeWhileFactory(this,s,o))},takeUntil:function(s,o){return this.takeWhile(not(s),o)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=hashIterable(this))}});var ut=Iterable.prototype;ut[o]=!0,ut[Z]=ut.values,ut.__toJS=ut.toArray,ut.__toStringMapper=quoteString,ut.inspect=ut.toSource=function(){return this.toString()},ut.chain=ut.flatMap,ut.contains=ut.includes,mixin(KeyedIterable,{flip:function(){return reify(this,flipFactory(this))},mapEntries:function(s,o){var i=this,a=0;return reify(this,this.toSeq().map((function(u,_){return s.call(o,[_,u],a++,i)})).fromEntrySeq())},mapKeys:function(s,o){var i=this;return reify(this,this.toSeq().flip().map((function(a,u){return s.call(o,a,u,i)})).flip())}});var pt=KeyedIterable.prototype;function keyMapper(s,o){return o}function entryMapper(s,o){return[o,s]}function not(s){return function(){return!s.apply(this,arguments)}}function neg(s){return function(){return-s.apply(this,arguments)}}function quoteString(s){return"string"==typeof s?JSON.stringify(s):String(s)}function defaultZipper(){return arrCopy(arguments)}function defaultNegComparator(s,o){return so?-1:0}function hashIterable(s){if(s.size===1/0)return 0;var o=isOrdered(s),i=isKeyed(s),a=o?1:0;return murmurHashOfSize(s.__iterate(i?o?function(s,o){a=31*a+hashMerge(hash(s),hash(o))|0}:function(s,o){a=a+hashMerge(hash(s),hash(o))|0}:o?function(s){a=31*a+hash(s)|0}:function(s){a=a+hash(s)|0}),a)}function murmurHashOfSize(s,o){return o=le(o,3432918353),o=le(o<<15|o>>>-15,461845907),o=le(o<<13|o>>>-13,5),o=le((o=o+3864292196^s)^o>>>16,2246822507),o=smi((o=le(o^o>>>13,3266489909))^o>>>16)}function hashMerge(s,o){return s^o+2654435769+(s<<6)+(s>>2)}return pt[i]=!0,pt[Z]=ut.entries,pt.__toJS=ut.toObject,pt.__toStringMapper=function(s,o){return JSON.stringify(o)+": "+quoteString(s)},mixin(IndexedIterable,{toKeyedSeq:function(){return new ToKeyedSequence(this,!1)},filter:function(s,o){return reify(this,filterFactory(this,s,o,!1))},findIndex:function(s,o){var i=this.findEntry(s,o);return i?i[0]:-1},indexOf:function(s){var o=this.keyOf(s);return void 0===o?-1:o},lastIndexOf:function(s){var o=this.lastKeyOf(s);return void 0===o?-1:o},reverse:function(){return reify(this,reverseFactory(this,!1))},slice:function(s,o){return reify(this,sliceFactory(this,s,o,!1))},splice:function(s,o){var i=arguments.length;if(o=Math.max(0|o,0),0===i||2===i&&!o)return this;s=resolveBegin(s,s<0?this.count():this.size);var a=this.slice(0,s);return reify(this,1===i?a:a.concat(arrCopy(arguments,2),this.slice(s+o)))},findLastIndex:function(s,o){var i=this.findLastEntry(s,o);return i?i[0]:-1},first:function(){return this.get(0)},flatten:function(s){return reify(this,flattenFactory(this,s,!1))},get:function(s,o){return(s=wrapIndex(this,s))<0||this.size===1/0||void 0!==this.size&&s>this.size?o:this.find((function(o,i){return i===s}),void 0,o)},has:function(s){return(s=wrapIndex(this,s))>=0&&(void 0!==this.size?this.size===1/0||s{"use strict";i(71340);var a=i(92046);s.exports=a.Object.assign},9999:(s,o,i)=>{var a=i(37217),u=i(83729),_=i(16547),w=i(74733),x=i(43838),C=i(93290),j=i(23007),L=i(92271),B=i(48948),$=i(50002),V=i(83349),U=i(5861),z=i(76189),Y=i(77199),Z=i(35529),ee=i(56449),ie=i(3656),ae=i(87730),ce=i(23805),le=i(38440),pe=i(95950),de=i(37241),fe="[object Arguments]",ye="[object Function]",be="[object Object]",_e={};_e[fe]=_e["[object Array]"]=_e["[object ArrayBuffer]"]=_e["[object DataView]"]=_e["[object Boolean]"]=_e["[object Date]"]=_e["[object Float32Array]"]=_e["[object Float64Array]"]=_e["[object Int8Array]"]=_e["[object Int16Array]"]=_e["[object Int32Array]"]=_e["[object Map]"]=_e["[object Number]"]=_e[be]=_e["[object RegExp]"]=_e["[object Set]"]=_e["[object String]"]=_e["[object Symbol]"]=_e["[object Uint8Array]"]=_e["[object Uint8ClampedArray]"]=_e["[object Uint16Array]"]=_e["[object Uint32Array]"]=!0,_e["[object Error]"]=_e[ye]=_e["[object WeakMap]"]=!1,s.exports=function baseClone(s,o,i,Se,we,xe){var Pe,Te=1&o,Re=2&o,qe=4&o;if(i&&(Pe=we?i(s,Se,we,xe):i(s)),void 0!==Pe)return Pe;if(!ce(s))return s;var $e=ee(s);if($e){if(Pe=z(s),!Te)return j(s,Pe)}else{var ze=U(s),We=ze==ye||"[object GeneratorFunction]"==ze;if(ie(s))return C(s,Te);if(ze==be||ze==fe||We&&!we){if(Pe=Re||We?{}:Z(s),!Te)return Re?B(s,x(Pe,s)):L(s,w(Pe,s))}else{if(!_e[ze])return we?s:{};Pe=Y(s,ze,Te)}}xe||(xe=new a);var He=xe.get(s);if(He)return He;xe.set(s,Pe),le(s)?s.forEach((function(a){Pe.add(baseClone(a,o,i,a,s,xe))})):ae(s)&&s.forEach((function(a,u){Pe.set(u,baseClone(a,o,i,u,s,xe))}));var Xe=$e?void 0:(qe?Re?V:$:Re?de:pe)(s);return u(Xe||s,(function(a,u){Xe&&(a=s[u=a]),_(Pe,u,baseClone(a,o,i,u,s,xe))})),Pe}},10023:(s,o,i)=>{const a=i(6205),INTS=()=>[{type:a.RANGE,from:48,to:57}],WORDS=()=>[{type:a.CHAR,value:95},{type:a.RANGE,from:97,to:122},{type:a.RANGE,from:65,to:90}].concat(INTS()),WHITESPACE=()=>[{type:a.CHAR,value:9},{type:a.CHAR,value:10},{type:a.CHAR,value:11},{type:a.CHAR,value:12},{type:a.CHAR,value:13},{type:a.CHAR,value:32},{type:a.CHAR,value:160},{type:a.CHAR,value:5760},{type:a.RANGE,from:8192,to:8202},{type:a.CHAR,value:8232},{type:a.CHAR,value:8233},{type:a.CHAR,value:8239},{type:a.CHAR,value:8287},{type:a.CHAR,value:12288},{type:a.CHAR,value:65279}];o.words=()=>({type:a.SET,set:WORDS(),not:!1}),o.notWords=()=>({type:a.SET,set:WORDS(),not:!0}),o.ints=()=>({type:a.SET,set:INTS(),not:!1}),o.notInts=()=>({type:a.SET,set:INTS(),not:!0}),o.whitespace=()=>({type:a.SET,set:WHITESPACE(),not:!1}),o.notWhitespace=()=>({type:a.SET,set:WHITESPACE(),not:!0}),o.anyChar=()=>({type:a.SET,set:[{type:a.CHAR,value:10},{type:a.CHAR,value:13},{type:a.CHAR,value:8232},{type:a.CHAR,value:8233}],not:!0})},10043:(s,o,i)=>{"use strict";var a=i(54018),u=String,_=TypeError;s.exports=function(s){if(a(s))return s;throw new _("Can't set "+u(s)+" as a prototype")}},10124:(s,o,i)=>{var a=i(9325);s.exports=function(){return a.Date.now()}},10300:(s,o,i)=>{"use strict";var a=i(13930),u=i(82159),_=i(36624),w=i(4640),x=i(73448),C=TypeError;s.exports=function(s,o){var i=arguments.length<2?x(s):o;if(u(i))return _(a(i,s));throw new C(w(s)+" is not iterable")}},10316:(s,o,i)=>{const a=i(2404),u=i(55973),_=i(92340);class Element{constructor(s,o,i){o&&(this.meta=o),i&&(this.attributes=i),this.content=s}freeze(){Object.isFrozen(this)||(this._meta&&(this.meta.parent=this,this.meta.freeze()),this._attributes&&(this.attributes.parent=this,this.attributes.freeze()),this.children.forEach((s=>{s.parent=this,s.freeze()}),this),this.content&&Array.isArray(this.content)&&Object.freeze(this.content),Object.freeze(this))}primitive(){}clone(){const s=new this.constructor;return s.element=this.element,this.meta.length&&(s._meta=this.meta.clone()),this.attributes.length&&(s._attributes=this.attributes.clone()),this.content?this.content.clone?s.content=this.content.clone():Array.isArray(this.content)?s.content=this.content.map((s=>s.clone())):s.content=this.content:s.content=this.content,s}toValue(){return this.content instanceof Element?this.content.toValue():this.content instanceof u?{key:this.content.key.toValue(),value:this.content.value?this.content.value.toValue():void 0}:this.content&&this.content.map?this.content.map((s=>s.toValue()),this):this.content}toRef(s){if(""===this.id.toValue())throw Error("Cannot create reference to an element that does not contain an ID");const o=new this.RefElement(this.id.toValue());return s&&(o.path=s),o}findRecursive(...s){if(arguments.length>1&&!this.isFrozen)throw new Error("Cannot find recursive with multiple element names without first freezing the element. Call `element.freeze()`");const o=s.pop();let i=new _;const append=(s,o)=>(s.push(o),s),checkElement=(s,i)=>{i.element===o&&s.push(i);const a=i.findRecursive(o);return a&&a.reduce(append,s),i.content instanceof u&&(i.content.key&&checkElement(s,i.content.key),i.content.value&&checkElement(s,i.content.value)),s};return this.content&&(this.content.element&&checkElement(i,this.content),Array.isArray(this.content)&&this.content.reduce(checkElement,i)),s.isEmpty||(i=i.filter((o=>{let i=o.parents.map((s=>s.element));for(const o in s){const a=s[o],u=i.indexOf(a);if(-1===u)return!1;i=i.splice(0,u)}return!0}))),i}set(s){return this.content=s,this}equals(s){return a(this.toValue(),s)}getMetaProperty(s,o){if(!this.meta.hasKey(s)){if(this.isFrozen){const s=this.refract(o);return s.freeze(),s}this.meta.set(s,o)}return this.meta.get(s)}setMetaProperty(s,o){this.meta.set(s,o)}get element(){return this._storedElement||"element"}set element(s){this._storedElement=s}get content(){return this._content}set content(s){if(s instanceof Element)this._content=s;else if(s instanceof _)this.content=s.elements;else if("string"==typeof s||"number"==typeof s||"boolean"==typeof s||"null"===s||null==s)this._content=s;else if(s instanceof u)this._content=s;else if(Array.isArray(s))this._content=s.map(this.refract);else{if("object"!=typeof s)throw new Error("Cannot set content to given value");this._content=Object.keys(s).map((o=>new this.MemberElement(o,s[o])))}}get meta(){if(!this._meta){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._meta=new this.ObjectElement}return this._meta}set meta(s){s instanceof this.ObjectElement?this._meta=s:this.meta.set(s||{})}get attributes(){if(!this._attributes){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._attributes=new this.ObjectElement}return this._attributes}set attributes(s){s instanceof this.ObjectElement?this._attributes=s:this.attributes.set(s||{})}get id(){return this.getMetaProperty("id","")}set id(s){this.setMetaProperty("id",s)}get classes(){return this.getMetaProperty("classes",[])}set classes(s){this.setMetaProperty("classes",s)}get title(){return this.getMetaProperty("title","")}set title(s){this.setMetaProperty("title",s)}get description(){return this.getMetaProperty("description","")}set description(s){this.setMetaProperty("description",s)}get links(){return this.getMetaProperty("links",[])}set links(s){this.setMetaProperty("links",s)}get isFrozen(){return Object.isFrozen(this)}get parents(){let{parent:s}=this;const o=new _;for(;s;)o.push(s),s=s.parent;return o}get children(){if(Array.isArray(this.content))return new _(this.content);if(this.content instanceof u){const s=new _([this.content.key]);return this.content.value&&s.push(this.content.value),s}return this.content instanceof Element?new _([this.content]):new _}get recursiveChildren(){const s=new _;return this.children.forEach((o=>{s.push(o),o.recursiveChildren.forEach((o=>{s.push(o)}))})),s}}s.exports=Element},10392:s=>{s.exports=function getValue(s,o){return null==s?void 0:s[o]}},10776:(s,o,i)=>{var a=i(30756),u=i(95950);s.exports=function getMatchData(s){for(var o=u(s),i=o.length;i--;){var _=o[i],w=s[_];o[i]=[_,w,a(w)]}return o}},10866:(s,o,i)=>{const a=i(6048),u=i(92340);class ObjectSlice extends u{map(s,o){return this.elements.map((i=>s.bind(o)(i.value,i.key,i)))}filter(s,o){return new ObjectSlice(this.elements.filter((i=>s.bind(o)(i.value,i.key,i))))}reject(s,o){return this.filter(a(s.bind(o)))}forEach(s,o){return this.elements.forEach(((i,a)=>{s.bind(o)(i.value,i.key,i,a)}))}keys(){return this.map(((s,o)=>o.toValue()))}values(){return this.map((s=>s.toValue()))}}s.exports=ObjectSlice},11042:(s,o,i)=>{"use strict";var a=i(85582),u=i(1907),_=i(24443),w=i(87170),x=i(36624),C=u([].concat);s.exports=a("Reflect","ownKeys")||function ownKeys(s){var o=_.f(x(s)),i=w.f;return i?C(o,i(s)):o}},11091:(s,o,i)=>{"use strict";var a=i(45951),u=i(76024),_=i(92361),w=i(62250),x=i(13846).f,C=i(7463),j=i(92046),L=i(28311),B=i(61626),$=i(49724);i(36128);var wrapConstructor=function(s){var Wrapper=function(o,i,a){if(this instanceof Wrapper){switch(arguments.length){case 0:return new s;case 1:return new s(o);case 2:return new s(o,i)}return new s(o,i,a)}return u(s,this,arguments)};return Wrapper.prototype=s.prototype,Wrapper};s.exports=function(s,o){var i,u,V,U,z,Y,Z,ee,ie,ae=s.target,ce=s.global,le=s.stat,pe=s.proto,de=ce?a:le?a[ae]:a[ae]&&a[ae].prototype,fe=ce?j:j[ae]||B(j,ae,{})[ae],ye=fe.prototype;for(U in o)u=!(i=C(ce?U:ae+(le?".":"#")+U,s.forced))&&de&&$(de,U),Y=fe[U],u&&(Z=s.dontCallGetSet?(ie=x(de,U))&&ie.value:de[U]),z=u&&Z?Z:o[U],(i||pe||typeof Y!=typeof z)&&(ee=s.bind&&u?L(z,a):s.wrap&&u?wrapConstructor(z):pe&&w(z)?_(z):z,(s.sham||z&&z.sham||Y&&Y.sham)&&B(ee,"sham",!0),B(fe,U,ee),pe&&($(j,V=ae+"Prototype")||B(j,V,{}),B(j[V],U,z),s.real&&ye&&(i||!ye[U])&&B(ye,U,z)))}},11287:s=>{s.exports=function getHolder(s){return s.placeholder}},11331:(s,o,i)=>{var a=i(72552),u=i(28879),_=i(40346),w=Function.prototype,x=Object.prototype,C=w.toString,j=x.hasOwnProperty,L=C.call(Object);s.exports=function isPlainObject(s){if(!_(s)||"[object Object]"!=a(s))return!1;var o=u(s);if(null===o)return!0;var i=j.call(o,"constructor")&&o.constructor;return"function"==typeof i&&i instanceof i&&C.call(i)==L}},11470:(s,o,i)=>{"use strict";var a=i(1907),u=i(65482),_=i(90160),w=i(74239),x=a("".charAt),C=a("".charCodeAt),j=a("".slice),createMethod=function(s){return function(o,i){var a,L,B=_(w(o)),$=u(i),V=B.length;return $<0||$>=V?s?"":void 0:(a=C(B,$))<55296||a>56319||$+1===V||(L=C(B,$+1))<56320||L>57343?s?x(B,$):a:s?j(B,$,$+2):L-56320+(a-55296<<10)+65536}};s.exports={codeAt:createMethod(!1),charAt:createMethod(!0)}},11842:(s,o,i)=>{var a=i(82819),u=i(9325);s.exports=function createBind(s,o,i){var _=1&o,w=a(s);return function wrapper(){return(this&&this!==u&&this instanceof wrapper?w:s).apply(_?i:this,arguments)}}},12242:(s,o,i)=>{const a=i(10316);s.exports=class BooleanElement extends a{constructor(s,o,i){super(s,o,i),this.element="boolean"}primitive(){return"boolean"}}},12507:(s,o,i)=>{var a=i(28754),u=i(49698),_=i(63912),w=i(13222);s.exports=function createCaseFirst(s){return function(o){o=w(o);var i=u(o)?_(o):void 0,x=i?i[0]:o.charAt(0),C=i?a(i,1).join(""):o.slice(1);return x[s]()+C}}},12560:(s,o,i)=>{"use strict";i(99363);var a=i(19287),u=i(45951),_=i(14840),w=i(93742);for(var x in a)_(u[x],x),w[x]=w.Array},12651:(s,o,i)=>{var a=i(74218);s.exports=function getMapData(s,o){var i=s.__data__;return a(o)?i["string"==typeof o?"string":"hash"]:i.map}},12749:(s,o,i)=>{var a=i(81042),u=Object.prototype.hasOwnProperty;s.exports=function hashHas(s){var o=this.__data__;return a?void 0!==o[s]:u.call(o,s)}},13222:(s,o,i)=>{var a=i(77556);s.exports=function toString(s){return null==s?"":a(s)}},13846:(s,o,i)=>{"use strict";var a=i(39447),u=i(13930),_=i(22574),w=i(75817),x=i(4993),C=i(70470),j=i(49724),L=i(73648),B=Object.getOwnPropertyDescriptor;o.f=a?B:function getOwnPropertyDescriptor(s,o){if(s=x(s),o=C(o),L)try{return B(s,o)}catch(s){}if(j(s,o))return w(!u(_.f,s,o),s[o])}},13930:(s,o,i)=>{"use strict";var a=i(41505),u=Function.prototype.call;s.exports=a?u.bind(u):function(){return u.apply(u,arguments)}},14248:s=>{s.exports=function arraySome(s,o){for(var i=-1,a=null==s?0:s.length;++i{s.exports=function arrayPush(s,o){for(var i=-1,a=o.length,u=s.length;++i{const a=i(10316);s.exports=class RefElement extends a{constructor(s,o,i){super(s||[],o,i),this.element="ref",this.path||(this.path="element")}get path(){return this.attributes.get("path")}set path(s){this.attributes.set("path",s)}}},14744:s=>{"use strict";var o=function isMergeableObject(s){return function isNonNullObject(s){return!!s&&"object"==typeof s}(s)&&!function isSpecial(s){var o=Object.prototype.toString.call(s);return"[object RegExp]"===o||"[object Date]"===o||function isReactElement(s){return s.$$typeof===i}(s)}(s)};var i="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function cloneUnlessOtherwiseSpecified(s,o){return!1!==o.clone&&o.isMergeableObject(s)?deepmerge(function emptyTarget(s){return Array.isArray(s)?[]:{}}(s),s,o):s}function defaultArrayMerge(s,o,i){return s.concat(o).map((function(s){return cloneUnlessOtherwiseSpecified(s,i)}))}function getKeys(s){return Object.keys(s).concat(function getEnumerableOwnPropertySymbols(s){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(s).filter((function(o){return Object.propertyIsEnumerable.call(s,o)})):[]}(s))}function propertyIsOnObject(s,o){try{return o in s}catch(s){return!1}}function mergeObject(s,o,i){var a={};return i.isMergeableObject(s)&&getKeys(s).forEach((function(o){a[o]=cloneUnlessOtherwiseSpecified(s[o],i)})),getKeys(o).forEach((function(u){(function propertyIsUnsafe(s,o){return propertyIsOnObject(s,o)&&!(Object.hasOwnProperty.call(s,o)&&Object.propertyIsEnumerable.call(s,o))})(s,u)||(propertyIsOnObject(s,u)&&i.isMergeableObject(o[u])?a[u]=function getMergeFunction(s,o){if(!o.customMerge)return deepmerge;var i=o.customMerge(s);return"function"==typeof i?i:deepmerge}(u,i)(s[u],o[u],i):a[u]=cloneUnlessOtherwiseSpecified(o[u],i))})),a}function deepmerge(s,i,a){(a=a||{}).arrayMerge=a.arrayMerge||defaultArrayMerge,a.isMergeableObject=a.isMergeableObject||o,a.cloneUnlessOtherwiseSpecified=cloneUnlessOtherwiseSpecified;var u=Array.isArray(i);return u===Array.isArray(s)?u?a.arrayMerge(s,i,a):mergeObject(s,i,a):cloneUnlessOtherwiseSpecified(i,a)}deepmerge.all=function deepmergeAll(s,o){if(!Array.isArray(s))throw new Error("first argument should be an array");return s.reduce((function(s,i){return deepmerge(s,i,o)}),{})};var a=deepmerge;s.exports=a},14792:(s,o,i)=>{var a=i(13222),u=i(55808);s.exports=function capitalize(s){return u(a(s).toLowerCase())}},14840:(s,o,i)=>{"use strict";var a=i(52623),u=i(74284).f,_=i(61626),w=i(49724),x=i(54878),C=i(76264)("toStringTag");s.exports=function(s,o,i,j){var L=i?s:s&&s.prototype;L&&(w(L,C)||u(L,C,{configurable:!0,value:o}),j&&!a&&_(L,"toString",x))}},14974:s=>{s.exports=function safeGet(s,o){if(("constructor"!==o||"function"!=typeof s[o])&&"__proto__"!=o)return s[o]}},15287:(s,o)=>{"use strict";var i=Symbol.for("react.element"),a=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),x=Symbol.for("react.provider"),C=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),L=Symbol.for("react.suspense"),B=Symbol.for("react.memo"),$=Symbol.for("react.lazy"),V=Symbol.iterator;var U={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},z=Object.assign,Y={};function E(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i||U}function F(){}function G(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i||U}E.prototype.isReactComponent={},E.prototype.setState=function(s,o){if("object"!=typeof s&&"function"!=typeof s&&null!=s)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,s,o,"setState")},E.prototype.forceUpdate=function(s){this.updater.enqueueForceUpdate(this,s,"forceUpdate")},F.prototype=E.prototype;var Z=G.prototype=new F;Z.constructor=G,z(Z,E.prototype),Z.isPureReactComponent=!0;var ee=Array.isArray,ie=Object.prototype.hasOwnProperty,ae={current:null},ce={key:!0,ref:!0,__self:!0,__source:!0};function M(s,o,a){var u,_={},w=null,x=null;if(null!=o)for(u in void 0!==o.ref&&(x=o.ref),void 0!==o.key&&(w=""+o.key),o)ie.call(o,u)&&!ce.hasOwnProperty(u)&&(_[u]=o[u]);var C=arguments.length-2;if(1===C)_.children=a;else if(1{var a=i(96131);s.exports=function arrayIncludes(s,o){return!!(null==s?0:s.length)&&a(s,o,0)>-1}},15340:()=>{},15389:(s,o,i)=>{var a=i(93663),u=i(87978),_=i(83488),w=i(56449),x=i(50583);s.exports=function baseIteratee(s){return"function"==typeof s?s:null==s?_:"object"==typeof s?w(s)?u(s[0],s[1]):a(s):x(s)}},15972:(s,o,i)=>{"use strict";var a=i(49724),u=i(62250),_=i(39298),w=i(92522),x=i(57382),C=w("IE_PROTO"),j=Object,L=j.prototype;s.exports=x?j.getPrototypeOf:function(s){var o=_(s);if(a(o,C))return o[C];var i=o.constructor;return u(i)&&o instanceof i?i.prototype:o instanceof j?L:null}},16038:(s,o,i)=>{var a=i(5861),u=i(40346);s.exports=function baseIsSet(s){return u(s)&&"[object Set]"==a(s)}},16426:s=>{s.exports=function(){var s=document.getSelection();if(!s.rangeCount)return function(){};for(var o=document.activeElement,i=[],a=0;a{var a=i(43360),u=i(75288),_=Object.prototype.hasOwnProperty;s.exports=function assignValue(s,o,i){var w=s[o];_.call(s,o)&&u(w,i)&&(void 0!==i||o in s)||a(s,o,i)}},16708:(s,o,i)=>{"use strict";var a,u=i(65606);function CorkedRequest(s){var o=this;this.next=null,this.entry=null,this.finish=function(){!function onCorkedFinish(s,o,i){var a=s.entry;s.entry=null;for(;a;){var u=a.callback;o.pendingcb--,u(i),a=a.next}o.corkedRequestsFree.next=s}(o,s)}}s.exports=Writable,Writable.WritableState=WritableState;var _={deprecate:i(94643)},w=i(40345),x=i(48287).Buffer,C=(void 0!==i.g?i.g:"undefined"!=typeof window?window:"undefined"!=typeof self?self:{}).Uint8Array||function(){};var j,L=i(75896),B=i(65291).getHighWaterMark,$=i(86048).F,V=$.ERR_INVALID_ARG_TYPE,U=$.ERR_METHOD_NOT_IMPLEMENTED,z=$.ERR_MULTIPLE_CALLBACK,Y=$.ERR_STREAM_CANNOT_PIPE,Z=$.ERR_STREAM_DESTROYED,ee=$.ERR_STREAM_NULL_VALUES,ie=$.ERR_STREAM_WRITE_AFTER_END,ae=$.ERR_UNKNOWN_ENCODING,ce=L.errorOrDestroy;function nop(){}function WritableState(s,o,_){a=a||i(25382),s=s||{},"boolean"!=typeof _&&(_=o instanceof a),this.objectMode=!!s.objectMode,_&&(this.objectMode=this.objectMode||!!s.writableObjectMode),this.highWaterMark=B(this,s,"writableHighWaterMark",_),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var w=!1===s.decodeStrings;this.decodeStrings=!w,this.defaultEncoding=s.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(s){!function onwrite(s,o){var i=s._writableState,a=i.sync,_=i.writecb;if("function"!=typeof _)throw new z;if(function onwriteStateUpdate(s){s.writing=!1,s.writecb=null,s.length-=s.writelen,s.writelen=0}(i),o)!function onwriteError(s,o,i,a,_){--o.pendingcb,i?(u.nextTick(_,a),u.nextTick(finishMaybe,s,o),s._writableState.errorEmitted=!0,ce(s,a)):(_(a),s._writableState.errorEmitted=!0,ce(s,a),finishMaybe(s,o))}(s,i,a,o,_);else{var w=needFinish(i)||s.destroyed;w||i.corked||i.bufferProcessing||!i.bufferedRequest||clearBuffer(s,i),a?u.nextTick(afterWrite,s,i,w,_):afterWrite(s,i,w,_)}}(o,s)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!1!==s.emitClose,this.autoDestroy=!!s.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new CorkedRequest(this)}function Writable(s){var o=this instanceof(a=a||i(25382));if(!o&&!j.call(Writable,this))return new Writable(s);this._writableState=new WritableState(s,this,o),this.writable=!0,s&&("function"==typeof s.write&&(this._write=s.write),"function"==typeof s.writev&&(this._writev=s.writev),"function"==typeof s.destroy&&(this._destroy=s.destroy),"function"==typeof s.final&&(this._final=s.final)),w.call(this)}function doWrite(s,o,i,a,u,_,w){o.writelen=a,o.writecb=w,o.writing=!0,o.sync=!0,o.destroyed?o.onwrite(new Z("write")):i?s._writev(u,o.onwrite):s._write(u,_,o.onwrite),o.sync=!1}function afterWrite(s,o,i,a){i||function onwriteDrain(s,o){0===o.length&&o.needDrain&&(o.needDrain=!1,s.emit("drain"))}(s,o),o.pendingcb--,a(),finishMaybe(s,o)}function clearBuffer(s,o){o.bufferProcessing=!0;var i=o.bufferedRequest;if(s._writev&&i&&i.next){var a=o.bufferedRequestCount,u=new Array(a),_=o.corkedRequestsFree;_.entry=i;for(var w=0,x=!0;i;)u[w]=i,i.isBuf||(x=!1),i=i.next,w+=1;u.allBuffers=x,doWrite(s,o,!0,o.length,u,"",_.finish),o.pendingcb++,o.lastBufferedRequest=null,_.next?(o.corkedRequestsFree=_.next,_.next=null):o.corkedRequestsFree=new CorkedRequest(o),o.bufferedRequestCount=0}else{for(;i;){var C=i.chunk,j=i.encoding,L=i.callback;if(doWrite(s,o,!1,o.objectMode?1:C.length,C,j,L),i=i.next,o.bufferedRequestCount--,o.writing)break}null===i&&(o.lastBufferedRequest=null)}o.bufferedRequest=i,o.bufferProcessing=!1}function needFinish(s){return s.ending&&0===s.length&&null===s.bufferedRequest&&!s.finished&&!s.writing}function callFinal(s,o){s._final((function(i){o.pendingcb--,i&&ce(s,i),o.prefinished=!0,s.emit("prefinish"),finishMaybe(s,o)}))}function finishMaybe(s,o){var i=needFinish(o);if(i&&(function prefinish(s,o){o.prefinished||o.finalCalled||("function"!=typeof s._final||o.destroyed?(o.prefinished=!0,s.emit("prefinish")):(o.pendingcb++,o.finalCalled=!0,u.nextTick(callFinal,s,o)))}(s,o),0===o.pendingcb&&(o.finished=!0,s.emit("finish"),o.autoDestroy))){var a=s._readableState;(!a||a.autoDestroy&&a.endEmitted)&&s.destroy()}return i}i(56698)(Writable,w),WritableState.prototype.getBuffer=function getBuffer(){for(var s=this.bufferedRequest,o=[];s;)o.push(s),s=s.next;return o},function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:_.deprecate((function writableStateBufferGetter(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(s){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(j=Function.prototype[Symbol.hasInstance],Object.defineProperty(Writable,Symbol.hasInstance,{value:function value(s){return!!j.call(this,s)||this===Writable&&(s&&s._writableState instanceof WritableState)}})):j=function realHasInstance(s){return s instanceof this},Writable.prototype.pipe=function(){ce(this,new Y)},Writable.prototype.write=function(s,o,i){var a=this._writableState,_=!1,w=!a.objectMode&&function _isUint8Array(s){return x.isBuffer(s)||s instanceof C}(s);return w&&!x.isBuffer(s)&&(s=function _uint8ArrayToBuffer(s){return x.from(s)}(s)),"function"==typeof o&&(i=o,o=null),w?o="buffer":o||(o=a.defaultEncoding),"function"!=typeof i&&(i=nop),a.ending?function writeAfterEnd(s,o){var i=new ie;ce(s,i),u.nextTick(o,i)}(this,i):(w||function validChunk(s,o,i,a){var _;return null===i?_=new ee:"string"==typeof i||o.objectMode||(_=new V("chunk",["string","Buffer"],i)),!_||(ce(s,_),u.nextTick(a,_),!1)}(this,a,s,i))&&(a.pendingcb++,_=function writeOrBuffer(s,o,i,a,u,_){if(!i){var w=function decodeChunk(s,o,i){s.objectMode||!1===s.decodeStrings||"string"!=typeof o||(o=x.from(o,i));return o}(o,a,u);a!==w&&(i=!0,u="buffer",a=w)}var C=o.objectMode?1:a.length;o.length+=C;var j=o.length-1))throw new ae(s);return this._writableState.defaultEncoding=s,this},Object.defineProperty(Writable.prototype,"writableBuffer",{enumerable:!1,get:function get(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:!1,get:function get(){return this._writableState.highWaterMark}}),Writable.prototype._write=function(s,o,i){i(new U("_write()"))},Writable.prototype._writev=null,Writable.prototype.end=function(s,o,i){var a=this._writableState;return"function"==typeof s?(i=s,s=null,o=null):"function"==typeof o&&(i=o,o=null),null!=s&&this.write(s,o),a.corked&&(a.corked=1,this.uncork()),a.ending||function endWritable(s,o,i){o.ending=!0,finishMaybe(s,o),i&&(o.finished?u.nextTick(i):s.once("finish",i));o.ended=!0,s.writable=!1}(this,a,i),this},Object.defineProperty(Writable.prototype,"writableLength",{enumerable:!1,get:function get(){return this._writableState.length}}),Object.defineProperty(Writable.prototype,"destroyed",{enumerable:!1,get:function get(){return void 0!==this._writableState&&this._writableState.destroyed},set:function set(s){this._writableState&&(this._writableState.destroyed=s)}}),Writable.prototype.destroy=L.destroy,Writable.prototype._undestroy=L.undestroy,Writable.prototype._destroy=function(s,o){o(s)}},16750:(s,o,i)=>{"use strict";o.J=void 0;var a=i(69119);function decodeURI(s){try{return decodeURIComponent(s)}catch(o){return s}}o.J=function sanitizeUrl(s){if(!s)return a.BLANK_URL;var o,i,u=decodeURI(s);do{o=(u=decodeURI(u=(i=u,i.replace(a.ctrlCharactersRegex,"").replace(a.htmlEntitiesRegex,(function(s,o){return String.fromCharCode(o)}))).replace(a.htmlCtrlEntityRegex,"").replace(a.ctrlCharactersRegex,"").replace(a.whitespaceEscapeCharsRegex,"").trim())).match(a.ctrlCharactersRegex)||u.match(a.htmlEntitiesRegex)||u.match(a.htmlCtrlEntityRegex)||u.match(a.whitespaceEscapeCharsRegex)}while(o&&o.length>0);var _=u;if(!_)return a.BLANK_URL;if(function isRelativeUrlWithoutProtocol(s){return a.relativeFirstCharacters.indexOf(s[0])>-1}(_))return _;var w=_.match(a.urlSchemeRegex);if(!w)return _;var x=w[0];return a.invalidProtocolRegex.test(x)?a.BLANK_URL:_}},16946:(s,o,i)=>{"use strict";var a=i(1907),u=i(98828),_=i(45807),w=Object,x=a("".split);s.exports=u((function(){return!w("z").propertyIsEnumerable(0)}))?function(s){return"String"===_(s)?x(s,""):w(s)}:w},16962:(s,o)=>{o.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},o.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},o.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},o.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},o.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},o.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},o.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},o.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},o.realToAlias=function(){var s=Object.prototype.hasOwnProperty,i=o.aliasToReal,a={};for(var u in i){var _=i[u];s.call(a,_)?a[_].push(u):a[_]=[u]}return a}(),o.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},o.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},o.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},17255:(s,o,i)=>{var a=i(47422);s.exports=function basePropertyDeep(s){return function(o){return a(o,s)}}},17285:s=>{function source(s){return s?"string"==typeof s?s:s.source:null}function lookahead(s){return concat("(?=",s,")")}function concat(...s){return s.map((s=>source(s))).join("")}function either(...s){return"("+s.map((s=>source(s))).join("|")+")"}s.exports=function xml(s){const o=concat(/[A-Z_]/,function optional(s){return concat("(",s,")?")}(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),i={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},u=s.inherit(a,{begin:/\(/,end:/\)/}),_=s.inherit(s.APOS_STRING_MODE,{className:"meta-string"}),w=s.inherit(s.QUOTE_STRING_MODE,{className:"meta-string"}),x={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[a,w,_,u,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[a,u,w,_]}]}]},s.COMMENT(//,{relevance:10}),{begin://,relevance:10},i,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[x],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[x],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:o,relevance:0,starts:x}]},{className:"tag",begin:concat(/<\//,lookahead(concat(o,/>/))),contains:[{className:"name",begin:o,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}},17400:(s,o,i)=>{var a=i(99374),u=1/0;s.exports=function toFinite(s){return s?(s=a(s))===u||s===-1/0?17976931348623157e292*(s<0?-1:1):s==s?s:0:0===s?s:0}},17533:s=>{s.exports=function yaml(s){var o="true false yes no null",i="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[s.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},u=s.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),_={className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},w={end:",",endsWithParent:!0,excludeEnd:!0,keywords:o,relevance:0},x={begin:/\{/,end:/\}/,contains:[w],illegal:"\\n",relevance:0},C={begin:"\\[",end:"\\]",contains:[w],illegal:"\\n",relevance:0},j=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+i},{className:"type",begin:"!<"+i+">"},{className:"type",begin:"!"+i},{className:"type",begin:"!!"+i},{className:"meta",begin:"&"+s.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+s.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},s.HASH_COMMENT_MODE,{beginKeywords:o,keywords:{literal:o}},_,{className:"number",begin:s.C_NUMBER_RE+"\\b",relevance:0},x,C,a],L=[...j];return L.pop(),L.push(u),w.contains=L,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:j}}},17670:(s,o,i)=>{var a=i(12651);s.exports=function mapCacheDelete(s){var o=a(this,s).delete(s);return this.size-=o?1:0,o}},17965:(s,o,i)=>{"use strict";var a=i(16426),u={"text/plain":"Text","text/html":"Url",default:"Text"};s.exports=function copy(s,o){var i,_,w,x,C,j,L=!1;o||(o={}),i=o.debug||!1;try{if(w=a(),x=document.createRange(),C=document.getSelection(),(j=document.createElement("span")).textContent=s,j.ariaHidden="true",j.style.all="unset",j.style.position="fixed",j.style.top=0,j.style.clip="rect(0, 0, 0, 0)",j.style.whiteSpace="pre",j.style.webkitUserSelect="text",j.style.MozUserSelect="text",j.style.msUserSelect="text",j.style.userSelect="text",j.addEventListener("copy",(function(a){if(a.stopPropagation(),o.format)if(a.preventDefault(),void 0===a.clipboardData){i&&console.warn("unable to use e.clipboardData"),i&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var _=u[o.format]||u.default;window.clipboardData.setData(_,s)}else a.clipboardData.clearData(),a.clipboardData.setData(o.format,s);o.onCopy&&(a.preventDefault(),o.onCopy(a.clipboardData))})),document.body.appendChild(j),x.selectNodeContents(j),C.addRange(x),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");L=!0}catch(a){i&&console.error("unable to copy using execCommand: ",a),i&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(o.format||"text",s),o.onCopy&&o.onCopy(window.clipboardData),L=!0}catch(a){i&&console.error("unable to copy using clipboardData: ",a),i&&console.error("falling back to prompt"),_=function format(s){var o=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return s.replace(/#{\s*key\s*}/g,o)}("message"in o?o.message:"Copy to clipboard: #{key}, Enter"),window.prompt(_,s)}}finally{C&&("function"==typeof C.removeRange?C.removeRange(x):C.removeAllRanges()),j&&document.body.removeChild(j),w()}return L}},18073:(s,o,i)=>{var a=i(85087),u=i(54641),_=i(70981);s.exports=function createRecurry(s,o,i,w,x,C,j,L,B,$){var V=8&o;o|=V?32:64,4&(o&=~(V?64:32))||(o&=-4);var U=[s,o,x,V?C:void 0,V?j:void 0,V?void 0:C,V?void 0:j,L,B,$],z=i.apply(void 0,U);return a(s)&&u(z,U),z.placeholder=w,_(z,s,o)}},19123:(s,o,i)=>{var a=i(65606),u=i(31499),_=i(88310).Stream;function resolve(s,o,i){var a,_=function create_indent(s,o){return new Array(o||0).join(s||"")}(o,i=i||0),w=s;if("object"==typeof s&&((w=s[a=Object.keys(s)[0]])&&w._elem))return w._elem.name=a,w._elem.icount=i,w._elem.indent=o,w._elem.indents=_,w._elem.interrupt=w,w._elem;var x,C=[],j=[];function get_attributes(s){Object.keys(s).forEach((function(o){C.push(function attribute(s,o){return s+'="'+u(o)+'"'}(o,s[o]))}))}switch(typeof w){case"object":if(null===w)break;w._attr&&get_attributes(w._attr),w._cdata&&j.push(("/g,"]]]]>")+"]]>"),w.forEach&&(x=!1,j.push(""),w.forEach((function(s){"object"==typeof s?"_attr"==Object.keys(s)[0]?get_attributes(s._attr):j.push(resolve(s,o,i+1)):(j.pop(),x=!0,j.push(u(s)))})),x||j.push(""));break;default:j.push(u(w))}return{name:a,interrupt:!1,attributes:C,content:j,icount:i,indents:_,indent:o}}function format(s,o,i){if("object"!=typeof o)return s(!1,o);var a=o.interrupt?1:o.content.length;function proceed(){for(;o.content.length;){var u=o.content.shift();if(void 0!==u){if(interrupt(u))return;format(s,u)}}s(!1,(a>1?o.indents:"")+(o.name?"":"")+(o.indent&&!i?"\n":"")),i&&i()}function interrupt(o){return!!o.interrupt&&(o.interrupt.append=s,o.interrupt.end=proceed,o.interrupt=!1,s(!0),!0)}if(s(!1,o.indents+(o.name?"<"+o.name:"")+(o.attributes.length?" "+o.attributes.join(" "):"")+(a?o.name?">":"":o.name?"/>":"")+(o.indent&&a>1?"\n":"")),!a)return s(!1,o.indent?"\n":"");interrupt(o)||proceed()}s.exports=function xml(s,o){"object"!=typeof o&&(o={indent:o});var i=o.stream?new _:null,u="",w=!1,x=o.indent?!0===o.indent?" ":o.indent:"",C=!0;function delay(s){C?a.nextTick(s):s()}function append(s,o){if(void 0!==o&&(u+=o),s&&!w&&(i=i||new _,w=!0),s&&w){var a=u;delay((function(){i.emit("data",a)})),u=""}}function add(s,o){format(append,resolve(s,x,x?1:0),o)}function end(){if(i){var s=u;delay((function(){i.emit("data",s),i.emit("end"),i.readable=!1,i.emit("close")}))}}return delay((function(){C=!1})),o.declaration&&function addXmlDeclaration(s){var o={version:"1.0",encoding:s.encoding||"UTF-8"};s.standalone&&(o.standalone=s.standalone),add({"?xml":{_attr:o}}),u=u.replace("/>","?>")}(o.declaration),s&&s.forEach?s.forEach((function(o,i){var a;i+1===s.length&&(a=end),add(o,a)})):add(s,end),i?(i.readable=!0,i):u},s.exports.element=s.exports.Element=function element(){var s={_elem:resolve(Array.prototype.slice.call(arguments)),push:function(s){if(!this.append)throw new Error("not assigned to a parent!");var o=this,i=this._elem.indent;format(this.append,resolve(s,i,this._elem.icount+(i?1:0)),(function(){o.append(!0)}))},close:function(s){void 0!==s&&this.push(s),this.end&&this.end()}};return s}},19219:s=>{s.exports=function cacheHas(s,o){return s.has(o)}},19287:s=>{"use strict";s.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},19358:(s,o,i)=>{"use strict";var a=i(85582),u=i(49724),_=i(61626),w=i(88280),x=i(79192),C=i(19595),j=i(54829),L=i(34084),B=i(32096),$=i(39259),V=i(85884),U=i(39447),z=i(7376);s.exports=function(s,o,i,Y){var Z="stackTraceLimit",ee=Y?2:1,ie=s.split("."),ae=ie[ie.length-1],ce=a.apply(null,ie);if(ce){var le=ce.prototype;if(!z&&u(le,"cause")&&delete le.cause,!i)return ce;var pe=a("Error"),de=o((function(s,o){var i=B(Y?o:s,void 0),a=Y?new ce(s):new ce;return void 0!==i&&_(a,"message",i),V(a,de,a.stack,2),this&&w(le,this)&&L(a,this,de),arguments.length>ee&&$(a,arguments[ee]),a}));if(de.prototype=le,"Error"!==ae?x?x(de,pe):C(de,pe,{name:!0}):U&&Z in ce&&(j(de,ce,Z),j(de,ce,"prepareStackTrace")),C(de,ce),!z)try{le.name!==ae&&_(le,"name",ae),le.constructor=de}catch(s){}return de}}},19570:(s,o,i)=>{var a=i(37334),u=i(93243),_=i(83488),w=u?function(s,o){return u(s,"toString",{configurable:!0,enumerable:!1,value:a(o),writable:!0})}:_;s.exports=w},19595:(s,o,i)=>{"use strict";var a=i(49724),u=i(11042),_=i(13846),w=i(74284);s.exports=function(s,o,i){for(var x=u(o),C=w.f,j=_.f,L=0;L{"use strict";var a=i(23034);s.exports=a},19846:(s,o,i)=>{"use strict";var a=i(20798),u=i(98828),_=i(45951).String;s.exports=!!Object.getOwnPropertySymbols&&!u((function(){var s=Symbol("symbol detection");return!_(s)||!(Object(s)instanceof Symbol)||!Symbol.sham&&a&&a<41}))},19931:(s,o,i)=>{var a=i(31769),u=i(68090),_=i(68969),w=i(77797);s.exports=function baseUnset(s,o){return o=a(o,s),null==(s=_(s,o))||delete s[w(u(o))]}},20181:(s,o,i)=>{var a=/^\s+|\s+$/g,u=/^[-+]0x[0-9a-f]+$/i,_=/^0b[01]+$/i,w=/^0o[0-7]+$/i,x=parseInt,C="object"==typeof i.g&&i.g&&i.g.Object===Object&&i.g,j="object"==typeof self&&self&&self.Object===Object&&self,L=C||j||Function("return this")(),B=Object.prototype.toString,$=Math.max,V=Math.min,now=function(){return L.Date.now()};function isObject(s){var o=typeof s;return!!s&&("object"==o||"function"==o)}function toNumber(s){if("number"==typeof s)return s;if(function isSymbol(s){return"symbol"==typeof s||function isObjectLike(s){return!!s&&"object"==typeof s}(s)&&"[object Symbol]"==B.call(s)}(s))return NaN;if(isObject(s)){var o="function"==typeof s.valueOf?s.valueOf():s;s=isObject(o)?o+"":o}if("string"!=typeof s)return 0===s?s:+s;s=s.replace(a,"");var i=_.test(s);return i||w.test(s)?x(s.slice(2),i?2:8):u.test(s)?NaN:+s}s.exports=function debounce(s,o,i){var a,u,_,w,x,C,j=0,L=!1,B=!1,U=!0;if("function"!=typeof s)throw new TypeError("Expected a function");function invokeFunc(o){var i=a,_=u;return a=u=void 0,j=o,w=s.apply(_,i)}function shouldInvoke(s){var i=s-C;return void 0===C||i>=o||i<0||B&&s-j>=_}function timerExpired(){var s=now();if(shouldInvoke(s))return trailingEdge(s);x=setTimeout(timerExpired,function remainingWait(s){var i=o-(s-C);return B?V(i,_-(s-j)):i}(s))}function trailingEdge(s){return x=void 0,U&&a?invokeFunc(s):(a=u=void 0,w)}function debounced(){var s=now(),i=shouldInvoke(s);if(a=arguments,u=this,C=s,i){if(void 0===x)return function leadingEdge(s){return j=s,x=setTimeout(timerExpired,o),L?invokeFunc(s):w}(C);if(B)return x=setTimeout(timerExpired,o),invokeFunc(C)}return void 0===x&&(x=setTimeout(timerExpired,o)),w}return o=toNumber(o)||0,isObject(i)&&(L=!!i.leading,_=(B="maxWait"in i)?$(toNumber(i.maxWait)||0,o):_,U="trailing"in i?!!i.trailing:U),debounced.cancel=function cancel(){void 0!==x&&clearTimeout(x),j=0,a=C=u=x=void 0},debounced.flush=function flush(){return void 0===x?w:trailingEdge(now())},debounced}},20317:s=>{s.exports=function mapToArray(s){var o=-1,i=Array(s.size);return s.forEach((function(s,a){i[++o]=[a,s]})),i}},20334:(s,o,i)=>{"use strict";var a=i(48287).Buffer;class NonError extends Error{constructor(s){super(NonError._prepareSuperMessage(s)),Object.defineProperty(this,"name",{value:"NonError",configurable:!0,writable:!0}),Error.captureStackTrace&&Error.captureStackTrace(this,NonError)}static _prepareSuperMessage(s){try{return JSON.stringify(s)}catch{return String(s)}}}const u=[{property:"name",enumerable:!1},{property:"message",enumerable:!1},{property:"stack",enumerable:!1},{property:"code",enumerable:!0}],_=Symbol(".toJSON called"),destroyCircular=({from:s,seen:o,to_:i,forceEnumerable:w,maxDepth:x,depth:C})=>{const j=i||(Array.isArray(s)?[]:{});if(o.push(s),C>=x)return j;if("function"==typeof s.toJSON&&!0!==s[_])return(s=>{s[_]=!0;const o=s.toJSON();return delete s[_],o})(s);for(const[i,u]of Object.entries(s))"function"==typeof a&&a.isBuffer(u)?j[i]="[object Buffer]":"function"!=typeof u&&(u&&"object"==typeof u?o.includes(s[i])?j[i]="[Circular]":(C++,j[i]=destroyCircular({from:s[i],seen:o.slice(),forceEnumerable:w,maxDepth:x,depth:C})):j[i]=u);for(const{property:o,enumerable:i}of u)"string"==typeof s[o]&&Object.defineProperty(j,o,{value:s[o],enumerable:!!w||i,configurable:!0,writable:!0});return j};s.exports={serializeError:(s,o={})=>{const{maxDepth:i=Number.POSITIVE_INFINITY}=o;return"object"==typeof s&&null!==s?destroyCircular({from:s,seen:[],forceEnumerable:!0,maxDepth:i,depth:0}):"function"==typeof s?`[Function: ${s.name||"anonymous"}]`:s},deserializeError:(s,o={})=>{const{maxDepth:i=Number.POSITIVE_INFINITY}=o;if(s instanceof Error)return s;if("object"==typeof s&&null!==s&&!Array.isArray(s)){const o=new Error;return destroyCircular({from:s,seen:[],to_:o,maxDepth:i,depth:0}),o}return new NonError(s)}}},20426:s=>{var o=Object.prototype.hasOwnProperty;s.exports=function baseHas(s,i){return null!=s&&o.call(s,i)}},20575:(s,o,i)=>{"use strict";var a=i(3121);s.exports=function(s){return a(s.length)}},20798:(s,o,i)=>{"use strict";var a,u,_=i(45951),w=i(96794),x=_.process,C=_.Deno,j=x&&x.versions||C&&C.version,L=j&&j.v8;L&&(u=(a=L.split("."))[0]>0&&a[0]<4?1:+(a[0]+a[1])),!u&&w&&(!(a=w.match(/Edge\/(\d+)/))||a[1]>=74)&&(a=w.match(/Chrome\/(\d+)/))&&(u=+a[1]),s.exports=u},20850:(s,o,i)=>{"use strict";s.exports=i(46076)},20999:(s,o,i)=>{var a=i(69302),u=i(36800);s.exports=function createAssigner(s){return a((function(o,i){var a=-1,_=i.length,w=_>1?i[_-1]:void 0,x=_>2?i[2]:void 0;for(w=s.length>3&&"function"==typeof w?(_--,w):void 0,x&&u(i[0],i[1],x)&&(w=_<3?void 0:w,_=1),o=Object(o);++a<_;){var C=i[a];C&&s(o,C,a,w)}return o}))}},21549:(s,o,i)=>{var a=i(22032),u=i(63862),_=i(66721),w=i(12749),x=i(35749);function Hash(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o{var a=i(16547),u=i(43360);s.exports=function copyObject(s,o,i,_){var w=!i;i||(i={});for(var x=-1,C=o.length;++x{var a=i(51873),u=i(37828),_=i(75288),w=i(25911),x=i(20317),C=i(84247),j=a?a.prototype:void 0,L=j?j.valueOf:void 0;s.exports=function equalByTag(s,o,i,a,j,B,$){switch(i){case"[object DataView]":if(s.byteLength!=o.byteLength||s.byteOffset!=o.byteOffset)return!1;s=s.buffer,o=o.buffer;case"[object ArrayBuffer]":return!(s.byteLength!=o.byteLength||!B(new u(s),new u(o)));case"[object Boolean]":case"[object Date]":case"[object Number]":return _(+s,+o);case"[object Error]":return s.name==o.name&&s.message==o.message;case"[object RegExp]":case"[object String]":return s==o+"";case"[object Map]":var V=x;case"[object Set]":var U=1&a;if(V||(V=C),s.size!=o.size&&!U)return!1;var z=$.get(s);if(z)return z==o;a|=2,$.set(s,o);var Y=w(V(s),V(o),a,j,B,$);return $.delete(s),Y;case"[object Symbol]":if(L)return L.call(s)==L.call(o)}return!1}},22032:(s,o,i)=>{var a=i(81042);s.exports=function hashClear(){this.__data__=a?a(null):{},this.size=0}},22225:s=>{var o="\\ud800-\\udfff",i="\\u2700-\\u27bf",a="a-z\\xdf-\\xf6\\xf8-\\xff",u="A-Z\\xc0-\\xd6\\xd8-\\xde",_="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",w="["+_+"]",x="\\d+",C="["+i+"]",j="["+a+"]",L="[^"+o+_+x+i+a+u+"]",B="(?:\\ud83c[\\udde6-\\uddff]){2}",$="[\\ud800-\\udbff][\\udc00-\\udfff]",V="["+u+"]",U="(?:"+j+"|"+L+")",z="(?:"+V+"|"+L+")",Y="(?:['’](?:d|ll|m|re|s|t|ve))?",Z="(?:['’](?:D|LL|M|RE|S|T|VE))?",ee="(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?",ie="[\\ufe0e\\ufe0f]?",ae=ie+ee+("(?:\\u200d(?:"+["[^"+o+"]",B,$].join("|")+")"+ie+ee+")*"),ce="(?:"+[C,B,$].join("|")+")"+ae,le=RegExp([V+"?"+j+"+"+Y+"(?="+[w,V,"$"].join("|")+")",z+"+"+Z+"(?="+[w,V+U,"$"].join("|")+")",V+"?"+U+"+"+Y,V+"+"+Z,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",x,ce].join("|"),"g");s.exports=function unicodeWords(s){return s.match(le)||[]}},22551:(s,o,i)=>{"use strict";var a=i(96540),u=i(69982);function p(s){for(var o="https://reactjs.org/docs/error-decoder.html?invariant="+s,i=1;i