diff --git a/dtwo/.claude-plugin/plugin.json b/dtwo/.claude-plugin/plugin.json index a32fda5..01a1d02 100644 --- a/dtwo/.claude-plugin/plugin.json +++ b/dtwo/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "dtwo", - "version": "1.1.7", + "version": "1.1.8", "description": "Manage Dtwo gateways, policies, and Rego with the Dtwo MCP server.", "author": { "name": "Dtwo", diff --git a/dtwo/skills/dtwo-gateway-config/SKILL.md b/dtwo/skills/dtwo-gateway-config/SKILL.md index 3eddc52..1427a8b 100644 --- a/dtwo/skills/dtwo-gateway-config/SKILL.md +++ b/dtwo/skills/dtwo-gateway-config/SKILL.md @@ -118,7 +118,7 @@ This subsection is generated from `schema-reference.json` by `scripts/generate-s | `gateway.authentication.oauth_dcr` | OAuth Dynamic Client Registration overrides. Defaults are auto-derived from mcp_servers; set fields here to override (typically to disable DCR/discovery for IdPs that pre-provision clients). | | `gateway.ssrf` | SSRF protection overrides. Strict defaults apply when omitted. | | `gateway.intent` | Gateway session-intent controls. | -| `gateway.session_control` | Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it. | +| `gateway.session_control` | Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. A gateway using Dtwo authentication needs no credentials here — it gets its organization's platform-provisioned app — but prefer `clearing: {enabled: true}` over an empty block, so the block states what it does: an empty one arms only while `intent.enabled` is true and parks inert otherwise. `client_id` is only needed for a gateway trusting a customer-run IdP, and `redirect_uri` only for one the browser reaches at a different origin than its token audience. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it. | | `gateway.session_control.clearing` | Arming control for human-gated clearing. | | `mcp_servers[]` | One entry per upstream MCP server. `name` and `url` required. | | `mcp_servers[].authentication` | Discriminated union keyed on `type`; outbound auth from gateway to the upstream server. 7 variants (see table). | @@ -144,7 +144,7 @@ Every field in this section, with the artifact's own guidance: | Field | Required | Type | Default | Target | Guidance (from artifact) | |---|---|---|---|---|---| -| `enabled` | yes | boolean | `true` (schema) | `MCP_REQUIRE_AUTH` | Leave at the default `true` for production. Set `false` only for local development where you want an unauthenticated gateway. | +| `enabled` | no | boolean | `true` (schema) | `MCP_REQUIRE_AUTH` | Leave at the default `true` for production. Set `false` only for local development where you want an unauthenticated gateway. | | `sso_issuer` | no | URL | `not declared` | `SSO_GENERIC_ISSUER` | Set when you're using an SSO provider that publishes an OpenID Connect discovery document at `{issuer}/.well-known/openid-configuration`. Only set an issuer you want advertised: MCP clients will follow it for OAuth discovery. | | `jwt_issuer_verification` | no | boolean | `true` (gateway) | `JWT_ISSUER_VERIFICATION` | Leave unset or `true` — the gateway defaults it to `true` and refuses to start with `false` whenever `jwks_info` is configured, because skipping issuer verification against external IdP keys enables token substitution; the schema rejects `false` for the same reason. Set `true` explicitly to pin the secure value against a future change in the gateway default, not to make a choice. | | `jwt_audience_verification` | no | boolean | `true` (gateway) | `JWT_AUDIENCE_VERIFICATION` | Leave unset or `true` — the gateway defaults it to `true` and refuses to start with `false` whenever `jwks_info` is configured, since a token minted for another service in the same tenant would otherwise be accepted here; the schema rejects `false` for the same reason. Set `true` explicitly to pin the secure value against a future change in the gateway default, not to make a choice. | @@ -194,7 +194,7 @@ Strict defaults block localhost, private networks, and fail-closed DNS when omit |---|---|---|---|---| | `allow_localhost` | boolean | `false` (deploy) | `SSRF_ALLOW_LOCALHOST` | Enable only for local development where the MCP server runs on the same host as the gateway; leaving it on in production widens the gateway's outbound attack surface. | | `allow_private_networks` | boolean | `false` (deploy) | `SSRF_ALLOW_PRIVATE_NETWORKS` | Enable only when the gateway and MCP server share a private network (e.g. co-located on one EC2 host); prefer `allowed_networks` with a surgical CIDR allowlist in production, since a blanket private-range allow widens the gateway's outbound attack surface. | -| `allowed_networks` | array | `[]` (deploy) | `SSRF_ALLOWED_NETWORKS` | Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts — prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface. | +| `allowed_networks` | array | `[]` (deploy) | `SSRF_ALLOWED_NETWORKS` | Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts — prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface. Shared address space `100.64.0.0/10` (CGNAT — every Tailscale node address, for example) is blocked on every server registration and config import since ContextForge 1.0.7, above every other SSRF setting; a CIDR here that lies wholly inside `100.64.0.0/10` (e.g. `100.64.0.0/10` itself or your tailnet subnet) re-permits those addresses. Broad entries such as `100.0.0.0/8` or `0.0.0.0/0` do not. | #### `gateway.advanced` and `gateway.log_level` @@ -203,9 +203,9 @@ Strict defaults block localhost, private networks, and fail-closed DNS when omit #### Reserved keys — rejected inside `gateway.advanced` -Validation rejects each of these 54 env-var names when written into `gateway.advanced`, in three groups. +Validation rejects each of these 60 env-var names when written into `gateway.advanced`, in three groups. -Owned by a typed config field documented above (20) — set the field instead of the raw env line: +Owned by a typed config field documented above (21) — set the field instead of the raw env line: | Reserved key | Configure via | |---|---| @@ -224,6 +224,7 @@ Owned by a typed config field documented above (20) — set the field instead of | `REQUIRE_JTI` | `gateway.authentication.require_jti` | | `REQUIRE_TOKEN_EXPIRATION` | `gateway.authentication.require_token_expiration` | | `SESSION_CONTROL_CLIENT_ID` | `gateway.session_control.client_id` | +| `SESSION_CONTROL_REDIRECT_URI` | `gateway.session_control.redirect_uri` | | `SSO_GENERIC_ISSUER` | `gateway.authentication.sso_issuer` | | `SSO_GENERIC_SCOPE` | `gateway.authentication.sso_generic_scope` | | `SSRF_ALLOWED_NETWORKS` | `gateway.ssrf.allowed_networks` | @@ -246,9 +247,9 @@ Owned by a typed config field outside this digest's documented surface (11) — | `SSRF_DNS_FAIL_CLOSED` | `gateway.ssrf.dns_fail_closed` | | `WELL_KNOWN_ALLOW_HTTP` | `gateway.authentication.well_known_allow_http` | -Platform-managed (23) — nothing in the config schema owns these, typed or otherwise; the platform sets them and they are not configurable through this config at all: +Platform-managed (28) — nothing in the config schema owns these, typed or otherwise; the platform sets them and they are not configurable through this config at all: -`AUDIT_TRAIL_ENABLED`, `AUTH_ENCRYPTION_SECRET`, `AUTH_REQUIRED`, `AUTO_REFRESH_SERVERS`, `CACHE_TYPE`, `D2_TENANT_ID`, `DATABASE_URL`, `DISABLE_ACCESS_LOG`, `EMAIL_AUTH_ENABLED`, `ENVIRONMENT`, `GUNICORN_WORKERS`, `JWT_REQUIRED_ORG_ID`, `JWT_SECRET_KEY`, `MCPGATEWAY_ADMIN_API_ENABLED`, `MCPGATEWAY_UI_ENABLED`, `PLATFORM_ADMIN_EMAIL`, `PLATFORM_ADMIN_PASSWORD`, `PLUGINS_CONFIG_FILE`, `PLUGINS_ENABLED`, `SECURITY_HEADERS_ENABLED`, `SESSION_CONTROL_ISSUER`, `STRUCTURED_LOGGING_DATABASE_ENABLED`, `TRANSPORT_TYPE` +`AUDIT_TRAIL_ENABLED`, `AUTH_ENCRYPTION_SECRET`, `AUTH_REQUIRED`, `AUTO_REFRESH_SERVERS`, `CACHE_TYPE`, `CPEX_CONTROL_TELEMETRY_DB_ENABLED`, `CPEX_CONTROL_TELEMETRY_ENABLED`, `CSRF_ENABLED`, `D2_TENANT_ID`, `DATABASE_URL`, `DISABLE_ACCESS_LOG`, `EMAIL_AUTH_ENABLED`, `ENVIRONMENT`, `GUNICORN_WORKERS`, `JWT_REQUIRED_ORG_ID`, `JWT_SECRET_KEY`, `MCPGATEWAY_A2A_ENABLED`, `MCPGATEWAY_ADMIN_API_ENABLED`, `MCPGATEWAY_UI_ENABLED`, `PLATFORM_ADMIN_EMAIL`, `PLATFORM_ADMIN_PASSWORD`, `PLUGINS_CONFIG_FILE`, `PLUGINS_ENABLED`, `SECURITY_HEADERS_ENABLED`, `SESSION_CONTROL_ISSUER`, `SOTW_DELETE_POLICY`, `STRUCTURED_LOGGING_DATABASE_ENABLED`, `TRANSPORT_TYPE` #### `gateway.intent` — session-intent capture @@ -264,11 +265,12 @@ Gateway session-intent controls. #### `gateway.session_control` — human-gated clearing registration -Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it. +Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. A gateway using Dtwo authentication needs no credentials here — it gets its organization's platform-provisioned app — but prefer `clearing: {enabled: true}` over an empty block, so the block states what it does: an empty one arms only while `intent.enabled` is true and parks inert otherwise. `client_id` is only needed for a gateway trusting a customer-run IdP, and `redirect_uri` only for one the browser reaches at a different origin than its token audience. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it. | Field | Required | Type | Default | Target | Guidance (from artifact) | |---|---|---|---|---|---| -| `client_id` | yes | string | — | `SESSION_CONTROL_CLIENT_ID` | Register a dedicated public client at your IdP for the clear ceremony (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client. | +| `client_id` | no | string | `not declared` | `SESSION_CONTROL_CLIENT_ID` | Leave unset on a gateway using Dtwo authentication. Set it only when the gateway trusts your own IdP: the ceremony app must live in the IdP that issues the gateway's inbound tokens, so register a dedicated public client there (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client. | +| `redirect_uri` | no | string | `not declared` | `SESSION_CONTROL_REDIRECT_URI` | Leave unset in almost all cases — the gateway derives `/session-control/clear/callback` and the platform registers that. Set it when a reverse proxy or split-horizon DNS puts the browser on a different origin than the audience: give the URL the browser can actually reach, at the root path (`/mcp/*` routes to the streamable-HTTP handler, which rejects browser GETs). | **Cross-field constraints** (verbatim from artifact): > `clearing.enabled` unset follows `gateway.intent.enabled`; an explicit `true` arms clearing even with intent capture off (the markers-only deployment). @@ -277,6 +279,10 @@ Human-gated session clearing (session-control) registration: the IdP app the bro > > While clearing is armed, `gateway.authentication` must be enabled with `jwks_info` — the ceremony binds every clear to the authenticated caller identity, so an unauthenticated inbound leg has nothing to bind. > +> A gateway that authenticates against an IdP other than Dtwo's Auth0 must set `client_id`: the platform provisions a ceremony app only in its own tenant, and the deploy fails rather than arming a gateway whose ceremony has no application to authenticate against. +> +> `redirect_uri`, when set, replaces the callback the gateway would derive from the first entry of `jwt_audience`, and is the URL the platform allow-lists on the IdP application. Unset, ordering within a comma-separated `jwt_audience` decides the callback. +> > While clearing is armed, `jwt_issuer` must be a normalized HTTPS URL (it becomes the ceremony issuer via `SESSION_CONTROL_ISSUER`) and `jwt_audience` must not be blank. #### `gateway.session_control.clearing` — arming control @@ -285,7 +291,7 @@ Arming control for human-gated clearing. | Field | Required | Type | Default | Target | Guidance (from artifact) | |---|---|---|---|---|---| -| `enabled` | no | boolean | `not declared` | `platform.session_control.clearing.enabled` | Leave unset in almost all cases — clearing arms automatically wherever intent capture is on and this block is configured. Set `true` explicitly on a gateway that runs marker-writing policies WITHOUT intent capture, which otherwise has no targeted clear path and can only wait for a marker to expire. | +| `enabled` | no | boolean | `not declared` | `platform.session_control.clearing.enabled` | Write `true` whenever you want clearing. It is only strictly *required* on a gateway that runs marker-writing policies WITHOUT intent capture — with intent capture on, the block arms on its own — but stating it makes the block say what it does rather than leaving that to `gateway.intent.enabled`, and it keeps clearing armed if intent capture is later turned off. `false` while intent capture is on is rejected: clearing cannot be withdrawn where markers can block. | #### `mcp_servers[]` — required and optional top-level fields @@ -309,33 +315,37 @@ Discriminated union keyed on `type`. `requiredFields[]` lists fields that MUST a | `basic` | `type`, `username`, `password` | HTTP basic auth. | | `authheaders` | `type`, `headers` | Array of `{key, value}` header pairs; each pair both required. | | `query_param` | `type`, `param_key`, `param_value` | Auth via URL query parameter. | -| `oauth` | `type`, `grant_type`, `scopes` | See the cross-field constraint below — `issuer`-OR-trio rule. | +| `oauth` | `type`, `grant_type` | See the cross-field constraint below — `issuer`-OR-trio rule. | | `cert` | `type`, `ca_cert` | PEM-encoded CA cert; used for custom-CA / mTLS / self-signed. | | `none` | `type` | Explicitly disabled auth. | #### OAuth variant — fields and the load-bearing cross-field rule -**Cross-field constraint** (verbatim from artifact): +**Cross-field constraints** (verbatim from artifact): > OAuth requires either `issuer` or all of `client_id`, `client_secret`, and `token_url` +> +> "token_endpoint_auth_method: client_secret_basic" requires `client_secret` In other words: a valid `oauth` block must satisfy one of these two shapes: - **DCR shape:** `issuer` is set. `client_id`, `client_secret`, and `token_url` may be omitted — the gateway discovers/registers them. - **Static-credentials shape:** `client_id` AND `client_secret` AND `token_url` are all set. `issuer` is not required. -Setting some but not all of `client_id` / `client_secret` / `token_url` without `issuer` is invalid. Both shapes still require `type: oauth`, `grant_type`, and `scopes`. +Setting some but not all of `client_id` / `client_secret` / `token_url` without `issuer` is invalid. Both shapes still require `type: oauth` and `grant_type` — `scopes` is optional (omit it, or `[]`, for providers that reject a `scope` parameter). -| Field | Required | Type | Target | Rationale (from artifact) | -|---|---|---|---|---| -| `grant_type` | yes (variant) | string | `sotw.oauth_config.grant_type` | Pick the OAuth grant the upstream server supports — `client_credentials` for machine-to-machine, `authorization_code` for delegated user auth. | -| `scopes` | yes (variant) | array | `sotw.oauth_config.scopes` | Scopes the gateway requests from the provider; match the provider's documented scope strings. | -| `issuer` | conditional | URL | `sotw.oauth_config.issuer` | Set to enable dynamic client registration — the gateway discovers token/authorize URLs and registers itself automatically. | -| `client_id` | conditional | string | `sotw.oauth_config.client_id` | The OAuth client identifier the upstream server issued you. Omit to let the gateway register dynamically (requires `issuer`). | -| `client_secret` | conditional | string, **secret** | `sotw.oauth_config.client_secret` | The OAuth client secret paired with `client_id`. Omit for public clients or when using DCR. | -| `token_url` | conditional | URL | `sotw.oauth_config.token_url` | The token endpoint the gateway posts to. Omit when `issuer` is set — DCR will discover it. | -| `authorization_url` | no | URL | `sotw.oauth_config.authorization_url` | The authorize endpoint for delegated user flows. Omit for non-interactive grants like `client_credentials`. | -| `redirect_uri` | no | URL | `sotw.oauth_config.redirect_uri` | Callback URL the upstream server redirects back to after user consent. | -| `pkce_enabled` | no | boolean | `sotw.oauth_config.pkce_enabled` | Enable for public clients where leaking the `client_secret` is a risk. | +| Field | Required | Type | Default | Target | Rationale (from artifact) | +|---|---|---|---|---|---| +| `grant_type` | yes (variant) | string | — | `sotw.oauth_config.grant_type` | Pick the OAuth grant the upstream server supports — `client_credentials` for machine-to-machine, `authorization_code` for delegated user auth. | +| `scopes` | no | array | `[]` (schema) | `sotw.oauth_config.scopes` | Scopes the gateway requests from the provider; match the provider's documented scope strings. Leave it out (or set `[]`) for providers that reject any `scope` parameter with `invalid_scope` — Docebo is one. With no `scope` parameter the provider applies its own default (RFC 6749 §3.3), usually the access configured on the client registration; confirm the issued token carries what the upstream server needs. On the Dynamic Client Registration path (`issuer` without `client_id`/`client_secret`) an omitted `scopes` registers the client with no scopes — the gateway's own DCR default scope does not apply to configs authored here. | +| `issuer` | conditional | URL | `not declared` | `sotw.oauth_config.issuer` | Set to enable dynamic client registration — the gateway discovers token/authorize URLs and registers itself automatically. | +| `client_id` | conditional | string | `not declared` | `sotw.oauth_config.client_id` | The OAuth client identifier the upstream server issued you. Omit to let the gateway register dynamically (requires `issuer`). | +| `client_secret` | conditional | string, **secret** | `not declared` | `sotw.oauth_config.client_secret` | The OAuth client secret paired with `client_id`. Omit for public clients or when using DCR. | +| `token_url` | conditional | URL | `not declared` | `sotw.oauth_config.token_url` | The token endpoint the gateway posts to. Omit when `issuer` is set — DCR will discover it. | +| `authorization_url` | no | URL | `not declared` | `sotw.oauth_config.authorization_url` | The authorize endpoint for delegated user flows. Omit for non-interactive grants like `client_credentials`. | +| `redirect_uri` | no | URL | `not declared` | `sotw.oauth_config.redirect_uri` | Callback URL the upstream server redirects back to after user consent. | +| `pkce_enabled` | no | boolean | `not declared` | `sotw.oauth_config.pkce_enabled` | Enable for public clients where leaking the `client_secret` is a risk. | +| `token_endpoint_auth_method` | no | enum | `not declared` | `sotw.oauth_config.token_endpoint_auth_method` | Defaults to `client_secret_post`, which sends `client_id`/`client_secret` in the request body. Set `client_secret_basic` for providers that require an HTTP Basic header and reject a body secret with `invalid_client` — Airtable is one. Ignored on the DCR path: when `issuer` drives dynamic client registration the gateway overwrites this with the method it registered under, so set it only alongside an explicit `client_id`/`client_secret`. | +| `omit_resource` | no | boolean | `not declared` | `sotw.oauth_config.omit_resource` | Escape hatch for providers that reject or mishandle the `resource` parameter on authorize, token-exchange, and refresh requests. | #### Non-OAuth variant fields — where each one lands @@ -372,7 +382,7 @@ Every field marked `secret: true` in the artifact. Emit a self-describing placeh - **`targetKind: platform`** — value is applied as a platform-side control at the named `platform.*` path rather than written to the gateway env file. - **`targetKind: sotwPath`** — value is written into the SOTW YAML at the named dotted path (e.g. `sotw.url`, `sotw.oauth_config.client_secret`). Read the `Target` column per field; do not infer a field's target from its section. - + diff --git a/dtwo/skills/dtwo-gateway-config/schema-reference.json b/dtwo/skills/dtwo-gateway-config/schema-reference.json index e1289c6..f85d81f 100644 --- a/dtwo/skills/dtwo-gateway-config/schema-reference.json +++ b/dtwo/skills/dtwo-gateway-config/schema-reference.json @@ -135,7 +135,7 @@ "schemaDefault": null, "deployDefault": null, "target": null, - "description": "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it." + "description": "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. A gateway using Dtwo authentication needs no credentials here — it gets its organization's platform-provisioned app — but prefer `clearing: {enabled: true}` over an empty block, so the block states what it does: an empty one arms only while `intent.enabled` is true and parks inert otherwise. `client_id` is only needed for a gateway trusting a customer-run IdP, and `redirect_uri` only for one the browser reaches at a different origin than its token audience. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it." }, { "name": "log_level", @@ -180,7 +180,7 @@ "fields": [ { "name": "enabled", - "required": true, + "required": false, "type": "boolean", "constraints": [], "enumValues": null, @@ -643,7 +643,7 @@ "deployDefault": [], "target": "SSRF_ALLOWED_NETWORKS", "description": "CIDR allowlist for outbound connections; JSON-encoded in the env file.", - "rationale": "Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts — prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface.", + "rationale": "Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts — prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface. Shared address space `100.64.0.0/10` (CGNAT — every Tailscale node address, for example) is blocked on every server registration and config import since ContextForge 1.0.7, above every other SSRF setting; a CIDR here that lies wholly inside `100.64.0.0/10` (e.g. `100.64.0.0/10` itself or your tailnet subnet) re-permits those addresses. Broad entries such as `100.0.0.0/8` or `0.0.0.0/0` do not.", "targetKind": "envVar" }, { @@ -704,11 +704,11 @@ { "path": "gateway.session_control", "title": "gateway.session_control", - "description": "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it.", + "description": "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. A gateway using Dtwo authentication needs no credentials here — it gets its organization's platform-provisioned app — but prefer `clearing: {enabled: true}` over an empty block, so the block states what it does: an empty one arms only while `intent.enabled` is true and parks inert otherwise. `client_id` is only needed for a gateway trusting a customer-run IdP, and `redirect_uri` only for one the browser reaches at a different origin than its token audience. The ceremony issuer is not configured here — it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it.", "fields": [ { "name": "client_id", - "required": true, + "required": false, "type": "string", "constraints": ["min length: 1", "matches `/^[\\x21-\\x7E]+$/`"], "enumValues": null, @@ -716,8 +716,22 @@ "schemaDefault": null, "deployDefault": null, "target": "SESSION_CONTROL_CLIENT_ID", - "description": "Public client id of the dedicated session-control OAuth app (native, PKCE, no client secret).", - "rationale": "Register a dedicated public client at your IdP for the clear ceremony (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client.", + "description": "Public client id of the dedicated session-control OAuth app (native, PKCE, no client secret). Optional on a gateway authenticating against Dtwo's Auth0: the platform provisions one per organization and renders it at deploy. An explicit value always wins.", + "rationale": "Leave unset on a gateway using Dtwo authentication. Set it only when the gateway trusts your own IdP: the ceremony app must live in the IdP that issues the gateway's inbound tokens, so register a dedicated public client there (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client.", + "targetKind": "envVar" + }, + { + "name": "redirect_uri", + "required": false, + "type": "string", + "constraints": ["min length: 1"], + "enumValues": null, + "audience": "user", + "schemaDefault": null, + "deployDefault": null, + "target": "SESSION_CONTROL_REDIRECT_URI", + "description": "Callback URL the browser clear ceremony redirects to, overriding the one the gateway derives from its own token audience. Must be an absolute `https://` URL (`http://` only on localhost, 127.0.0.1, or [::1]). Optional: leave it unset unless the browser reaches the gateway at a different origin than its audience. An explicit value always wins, and the platform allow-lists it verbatim on the IdP application.", + "rationale": "Leave unset in almost all cases — the gateway derives `/session-control/clear/callback` and the platform registers that. Set it when a reverse proxy or split-horizon DNS puts the browser on a different origin than the audience: give the URL the browser can actually reach, at the root path (`/mcp/*` routes to the streamable-HTTP handler, which rejects browser GETs).", "targetKind": "envVar" }, { @@ -743,6 +757,12 @@ { "message": "While clearing is armed, `gateway.authentication` must be enabled with `jwks_info` — the ceremony binds every clear to the authenticated caller identity, so an unauthenticated inbound leg has nothing to bind." }, + { + "message": "A gateway that authenticates against an IdP other than Dtwo's Auth0 must set `client_id`: the platform provisions a ceremony app only in its own tenant, and the deploy fails rather than arming a gateway whose ceremony has no application to authenticate against." + }, + { + "message": "`redirect_uri`, when set, replaces the callback the gateway would derive from the first entry of `jwt_audience`, and is the URL the platform allow-lists on the IdP application. Unset, ordering within a comma-separated `jwt_audience` decides the callback." + }, { "message": "While clearing is armed, `jwt_issuer` must be a normalized HTTPS URL (it becomes the ceremony issuer via `SESSION_CONTROL_ISSUER`) and `jwt_audience` must not be blank." } @@ -764,7 +784,7 @@ "deployDefault": null, "target": "platform.session_control.clearing.enabled", "description": "Arm human-gated clearing of session intent and markers. Unset follows `gateway.intent.enabled`. `false` while intent is enabled is a deploy error (clearing cannot be withdrawn where markers can block).", - "rationale": "Leave unset in almost all cases — clearing arms automatically wherever intent capture is on and this block is configured. Set `true` explicitly on a gateway that runs marker-writing policies WITHOUT intent capture, which otherwise has no targeted clear path and can only wait for a marker to expire.", + "rationale": "Write `true` whenever you want clearing. It is only strictly *required* on a gateway that runs marker-writing policies WITHOUT intent capture — with intent capture on, the block arms on its own — but stating it makes the block say what it does rather than leaving that to `gateway.intent.enabled`, and it keeps clearing armed if intent capture is later turned off. `false` while intent capture is on is rejected: clearing cannot be withdrawn where markers can block.", "targetKind": "platform" } ] @@ -915,7 +935,7 @@ { "name": "oauth", "path": "mcp_servers[].authentication (oauth)", - "requiredFields": ["type", "grant_type", "scopes"] + "requiredFields": ["type", "grant_type"] }, { "name": "cert", @@ -1193,6 +1213,20 @@ "targetKind": "sotwPath", "secret": true }, + { + "name": "token_endpoint_auth_method", + "required": false, + "type": "enum", + "constraints": [], + "enumValues": ["client_secret_basic", "client_secret_post"], + "audience": "user", + "schemaDefault": null, + "deployDefault": null, + "target": "sotw.oauth_config.token_endpoint_auth_method", + "description": "How the client authenticates to the token endpoint.", + "rationale": "Defaults to `client_secret_post`, which sends `client_id`/`client_secret` in the request body. Set `client_secret_basic` for providers that require an HTTP Basic header and reject a body secret with `invalid_client` — Airtable is one. Ignored on the DCR path: when `issuer` drives dynamic client registration the gateway overwrites this with the method it registered under, so set it only alongside an explicit `client_id`/`client_secret`.", + "targetKind": "sotwPath" + }, { "name": "token_url", "required": false, @@ -1251,16 +1285,16 @@ }, { "name": "scopes", - "required": true, + "required": false, "type": "array", - "constraints": ["min length: 1"], + "constraints": [], "enumValues": null, "audience": "user", - "schemaDefault": null, + "schemaDefault": [], "deployDefault": null, "target": "sotw.oauth_config.scopes", - "description": "OAuth scopes requested.", - "rationale": "Scopes the gateway requests from the provider; match the provider's documented scope strings.", + "description": "OAuth scopes requested. Optional: omitted or empty, the gateway sends no `scope` parameter to the provider.", + "rationale": "Scopes the gateway requests from the provider; match the provider's documented scope strings. Leave it out (or set `[]`) for providers that reject any `scope` parameter with `invalid_scope` — Docebo is one. With no `scope` parameter the provider applies its own default (RFC 6749 §3.3), usually the access configured on the client registration; confirm the issued token carries what the upstream server needs. On the Dynamic Client Registration path (`issuer` without `client_id`/`client_secret`) an omitted `scopes` registers the client with no scopes — the gateway's own DCR default scope does not apply to configs authored here.", "targetKind": "sotwPath" }, { @@ -1277,6 +1311,20 @@ "rationale": "Enable for public clients where leaking the `client_secret` is a risk.", "targetKind": "sotwPath" }, + { + "name": "omit_resource", + "required": false, + "type": "boolean", + "constraints": [], + "enumValues": null, + "audience": "user", + "schemaDefault": null, + "deployDefault": null, + "target": "sotw.oauth_config.omit_resource", + "description": "Omit the RFC 8707 resource parameter from OAuth authorize/token requests.", + "rationale": "Escape hatch for providers that reject or mishandle the `resource` parameter on authorize, token-exchange, and refresh requests.", + "targetKind": "sotwPath" + }, { "name": "oauth_quirks", "required": false, @@ -1362,6 +1410,9 @@ "crossFieldConstraints": [ { "message": "OAuth requires either \"issuer\" or all of \"client_id\", \"client_secret\", and \"token_url\"" + }, + { + "message": "\"token_endpoint_auth_method: client_secret_basic\" requires \"client_secret\"" } ] }, @@ -1440,6 +1491,15 @@ { "key": "CACHE_TYPE" }, + { + "key": "CPEX_CONTROL_TELEMETRY_DB_ENABLED" + }, + { + "key": "CPEX_CONTROL_TELEMETRY_ENABLED" + }, + { + "key": "CSRF_ENABLED" + }, { "key": "D2_TENANT_ID" }, @@ -1508,6 +1568,9 @@ "key": "LOG_LEVEL", "schemaPath": "gateway.log_level" }, + { + "key": "MCPGATEWAY_A2A_ENABLED" + }, { "key": "MCPGATEWAY_ADMIN_API_ENABLED" }, @@ -1572,6 +1635,13 @@ { "key": "SESSION_CONTROL_ISSUER" }, + { + "key": "SESSION_CONTROL_REDIRECT_URI", + "schemaPath": "gateway.session_control.redirect_uri" + }, + { + "key": "SOTW_DELETE_POLICY" + }, { "key": "SOTW_ENABLED", "schemaPath": "gateway.sotw.enabled" diff --git a/dtwo/skills/dtwo-gateway-policy/SKILL.md b/dtwo/skills/dtwo-gateway-policy/SKILL.md index 8c4bcc4..71fb94b 100644 --- a/dtwo/skills/dtwo-gateway-policy/SKILL.md +++ b/dtwo/skills/dtwo-gateway-policy/SKILL.md @@ -125,6 +125,8 @@ Markers are session-state flags that one policy writes and other policies read t | `dtwo-update-marker` | Update mutable fields on a customer-tier marker (`description`, `tags`, `minimumTtlSeconds`) | | `dtwo-delete-marker` | Delete a customer-tier marker. Platform-managed entries cannot be deleted | +What you register here is also visible to policy Rego as OPA data at `data.dtwo.intent_registry` — see The registry as policy data. + ### Intent Registry Tools (conditional — feature-gated) > **Availability gate — read this before surfacing anything about intents.** The intent tools below are only registered when the Dtwo MCP server is deployed with `enable_intent_tools: true`. **Marker tools (above) are always available; intent tools are not.** Before mentioning intent capture, intent registries, transitions, or intent/marker compatibility to the user, confirm the relevant `dtwo-*-intent*` tools are actually present in your available tool list. **If they are absent, the server is not configured for intent capture — do not present intent capture, the intent registry, transitions, or compatibility to the user, and do not attempt to call these tools.** Treat this subsection and the "Intent Capture" section below as inert in that case. Markers work fully without intent capture, so continue to use them normally. @@ -444,7 +446,7 @@ After publishing, call `dtwo-set-gateway-pipelines` again with `policyVersion: 1 ## Managing Markers -Markers are session-state flags that policies write and later policies read to gate on. They give the gateway a shared, tenant- and user-scoped, TTL-bounded "notepad" that survives across tool calls and across upstream MCP servers — a marker written during a Slack call is visible during a later Jira call for the same user (until its TTL expires). Use them to compose small single-purpose policies that signal to each other without shared code: a **writer** policy stamps a marker when it observes something (PII in a response, a production resource touched), and a **reader** policy on a different tool/pipeline/server gates on it. +Markers are session-state flags that policies write and later policies read to gate on. They give the gateway a shared, tenant- and user-scoped, TTL-bounded "notepad" that survives across tool calls and across upstream MCP servers — a marker written during a Slack call is visible during a later Jira call for the same user (until it expires or is cleared). Use them to compose small single-purpose policies that signal to each other without shared code: a **writer** policy stamps a marker when it observes something (PII in a response, a production resource touched), and a **reader** policy on a different tool/pipeline/server gates on it. Marker tools are always available (they do not require `enable_intent_tools`). The full lifecycle — register, author writer + reader, attach, deploy — runs through this skill plus `dtwo-policy-rego` for the Rego. The Rego authoring patterns (emitting `session_writes["marker::"]`, walking `input.context.session.policies` to read, and the `writableKeySchema` gotchas) live in the companion `dtwo-policy-rego` instructions — load that skill for the writer/reader bodies. @@ -452,7 +454,7 @@ Marker tools are always available (they do not require `enable_intent_tools`). T **Start simple — the minimal marker is a boolean flag.** A writer stamps `marker::` when it observes a condition; a reader denies (or transforms) whenever that key is present. Presence *is* the signal — no value semantics needed. That flag pattern (the PII example used throughout this section) is the recommended starting point; reach for value-carrying markers only when a flag won't do. Counters and other read-modify-write markers are possible but more involved — a self-incrementing writer has to read its own prior value and re-emit on every call, which keeps refreshing (pinning) the TTL — so they aren't a good first marker. -**Know these limits before you design:** no runtime inspection (verify behaviorally), no manual clearing (a marker lifts only on TTL expiry), and tenant+user scope (state survives reconnects/new sessions until TTL). Full detail — and why each bites — is under **Marker constraints today** below. +**Know these limits before you design:** no runtime inspection (verify behaviorally), tenant+user scope (state survives reconnects and new sessions until it lifts), and no agent-side clearing — a marker lifts either when its TTL expires or when a **person** approves a clear in a browser, which an agent can request but cannot complete. Full detail — and why each bites — is under **Clearing a marker** and **Marker constraints today** below. ### Registering a marker @@ -503,6 +505,28 @@ dtwo-add-policy( **Deploy-time validator.** The deploy hard-rejects if any attached policy declares a `writableKeySchema` marker key that isn't in the registry, reporting which key is unregistered. This is separate from the key's structural validation (allowed characters, reserved prefixes), which the backend applies when the policy is saved — the registry-existence check runs at deploy time. Register the marker *before* attaching a policy that writes it. +### Clearing a marker + +A marker has two exits: its TTL expires, or a **person approves a clear**. The second one is the fast path, and it is the one your deny reasons should offer first — a marker set at the start of an hour-long TTL can otherwise block someone for the rest of that hour over a condition they have already dealt with. + +**An agent can request a clear; it cannot complete one.** Requesting returns a link to open in a browser and nothing an agent can act on. The person opens it, signs in interactively at the identity provider (a fresh login, even if they are already signed in), picks what to clear from a list the gateway builds, and confirms. Everything after the request happens in a browser, authenticated as a human. + +**Why the person is in the loop.** A marker is worth exactly as much as the agent's inability to remove it. If the agent a marker constrains could also lift it, the marker would constrain nothing — it would be a speed bump with a documented way around, and every policy built on markers would inherit that. So the human step is not a convenience tax on the flow; it **is** the control. What the ceremony produces is evidence: a named person, freshly authenticated at that moment, explicitly authorized *this* clear of *these* specific values. That is also why the flow declines to be convenient — no arguments, so the agent cannot choose the target; one interactive login per clear, so an approval cannot be batched, reused, or replayed; and the same identity as the caller, so it cannot be handed to whoever happens to be at the keyboard. + +**What that means for how you use it.** Never offer a clear as a way around a policy decision. If a block is correct, the answer is to stop and explain it — not to reach for the clear. A clear is appropriate when the state has outlived its purpose: the condition that raised the marker has been dealt with, and **the person**, never the agent, judges that it has. An agent that reflexively requests a clear on every denial is doing the exact thing the human gate exists to prevent, and once clearing is armed, every request is recorded whether or not anyone approves it (the unarmed refusal returns before anything is minted, so it emits no event). + +What the shape means when you design a marker or word a deny reason: + +- **The clear is not a management tool.** It arrives as an argument-less tool on the platform tool surface the gateway injects — `clear_markers`, alongside `clear_intent` and `set_intent` (on the wire, `dtwo-platform-intent-clear-markers` — the federated name is hyphenated throughout). There is no `dtwo-*` call that lifts a marker, and nothing to declare per policy. +- **No arguments, deliberately.** The agent cannot name a key, so it cannot choose the target. The confirm page enumerates what is actually live and unexpired in the caller's scope, and the person selects from that list. +- **The approver must be the same identity as the caller.** The browser login is matched against the identity the agent is calling with, so a person clears their own session state — not another user's. One login authorizes exactly one clear. +- **Markers and intent clear separately.** `clear_markers` offers every live `marker:` instance in scope, and flags one that is held by more than one writer — clearing a single holder leaves the marker standing, so each holder is acknowledged on its own. `clear_intent` only ever offers the platform-captured intent. An approved marker clear can never drop the intent, and the reverse holds too. +- **It is armed per gateway.** Clearing requires the `gateway.session_control` block in the gateway config, and that block should say so explicitly — `clearing: {enabled: true}` (see `dtwo-gateway-config`). Left implicit it arms only while intent capture is on and parks inert otherwise — a shape that leaves marker policies enforcing with no targeted way out of a marker. Unavailable looks two different ways: where clearing is not armed the platform clear tool may be **absent from your tool list entirely**, so there is nothing to call and no refusal to read; where it is present but unarmed, the request returns a readable "not configured on this gateway" refusal that points at the TTL. Handle both rather than assuming the flow is available. It fails closed throughout: nothing is ever half-cleared. +- **Confirm before requesting.** The request is a state change with a person on the other end of it — ask first, as you would before any state-changing call, and never fire one speculatively to "reset" a session. +- **The request, the authorization and the commit are each recorded** in the gateway's event stream, so a clear is answerable after the fact: who approved it, when, and which instances went. + +**Wording deny reasons for this.** A reader policy's `reason` is what the blocked person actually sees, so it should name the fast exit first and keep the TTL as the fallback — see the deny-reason guidance in `dtwo-policy-rego` → Session State & Markers → Reading a marker. + ### Verifying a marker pipeline Markers can't be verified the way a single policy can — there is no tool to read active markers (see Marker constraints today), so verification is **behavioral and order-dependent**: a marker does nothing until its writer fires, and its effect is only visible through the reader's decision. The tenant+user scope (below) is what makes the negative case tricky, so mind it: @@ -510,9 +534,9 @@ Markers can't be verified the way a single policy can — there is no tool to re 1. **Confirm the deploy and attachment** as for any policy — poll `dtwo-get-deployment` to `completed`, then `dtwo-get-gateway-pipelines` to confirm both the writer and the reader landed at the expected step indexes with the version pins you intended. 2. **Trigger the writer first.** Make the tool call that satisfies the writer's condition (e.g. a response containing PII). This is what stamps the marker — nothing is active until the writer fires. 3. **Then exercise the reader** (as the same user). Confirm the reader's guarded tool now denies (or transforms) as intended. The marker stays active until its TTL expires. -4. **Confirm the negative case with a clean marker.** Either use a **short TTL and wait for it to expire**, or test as a **different user** who hasn't triggered the writer — then the reader's tool should succeed, proving it blocks only when the marker is active. Reopening the session as the *same* user does **not** clear the marker (tenant+user scope), so that is not a valid negative test. +4. **Confirm the negative case with a clean marker.** Use a **short TTL and wait for it to expire**, test as a **different user** who hasn't triggered the writer, or — on a gateway with clearing armed — **request a clear and approve it** (see Clearing a marker). Then the reader's tool should succeed, proving it blocks only when the marker is active. Reopening the session as the *same* user does **not** clear the marker (tenant+user scope), so that is not a valid negative test. -**Tip — validate with a short TTL.** A production-length TTL (say an hour) makes iterating painful: a marker stamped in one test stays set for that user until it expires and masks the next attempt. During validation, set the writer's `writableKeySchema.ttlSeconds` short (e.g. 30–60s) so it clears on its own between iterations. (Since the floor isn't enforced, a short `ttlSeconds` deploys regardless; set the marker's `minimumTtlSeconds` to match via `dtwo-update-marker` so the registry still reflects intent.) Once validated, raise the writer's `ttlSeconds` to the production length with `dtwo-update-policy` (and `minimumTtlSeconds` to match), then republish/redeploy. +**Tip — validate with a short TTL.** A production-length TTL (say an hour) makes iterating painful: a marker stamped in one test stays set for that user until it expires and masks the next attempt. During validation, set the writer's `writableKeySchema.ttlSeconds` short (e.g. 30–60s) so it clears on its own between iterations. (Since the floor isn't enforced, a short `ttlSeconds` deploys regardless; set the marker's `minimumTtlSeconds` to match via `dtwo-update-marker` so the registry still reflects intent.) Once validated, raise the writer's `ttlSeconds` to the production length with `dtwo-update-policy` (and `minimumTtlSeconds` to match), then republish/redeploy. (A short TTL is about **iterating quickly**, not about the only way out of a marker — approving a clear resets one on demand, but it takes a browser round trip each time, so the short TTL is still the better loop for repeated tests.) Watch for these: @@ -532,8 +556,8 @@ Skipping a step makes the next deploy fail (a policy still claims to write a mar ### Marker constraints today - **No "list active markers" tool.** `dtwo-list-markers` returns the registry *vocabulary* (the markers that are defined), not which markers are currently set on a given session. A policy can read active markers at evaluation time via `input.context.session.policies` (that's how reader policies work), but there is no MCP tool to query a session's live marker state on demand. -- **No "clear marker" tool.** Markers lift on their own when their TTL expires; there is no MCP tool to unset one. To recover from a marker that is blocking a user, wait out the TTL — a new session for the same user does **not** clear it (state is scoped to tenant + user, not per connection). -- **Multiple writers land in separate per-writer slots.** If two policies declare and emit the same marker key, each write lands under its own writer UID; readers get "any-writer" semantics by walking `session.policies.*`. Prefer one canonical writer per marker. +- **No agent-side clear — by design, not by omission.** There is no management tool that unsets a marker, and no `dtwo-*` call that lifts one, because state an agent can remove does not constrain that agent. A marker lifts on TTL expiry, or through the human-approved clear flow described under **Clearing a marker** — which the agent can only *start*. Reopening the session as the same user does **not** clear it (state is scoped to tenant + user, not per connection). +- **Multiple writers land in separate per-writer slots.** If two policies declare and emit the same marker key, each write lands under its own writer UID; readers get "any-writer" semantics by walking `session.policies.*`. Prefer one canonical writer per marker. Any-writer is the right default for a marker that *blocks* something — but a marker that *grants* a capability must instead pin its writer's UID, or any policy able to write that key can mint the grant (see `dtwo-policy-rego` → Markers that grant). ## Intent Capture (conditional — feature-gated) @@ -554,14 +578,14 @@ Two policies do the enforcement: **These are platform-managed policies — end users do not author, attach, copy, or modify them, and you should not offer to.** They are **automatically injected** when intent capture is enabled (`gateway.intent.enabled`); the platform owns their bodies and wiring (the auto-injected in-container intent server, internal UIDs), and their Rego may not be visible to users. If a user asks to write or change intent-capture Rego, decline and point them at the platform-managed feature rather than reconstructing it. The only intent surface users drive is the **registry** — the intent vocabulary, transitions, and marker compatibility (below), when the tools are enabled. -**Gating a tenant policy on the current intent** is allowed, though — a user policy may *read* the captured intent to decide access (e.g. "only allow this tool under the `internal:debug`/`internal:explore` intents" — compare against the full FQIDs, not the short form). When it does, it must read intent **only** through the platform helper `data.dtwo.lib.intent_match.*`, never via a direct `input.context.session.policies` read (a raw read is spoofable and couples to internals). The category values to compare against are the intent FQIDs from `dtwo-list-intents`. The Rego belongs to the companion `dtwo-policy-rego` skill — see its Intent-capture policies → Reading the session intent. +**Gating a tenant policy on the current intent** is allowed, though — a user policy may *read* the captured intent to decide access (e.g. "only allow this tool under the `internal:debug`/`internal:explore` intents" — compare against the full FQIDs, not the short form). When it does, it must read intent **only** through the platform helper `data.dtwo.lib.intent_match.*`, never via a direct `input.context.session.policies` read (a raw read is spoofable and couples to internals). The category values to compare against are the intent FQIDs from `dtwo-list-intents`. And it may **decide** on the intent but must **never return it** — do not interpolate the intent, or its caller-supplied `description`, into a deny `reason` or a transform; name the rule that fired instead. The Rego belongs to the companion `dtwo-policy-rego` skill — see its Intent-capture policies → Reading the session intent. ### Intent transitions (discoverability) Moving between intents is itself governed, and a `set_intent` can be **denied for two independent reasons** — in both cases the current intent stays unchanged. This surprises authors mid-test: - **`intent_change_disallowed` — transition rules.** The registry forbids that from→to move. Each entry carries `transitionsFromMode` (`ALL` / `RESTRICTED` / `NONE`) and, when `RESTRICTED`, an `allowedTransitionsFrom` list of the intents you may arrive *from*. Inspect it with `dtwo-list-intents` (or `dtwo-list-intent-transitions` when present). To reach a restricted target you may need an intermediate hop (e.g. `explore → debug → deploy` when `deploy` only allows arrival from `debug`/`review`/`incident_response`). -- **`intent_marker_incompatible` — an active marker blocks the target.** If a currently-set marker is registered incompatible with the intent you're switching *to*, the capture policy denies the `set_intent` (see Intent/marker compatibility below). So a marker stamped earlier in the session can make an otherwise-legal transition fail — and because markers only lift on TTL expiry (no clear tool), the transition stays blocked until the marker ages out. If a `set_intent` fails and the transition rules allow it, check for an active incompatible marker. +- **`intent_marker_incompatible` — an active marker blocks the target.** If a currently-set marker is registered incompatible with the intent you're switching *to*, the capture policy denies the `set_intent` (see Intent/marker compatibility below). So a marker stamped earlier in the session can make an otherwise-legal transition fail. If a `set_intent` fails and the transition rules allow it, check for an active incompatible marker: the way out is to clear that marker (**Clearing a marker** above) or wait for it to expire — the transition stays blocked until one of the two happens. Both are distinct from any tenant gate you author on the intent value. @@ -596,6 +620,37 @@ Example: once `marker:acme:pii_detected` is set, a `set_intent` to `incident_res **Set-time enforcement only.** The check runs at `set_intent` time. A marker raised *after* an intent is set does **not** retroactively invalidate the current intent. Markers accumulate; intents are validated at the decision point. Tell users this plainly so they don't design around a symmetric re-check that doesn't exist. +## The registry as policy data — `data.dtwo.intent_registry` + +> **Not gated.** Despite the name, this document ships to every gateway and always carries `markers[]`, so this section applies whether or not intent capture is enabled. + +The vocabulary you register is not only a management surface: it is shipped into **every** gateway's policy bundle as OPA base data at `data.dtwo.intent_registry`, in the same atomic deploy as the Rego that reads it. A policy can therefore consult the registry at decision time instead of hard-coding the vocabulary. The document is always present and always fully populated — an empty tenant yields empty arrays, never a missing object — so a policy only handles empty lists, never an undefined registry. + +```json +{ + "intents": [ + { "id": "acme:deploy", "description": "…", + "aliases": ["ship"], + "transitions_from": ["acme:review"] } + ], + "markers": [ + { "id": "marker:acme:pii_detected", "description": "…", + "minimum_ttl_seconds": 3600 } + ], + "compatibility": [ + { "intent": "acme:deploy", "excluded_marker": "marker:acme:pii_detected" } + ] +} +``` + +- Entries are keyed by **FQID** (`id`) — the same `name` the registry tools return. No UIDs appear in the data document. +- `markers[]` is there regardless of whether intent capture is enabled, so a marker-only gateway can still read it (e.g. to surface a marker's registered `description` or `minimum_ttl_seconds` in a message). +- `transitions_to` / `transitions_from` are **omitted when the move is unrestricted** and `[]` when it is locked — treat a missing field as "no restriction", not as an error. `aliases` is simply omitted when the entry has none. +- It is the tenant's whole vocabulary, not a slice for this gateway: an entry appearing here does not mean a policy on this gateway writes or reads it. +- Registry edits reach a gateway on its **next policy deploy**, not immediately — the data file rides the same bundle as the policies. + +The Rego for reading it belongs to `dtwo-policy-rego`; the platform's own intent enforcement reads this same document. + ## Limitations - This skill cannot author or modify Rego policies — see the companion `dtwo-policy-rego` instructions diff --git a/dtwo/skills/dtwo-policy-rego/SKILL.md b/dtwo/skills/dtwo-policy-rego/SKILL.md index 1af1a4b..17e6046 100644 --- a/dtwo/skills/dtwo-policy-rego/SKILL.md +++ b/dtwo/skills/dtwo-policy-rego/SKILL.md @@ -984,7 +984,7 @@ allow := false if { _pii_active } -reason := "PII was detected earlier in this session; outbound Slack sends are blocked. Wait for the marker TTL to expire." if { +reason := "PII was detected earlier in this session; outbound Slack sends are blocked. To lift the block now, ask your agent to request a session clear and approve it in your browser; otherwise it lifts when the marker expires." if { lower(input.resource.name) == "slack-mcp-slack-send-message" _pii_active } @@ -992,7 +992,267 @@ reason := "PII was detected earlier in this session; outbound Slack sends are bl - The walk-all-writers pattern (`some writer_uid; input.context.session.policies[writer_uid][key]`) is "present under *any* writer is truthy." To trust only a specific writer, filter on `writer_uid == ""`. - **This pattern is for reading *marker* keys only.** Do **not** use it — or any direct `input.context.session.policies` read — to read the platform **intent** (see Intent-capture policies → Reading the session intent). "Present under any writer" is exactly wrong for intent: a tenant policy could stamp an intent-shaped value under its own writer slot and a walk-all-writers read would honour it, spoofing the session intent. Read intent only through the platform helper, which is pinned to the trusted intent-capture slot. -- Deny reasons are user-visible — explain what to do about the block (e.g. "wait for the marker TTL to expire"). Avoid "start a new session": marker state is scoped to tenant + user and survives reconnecting, so a new session for the same user won't clear it. +- **Deny reasons are user-visible — give the path out, fastest first.** State what happened and what the person can do about it. A marker has two exits, and they are not equal: a **human-approved clear** lifts it in under a minute, and **TTL expiry** lifts it eventually. Offer the clear first and keep TTL as the fallback — a reason that mentions only the TTL tells someone to wait an hour for something they could have resolved immediately. Phrase it so it reads correctly either way ("ask your agent to request a session clear … otherwise it lifts when the marker expires"). Address the ask to the person's agent, not the person: the only way to start a clear is the platform tool call, so someone reading your reason in a log or the Hub has nothing to click. Keep the TTL half of the sentence even so — clearing is armed per gateway, and where it is not armed the clear tool may be missing from the agent's tool list altogether, or present but answering with a readable "not configured on this gateway" refusal; either way the TTL is the exit that still holds. Word it as a recovery the person authorizes, not as a way around the decision — the clear needs their explicit approval in a browser precisely so an agent cannot use it to shrug off a block (see `dtwo-gateway-policy` → Clearing a marker for the mechanics and the reasoning). +- **Avoid "start a new session"** — marker state is scoped to tenant + user and survives reconnecting, so a new session for the same user won't clear it. +- **Never build a reason out of the session intent.** A reason may say *that* the current intent failed a gate; it must not carry the intent itself — do not interpolate `current_intent(input)` or its `description` into `reason` or into a transform. Name the rule that fired instead. Full rule under Intent-capture policies → Reading the session intent. + +### Reading the registry (`data.dtwo.intent_registry`) + +The marker (and, where enabled, intent) vocabulary is shipped into every gateway's policy bundle as OPA base data at `data.dtwo.intent_registry`, in the same atomic deploy as the Rego — so a policy can consult the registry at decision time instead of hard-coding what it knows about a key. The document is always defined and always fully shaped (empty arrays for an empty tenant), so a read needs no "registry missing" branch; a *specific* entry can of course be absent. + +The reader from **Reading a marker** above, with its message sourced from the registry instead of a string pasted into the policy: + +```rego +package acme.ingress.pii_gate + +import future.keywords.if +import future.keywords.in + +default allow := true + +_key := "marker:acme:pii_detected" + +_pii_active if { + some writer_uid + input.context.session.policies[writer_uid][_key] +} + +# The registered description, so the message tracks the registry rather +# than a string pasted into the policy. The `default` is load-bearing: +# without it an unregistered key leaves the whole `reason` undefined. +default _registered_description := "a sensitive-data marker is set on this session" + +_registered_description := d if { + some m in data.dtwo.intent_registry.markers + m.id == _key + d := m.description +} + +allow := false if { + lower(input.resource.name) == "slack-mcp-slack-send-message" + _pii_active +} + +reason := sprintf("Blocked: %s. To lift the block now, ask your agent to request a session clear and approve it in your browser; otherwise it lifts when the marker expires.", [_registered_description]) if { + lower(input.resource.name) == "slack-mcp-slack-send-message" + _pii_active +} +``` + +- Entries are keyed by **FQID** (`id`) — `marker::` for markers, `:` for intents. No UIDs appear in the data document. +- `markers[]` carries `id`, `description` and `minimum_ttl_seconds`; `intents[]` carries `id`, `description`, and optionally `aliases` / `transitions_to` / `transitions_from`; `compatibility[]` carries `intent` and `excluded_marker`. A transitions field is **omitted when unrestricted** and `[]` when locked — treat missing as "no restriction". +- Registry text is authored by your own admins, so it is safe to surface in a reason — unlike the session intent, which must never be echoed (see Reading the session intent). +- **Give any registry-derived string a fallback** — the `default` line above is not decoration. A lookup that finds nothing is *undefined*, not empty, and an undefined term makes the whole `reason` undefined: the call still denies, but the person sees no message at all. A `default` on the lookup rule fixes it, as does a second `reason` rule that omits the lookup. +- Registry edits reach the gateway on its **next policy deploy**, not immediately. + +### Markers that grant (the allow direction) + +Every marker example above **takes a capability away**: something happened, so something is +now blocked. A marker can just as well **give one** — the tool is off by default and a +marker turns it on, so the agent *earns* access by doing the right thing first instead of +holding a standing privilege. "You may not comment on a ticket you have not read" and "you +may not delete a file you have not copied" are the same shape. + +The mechanism is identical. Four things change, and the first is a security property rather +than a style preference. + +**Pin the writer's UID — do not walk all writers.** The walk-all-writers read is correct for +a deny marker: more emitters can only make the gate more cautious. Invert the marker and it +inverts too — *any* policy that can write that key now mints the grant. As the caveat under +**Marker vs. general session key** says, session state is not access-isolated, so a marker +that unlocks something makes its writer an authorization decision point: + +```rego +# Deny direction — "did anyone see PII?" Any writer may answer. +_pii_active if { + some writer_uid + input.context.session.policies[writer_uid]["marker:acme:pii_detected"] +} + +# Allow direction — "did THE reviewer policy record this?" Exactly one writer may answer. +_reviewed_keys := object.get( + object.get(object.get(input.context.session, "policies", {}), _writer_uid, {}), + ["marker:acme:issue_read", "issue_keys"], + [], +) +``` + +**The gate now denies on absence, so read fail-closed.** *Marker Rego gotchas* below says to +structure gates so the marker's **presence** denies — that is the deny direction. A grant +gate is the mirror image: absent state must mean *no grant*, and therefore deny. Reach every +field through nested `object.get` with defaults so a missing session, a missing writer slot +or an absent `args` object all resolve to "not granted" rather than leaving the rule +undefined. + +**Scope it to the resource, and put the id in the value.** A grant is rarely "you may +comment"; it is "you may comment *on this issue*". The id cannot go in the key — a +`writableKeySchema` enumerates key names under `additionalProperties: false`, so a +per-resource key is impossible. Carry it in the **value** and compare against the argument of +the call being judged: + +```rego +package acme.ingress.comment_requires_read + +import future.keywords.if +import future.keywords.in + +# Allow broadly, deny the one narrow case — never `default allow := false` on a +# gateway that also fronts management tools. +default allow := true + +# The paired writer policy's UID. Replace after creating that policy; while the +# placeholder stands no slot matches, so every comment denies — an unconfigured +# pair fails closed and says so. +_writer_uid := "REPLACE-WITH-WRITER-POLICY-UID" + +_reviewed_keys := object.get( + object.get(object.get(input.context.session, "policies", {}), _writer_uid, {}), + ["marker:acme:issue_read", "issue_keys"], + [], +) + +_requested := object.get(object.get(input.payload, "args", {}), "issueIdOrKey", "") + +_has_read if { + is_string(_requested) + _requested != "" + _requested in _reviewed_keys +} + +allow := false if { + lower(input.resource.name) == "atlassian-addcommenttojiraissue" + not _has_read +} + +reason := "Commenting on an issue requires that this session has read that same issue first. Read it, then retry; reading a different issue does not unlock this one." if { + lower(input.resource.name) == "atlassian-addcommenttojiraissue" + not _has_read +} +``` + +**Take the id from the response, not the request.** Write the marker on **egress**. A +`tool_post_invoke` payload is `{name, text}` and carries **no arguments**, which sounds like +a limitation and is the point: the id comes from what the upstream actually returned, so a +caller cannot mark a resource it never fetched, and a call that failed upstream grants +nothing. This does require a tool whose response names its resource — a Jira issue and a +Drive file's metadata both do; a raw content read may not, in which case the grant cannot be +resource-scoped on that tool. + +#### Accumulating across calls + +A grant marker usually holds a *set* — every issue read so far. The writer reads its own +prior value and writes the extended list, so it needs **its own UID**: + +```rego +package acme.egress.issue_read_writer + +import future.keywords.if +import future.keywords.in + +default allow := true + +# THIS policy's own UID — session writes are keyed by writer, so accumulating +# means reading back at our own slot. Two-step: create, then update (see below). +_self_uid := "REPLACE-WITH-THIS-POLICY-UID" + +# Bind the whole response object, then derive from it — other rules below +# need more than the id. +_issue := obj if { + lower(input.resource.name) == "atlassian-getjiraissue" + some text in input.payload.text + obj := json.unmarshal(text) + is_string(obj.key) +} + +# The id comes from the response body, never from the caller's arguments. +_key := _issue.key + +_slot := object.get(object.get(input.context.session, "policies", {}), _self_uid, {}) +_prior := [x | some x in object.get(_slot, ["marker:acme:issue_read", "issue_keys"], []); is_string(x)] + +# Deduplicate and keep the value bounded — see the cap below. +_deduped := sort({k | some k in array.concat(_prior, [_key])}) +_keys := array.slice(_deduped, max([0, count(_deduped) - 12]), count(_deduped)) + +session_writes["marker:acme:issue_read"] := {"issue_keys": _keys} if { _key } +``` + +Three things that trip people up here: + +- **A policy cannot know its own UID until it exists.** Create it with the placeholder, take + the UID from the `dtwo-add-policy` response, then `dtwo-update-policy` with the real value. + The shipped intent-capture policies use exactly this two-step. +- **Writes apply *after* the evaluation that emitted them.** A policy never sees the write it + is currently making, so it cannot read-then-write a value in one decision. It *does* see + writes committed by **earlier evaluations of the same request** — an earlier pipeline step, + or ingress when the read happens on egress — as well as everything from previous requests. + That is what makes "read A, read B, then act on A" work, and what lets an ingress step mark + a call that a later step gates on. +- **Keep the value bounded.** A value is capped at **1 KB**, one decision may write at most + **16 keys**, and a session holds at most **64 keys** (and 16 KB in total). That is why the + list above dedupes and keeps only the most recent 12. An oversized value is rejected as + `VALUE_TOO_LARGE`, and because that code honours `onDrop`, a writer declaring + `"deny_request"` will **deny the tool call** rather than quietly skip the write. + +#### One read, two markers — opposite directions + +Nothing says a policy writes only one key. A single writer can emit several, and the +interesting case is emitting a **grant and a restriction from the same event**, because that +is usually what the event means: reading a confidential ticket both proves you have read it +(so you may comment on it) and puts sensitive content in the session (so you may not post it +outbound). Same fact, two gates, pointing opposite ways. + +Extending the writer above with a second key, conditional on the response content: + +```rego +_labels := [lower(l) | + some l in object.get(_issue, ["fields", "labels"], []) + is_string(l) +] + +# GRANT — the same rule as above, repeated so the two sit side by side. +session_writes["marker:acme:issue_read"] := {"issue_keys": _keys} if { _key } + +# RESTRICTION — only when the issue carries the `confidential` label. The value +# carries the key so a downstream deny can name what caused it. +session_writes["marker:acme:confidential_seen"] := {"issue_key": _key} if { + _key + "confidential" in _labels +} +``` + +Declare **both** keys in the policy's `writableKeySchema` — a write to an undeclared key is +dropped, so a schema listing only the first would silently lose the second: + +```json +[ + {"name": "marker:acme:issue_read", + "jsonSchema": "{\"type\":\"object\",\"properties\":{\"issue_keys\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"maxItems\":12}},\"required\":[\"issue_keys\"],\"additionalProperties\":false}", + "ttlSeconds": 900, "onDrop": "deny_request"}, + {"name": "marker:acme:confidential_seen", + "jsonSchema": "{\"type\":\"object\",\"properties\":{\"issue_key\":{\"type\":\"string\"}},\"required\":[\"issue_key\"],\"additionalProperties\":false}", + "ttlSeconds": 900, "onDrop": "deny_request"} +] +``` + +Two notes on doing this deliberately rather than by accident: + +- **The two keys are read by different policies, with different trust needs.** The grant is + read with its writer **pinned** (above); the restriction can be read with the any-writer + walk, since extra emitters only make it more cautious. One writer, two readers, two + different read idioms. +- **Both keys count against the per-decision and per-session caps**, and each carries its own + TTL. Give the restriction a TTL at least as long as the grant if a downstream policy + assumes both are present together — otherwise the restriction can expire first and leave a + grant standing on its own. + +#### What this does not give you + +A grant gate is not a single-use token. Two calls issued in parallel are both evaluated +against the state left by earlier evaluations, so both can be allowed before either write +lands. Recording "already used" in a marker makes the record correct, not the gate exclusive. +Treat a grant as **single-use for sequential calls** and say so plainly rather than implying +exactly-once. ### `writableKeySchema` (attached via `dtwo-add-policy` / `dtwo-update-policy`) @@ -1005,7 +1265,7 @@ Marker-key *shape* is validated server-side (the backend on save, and at deploy) - **`time.now_ns()` must stay an integer.** Use `time.now_ns()` raw for timestamp fields typed `integer` in the schema. Dividing in Rego (e.g. `time.now_ns() / 1000000`) produces a **float**, which fails a `"type": "integer"` schema — and with `onDrop: "deny_request"` that silently-authored bug will block the tool call. - **Match the key exactly.** The `session_writes` key, the `writableKeySchema` `name`, and the registered marker FQID must all be the identical `marker::` string. A mismatch drops the write. - **Multiple writers land in separate slots.** If two policies declare and emit the same key, each write lands under its own writer UID; the walk-all-writers read finds either. Prefer one canonical writer per marker. -- **Reads fail open on absent state.** If `input.context.session.policies` is missing or the marker was never written, the `_active` helper simply doesn't match — the reader allows. Structure high-sensitivity gates so the *presence* of the marker is what denies, not its absence (that's the intended semantics: no signal → nothing to block). +- **Reads fail open on absent state.** If `input.context.session.policies` is missing or the marker was never written, the `_pii_active` helper simply doesn't match — the reader allows. Structure high-sensitivity gates so the *presence* of the marker is what denies, not its absence (that's the intended semantics: no signal → nothing to block). A marker that *grants* a capability inverts this and must read fail-closed instead — see **Markers that grant**. ## Intent-capture policies (conditional — feature-gated) @@ -1061,7 +1321,7 @@ reason := "This tool is only permitted under the 'default', 'debug', or 'explore Notes: - **Availability — safe to reference on any gateway.** The `dtwo.lib.intent_match` library is shipped into **every** policy bundle unconditionally (independent of the intent flag), so a reference to `data.dtwo.lib.intent_match.*` always resolves and compiles — it will *not* cause an "undefined function" bundle failure when intent capture is off. It only returns real values when intent capture is enabled; with it off there's no captured intent, so `current_intent` is undefined and `category_in` is simply always `false` — meaning a gate like the one above would deny the gated tool on a no-intent gateway. Design the default accordingly (and see the availability gate at the top of this section before surfacing intent behavior at all). -- **Never echo the intent value into a deny `reason` or a `transform`.** The intent `description` is free text the caller supplied; use the intent for the *decision*, not for output. +- **Never echo the intent value into a deny `reason` or a `transform`.** Use the intent for the *decision*, never as content the agent reads back: do not interpolate `current_intent(input)` or `current_category(input)` — and above all not the intent `description` — into `decision.reason`, and do not place it in `decision.transforms[]`. Two independent reasons. The `description` is free text the *caller* supplied, so echoing it round-trips unvalidated caller text through your policy's output. And the intent is a governance input: a policy that reflects it back turns it into a channel the agent can read, which is exactly what it is not for. Say which rule denied ("this tool is not permitted under the current session intent"), not what the intent was. Registry text is a different matter — that is authored by your admins and is safe to surface (see Reading the registry). - **A `default allow := false` gate still risks self-lock** if it fronts the Dtwo MCP server — keep the non-gated-tool passthrough (as above) so `dtwo-*` management calls are unaffected. See the self-lock pitfall in Common Pitfalls. ### Closed pipeline — your policies may not enforce on `set_intent` diff --git a/scripts/generate-schema-digest.mjs b/scripts/generate-schema-digest.mjs index 480317b..67b38ba 100644 --- a/scripts/generate-schema-digest.mjs +++ b/scripts/generate-schema-digest.mjs @@ -569,10 +569,15 @@ function renderOAuthVariant(filtered) { // Cross-field-constraint conditional fields const conditional = new Set(['issuer', 'client_id', 'client_secret', 'token_url']); + // Ordered allowlist: a field newly added to the artifact is DROPPED here + // rather than appended blindly. That is safe only because the coverage check + // at the end of this script refuses to write the digest until the field is + // placed deliberately — if you hit that error, add the name here. const fieldOrder = [ 'grant_type', 'scopes', 'issuer', 'client_id', 'client_secret', 'token_url', 'authorization_url', 'redirect_uri', 'pkce_enabled', + 'token_endpoint_auth_method', 'omit_resource', ]; const rows = fieldOrder .map(name => fieldByName(oauth, name)) @@ -584,7 +589,10 @@ function renderOAuthVariant(filtered) { const type = f.secret ? `${f.type}, **secret**` : f.type; const target = f.target ? `\`${f.target}\`` : '—'; const rationale = f.rationale ?? f.description ?? ''; - return `| \`${f.name}\` | ${req} | ${escapePipe(type)} | ${target} | ${escapePipe(rationale)} |`; + // Default column added when `scopes` gained `schemaDefault: []` — the + // coverage gate requires every declared default to render its flavored + // cell, and this table had nowhere to put one. + return `| \`${f.name}\` | ${req} | ${escapePipe(type)} | ${defaultCell(f)} | ${target} | ${escapePipe(rationale)} |`; }); return [ @@ -598,10 +606,10 @@ function renderOAuthVariant(filtered) { '- **DCR shape:** `issuer` is set. `client_id`, `client_secret`, and `token_url` may be omitted — the gateway discovers/registers them.', '- **Static-credentials shape:** `client_id` AND `client_secret` AND `token_url` are all set. `issuer` is not required.', '', - 'Setting some but not all of `client_id` / `client_secret` / `token_url` without `issuer` is invalid. Both shapes still require `type: oauth`, `grant_type`, and `scopes`.', + 'Setting some but not all of `client_id` / `client_secret` / `token_url` without `issuer` is invalid. Both shapes still require `type: oauth` and `grant_type` — `scopes` is optional (omit it, or `[]`, for providers that reject a `scope` parameter).', '', - '| Field | Required | Type | Target | Rationale (from artifact) |', - '|---|---|---|---|---|', + '| Field | Required | Type | Default | Target | Rationale (from artifact) |', + '|---|---|---|---|---|---|', ...rows, '', ].join('\n'); diff --git a/skill-harness/src/schemaArtifact.ts b/skill-harness/src/schemaArtifact.ts index 77a5ea5..6ad37ed 100644 --- a/skill-harness/src/schemaArtifact.ts +++ b/skill-harness/src/schemaArtifact.ts @@ -45,7 +45,7 @@ export const SCHEMA_ARTIFACT_VERSION = '1.1.0'; * in reviewed source. It cannot stop a PR that bumps both the artifact and * this constant — judging that change is still review's job. */ -export const EXPECTED_SCHEMA_ARTIFACT_SHA256 = '7da03dec3c066d3ca74a9a25173017dd63b0e8a04eea167dce3eec4ae19fad1d'; +export const EXPECTED_SCHEMA_ARTIFACT_SHA256 = '22f5fa77bd79b0686b23f663756e787613547f2f2d65e8e98d2a5d012ec0e30e'; /** * `platform` is emitted by the currently vendored artifact (every diff --git a/skill-harness/src/validatorBundle.ts b/skill-harness/src/validatorBundle.ts index 241f6ed..f8e927c 100644 --- a/skill-harness/src/validatorBundle.ts +++ b/skill-harness/src/validatorBundle.ts @@ -32,14 +32,14 @@ import { fileURLToPath } from 'node:url'; import { ConfigSchema, parseConfig, VALIDATOR_BUNDLE_VERSION } from '../vendor/config-validator.bundle.mjs'; /** Shape pin. See the module docstring for what this does and does not catch. */ -export const EXPECTED_VALIDATOR_BUNDLE_VERSION = '2.0.0'; +export const EXPECTED_VALIDATOR_BUNDLE_VERSION = '4.0.0'; /** * sha256 of the vendored bundle's bytes. Asserted by * `__tests__/schemaDigest.test.ts`, not at module load. Bump this together * with `EXPECTED_VALIDATOR_BUNDLE_VERSION` when the bundle is re-vendored. */ -export const EXPECTED_VALIDATOR_BUNDLE_SHA256 = 'd5d07962a80a47e3ccc7a9550e6b56650321bed2d3a541d932c70f167d5c9bda'; +export const EXPECTED_VALIDATOR_BUNDLE_SHA256 = '915727450d11614906e34260b742a3b7c814b58dbdbd6023c2f5af91e2e12ede'; const HERE = dirname(fileURLToPath(import.meta.url)); diff --git a/skill-harness/vendor/config-validator.bundle.mjs b/skill-harness/vendor/config-validator.bundle.mjs index 9a78d3f..dbf6261 100644 --- a/skill-harness/vendor/config-validator.bundle.mjs +++ b/skill-harness/vendor/config-validator.bundle.mjs @@ -1,5 +1,5 @@ // config-validator.bundle.mjs — generated artifact, do not edit by hand. -// Dtwo gateway ConfigSchema validator, bundle version 2.0.0. +// Dtwo gateway ConfigSchema validator, bundle version 4.0.0. var __defProp = Object.defineProperty; var __export = (target, all) => { @@ -7,1731 +7,2100 @@ var __export = (target, all) => { __defProp(target, name, { get: all[name], enumerable: true }); }; -// ../../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/dist/js-yaml.mjs -function isNothing(subject) { - return typeof subject === "undefined" || subject === null; -} -function isObject(subject) { - return typeof subject === "object" && subject !== null; -} -function toArray(sequence) { - if (Array.isArray(sequence)) return sequence; - else if (isNothing(sequence)) return []; - return [sequence]; -} -function extend(target, source) { - var index, length, key, sourceKeys; - if (source) { - sourceKeys = Object.keys(source); - for (index = 0, length = sourceKeys.length; index < length; index += 1) { - key = sourceKeys[index]; - target[key] = source[key]; +// ../../../node_modules/.pnpm/js-yaml@4.3.2/node_modules/js-yaml/dist/js-yaml.mjs +function getDefaultExportFromCjs(x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; +} +var jsYaml = {}; +var loader = {}; +var common = {}; +var hasRequiredCommon; +function requireCommon() { + if (hasRequiredCommon) return common; + hasRequiredCommon = 1; + function isNothing(subject) { + return typeof subject === "undefined" || subject === null; + } + function isObject2(subject) { + return typeof subject === "object" && subject !== null; + } + function toArray(sequence) { + if (Array.isArray(sequence)) return sequence; + else if (isNothing(sequence)) return []; + return [sequence]; + } + function extend2(target, source) { + if (source) { + const sourceKeys = Object.keys(source); + for (let index = 0, length = sourceKeys.length; index < length; index += 1) { + const key = sourceKeys[index]; + target[key] = source[key]; + } + } + return target; + } + function repeat(string4, count) { + let result = ""; + for (let cycle = 0; cycle < count; cycle += 1) { + result += string4; } + return result; } - return target; -} -function repeat(string4, count) { - var result = "", cycle; - for (cycle = 0; cycle < count; cycle += 1) { - result += string4; - } - return result; -} -function isNegativeZero(number4) { - return number4 === 0 && Number.NEGATIVE_INFINITY === 1 / number4; -} -var isNothing_1 = isNothing; -var isObject_1 = isObject; -var toArray_1 = toArray; -var repeat_1 = repeat; -var isNegativeZero_1 = isNegativeZero; -var extend_1 = extend; -var common = { - isNothing: isNothing_1, - isObject: isObject_1, - toArray: toArray_1, - repeat: repeat_1, - isNegativeZero: isNegativeZero_1, - extend: extend_1 -}; -function formatError(exception2, compact) { - var where = "", message = exception2.reason || "(unknown reason)"; - if (!exception2.mark) return message; - if (exception2.mark.name) { - where += 'in "' + exception2.mark.name + '" '; - } - where += "(" + (exception2.mark.line + 1) + ":" + (exception2.mark.column + 1) + ")"; - if (!compact && exception2.mark.snippet) { - where += "\n\n" + exception2.mark.snippet; - } - return message + " " + where; -} -function YAMLException$1(reason, mark) { - Error.call(this); - this.name = "YAMLException"; - this.reason = reason; - this.mark = mark; - this.message = formatError(this, false); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } else { - this.stack = new Error().stack || ""; + function isNegativeZero(number4) { + return number4 === 0 && Number.NEGATIVE_INFINITY === 1 / number4; + } + common.isNothing = isNothing; + common.isObject = isObject2; + common.toArray = toArray; + common.repeat = repeat; + common.isNegativeZero = isNegativeZero; + common.extend = extend2; + return common; +} +var exception; +var hasRequiredException; +function requireException() { + if (hasRequiredException) return exception; + hasRequiredException = 1; + function formatError2(exception2, compact) { + let where = ""; + const message = exception2.reason || "(unknown reason)"; + if (!exception2.mark) return message; + if (exception2.mark.name) { + where += 'in "' + exception2.mark.name + '" '; + } + where += "(" + (exception2.mark.line + 1) + ":" + (exception2.mark.column + 1) + ")"; + if (!compact && exception2.mark.snippet) { + where += "\n\n" + exception2.mark.snippet; + } + return message + " " + where; + } + function YAMLException2(reason, mark) { + Error.call(this); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError2(this, false); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + this.stack = new Error().stack || ""; + } + } + YAMLException2.prototype = Object.create(Error.prototype); + YAMLException2.prototype.constructor = YAMLException2; + YAMLException2.prototype.toString = function toString(compact) { + return this.name + ": " + formatError2(this, compact); + }; + exception = YAMLException2; + return exception; +} +var snippet; +var hasRequiredSnippet; +function requireSnippet() { + if (hasRequiredSnippet) return snippet; + hasRequiredSnippet = 1; + const common2 = requireCommon(); + function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + // relative position + }; } -} -YAMLException$1.prototype = Object.create(Error.prototype); -YAMLException$1.prototype.constructor = YAMLException$1; -YAMLException$1.prototype.toString = function toString(compact) { - return this.name + ": " + formatError(this, compact); -}; -var exception = YAMLException$1; -function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { - var head = ""; - var tail = ""; - var maxHalfLength = Math.floor(maxLineLength / 2) - 1; - if (position - lineStart > maxHalfLength) { - head = " ... "; - lineStart = position - maxHalfLength + head.length; - } - if (lineEnd - position > maxHalfLength) { - tail = " ..."; - lineEnd = position + maxHalfLength - tail.length; + function padStart(string4, max) { + return common2.repeat(" ", max - string4.length) + string4; + } + function makeSnippet(mark, options) { + options = Object.create(options || null); + if (!mark.buffer) return null; + if (!options.maxLength) options.maxLength = 79; + if (typeof options.indent !== "number") options.indent = 1; + if (typeof options.linesBefore !== "number") options.linesBefore = 3; + if (typeof options.linesAfter !== "number") options.linesAfter = 2; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) { + foundLineNo = lineStarts.length - 2; + } + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; + const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); + for (let i = 1; i <= options.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine( + mark.buffer, + lineStarts[foundLineNo - i], + lineEnds[foundLineNo - i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), + maxLineLength + ); + result = common2.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += common2.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; + result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; + for (let i = 1; i <= options.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine( + mark.buffer, + lineStarts[foundLineNo + i], + lineEnds[foundLineNo + i], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), + maxLineLength + ); + result += common2.repeat(" ", options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n"; + } + return result.replace(/\n$/, ""); + } + snippet = makeSnippet; + return snippet; +} +var type; +var hasRequiredType; +function requireType() { + if (hasRequiredType) return type; + hasRequiredType = 1; + const YAMLException2 = requireException(); + const TYPE_CONSTRUCTOR_OPTIONS = [ + "kind", + "multi", + "resolve", + "construct", + "instanceOf", + "predicate", + "represent", + "representName", + "defaultStyle", + "styleAliases" + ]; + const YAML_NODE_KINDS = [ + "scalar", + "sequence", + "mapping" + ]; + function compileStyleAliases(map22) { + const result = {}; + if (map22 !== null) { + Object.keys(map22).forEach(function(style) { + map22[style].forEach(function(alias) { + result[String(alias)] = style; + }); + }); + } + return result; } - return { - str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, - pos: position - lineStart + head.length - // relative position - }; -} -function padStart(string4, max) { - return common.repeat(" ", max - string4.length) + string4; -} -function makeSnippet(mark, options) { - options = Object.create(options || null); - if (!mark.buffer) return null; - if (!options.maxLength) options.maxLength = 79; - if (typeof options.indent !== "number") options.indent = 1; - if (typeof options.linesBefore !== "number") options.linesBefore = 3; - if (typeof options.linesAfter !== "number") options.linesAfter = 2; - var re = /\r?\n|\r|\0/g; - var lineStarts = [0]; - var lineEnds = []; - var match; - var foundLineNo = -1; - while (match = re.exec(mark.buffer)) { - lineEnds.push(match.index); - lineStarts.push(match.index + match[0].length); - if (mark.position <= match.index && foundLineNo < 0) { - foundLineNo = lineStarts.length - 2; - } - } - if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; - var result = "", i2, line; - var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length; - var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); - for (i2 = 1; i2 <= options.linesBefore; i2++) { - if (foundLineNo - i2 < 0) break; - line = getLine( - mark.buffer, - lineStarts[foundLineNo - i2], - lineEnds[foundLineNo - i2], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i2]), - maxLineLength - ); - result = common.repeat(" ", options.indent) + padStart((mark.line - i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n" + result; - } - line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); - result += common.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; - result += common.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; - for (i2 = 1; i2 <= options.linesAfter; i2++) { - if (foundLineNo + i2 >= lineEnds.length) break; - line = getLine( - mark.buffer, - lineStarts[foundLineNo + i2], - lineEnds[foundLineNo + i2], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i2]), - maxLineLength - ); - result += common.repeat(" ", options.indent) + padStart((mark.line + i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n"; - } - return result.replace(/\n$/, ""); -} -var snippet = makeSnippet; -var TYPE_CONSTRUCTOR_OPTIONS = [ - "kind", - "multi", - "resolve", - "construct", - "instanceOf", - "predicate", - "represent", - "representName", - "defaultStyle", - "styleAliases" -]; -var YAML_NODE_KINDS = [ - "scalar", - "sequence", - "mapping" -]; -function compileStyleAliases(map3) { - var result = {}; - if (map3 !== null) { - Object.keys(map3).forEach(function(style) { - map3[style].forEach(function(alias) { - result[String(alias)] = style; + function Type2(tag, options) { + options = options || {}; + Object.keys(options).forEach(function(name) { + if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { + throw new YAMLException2('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); + this.options = options; + this.tag = tag; + this.kind = options["kind"] || null; + this.resolve = options["resolve"] || function() { + return true; + }; + this.construct = options["construct"] || function(data) { + return data; + }; + this.instanceOf = options["instanceOf"] || null; + this.predicate = options["predicate"] || null; + this.represent = options["represent"] || null; + this.representName = options["representName"] || null; + this.defaultStyle = options["defaultStyle"] || null; + this.multi = options["multi"] || false; + this.styleAliases = compileStyleAliases(options["styleAliases"] || null); + if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { + throw new YAMLException2('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); + } + } + type = Type2; + return type; +} +var schema; +var hasRequiredSchema; +function requireSchema() { + if (hasRequiredSchema) return schema; + hasRequiredSchema = 1; + const YAMLException2 = requireException(); + const Type2 = requireType(); + function compileList(schema2, name) { + const result = []; + schema2[name].forEach(function(currentType) { + let newIndex = result.length; + result.forEach(function(previousType, previousIndex) { + if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) { + newIndex = previousIndex; + } }); + result[newIndex] = currentType; }); + return result; } - return result; -} -function Type$1(tag, options) { - options = options || {}; - Object.keys(options).forEach(function(name) { - if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) { - throw new exception('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); - } - }); - this.options = options; - this.tag = tag; - this.kind = options["kind"] || null; - this.resolve = options["resolve"] || function() { - return true; - }; - this.construct = options["construct"] || function(data) { - return data; - }; - this.instanceOf = options["instanceOf"] || null; - this.predicate = options["predicate"] || null; - this.represent = options["represent"] || null; - this.representName = options["representName"] || null; - this.defaultStyle = options["defaultStyle"] || null; - this.multi = options["multi"] || false; - this.styleAliases = compileStyleAliases(options["styleAliases"] || null); - if (YAML_NODE_KINDS.indexOf(this.kind) === -1) { - throw new exception('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); - } -} -var type = Type$1; -function compileList(schema2, name) { - var result = []; - schema2[name].forEach(function(currentType) { - var newIndex = result.length; - result.forEach(function(previousType, previousIndex) { - if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) { - newIndex = previousIndex; + function compileMap() { + const result = { + scalar: {}, + sequence: {}, + mapping: {}, + fallback: {}, + multi: { + scalar: [], + sequence: [], + mapping: [], + fallback: [] + } + }; + function collectType(type2) { + if (type2.multi) { + result.multi[type2.kind].push(type2); + result.multi["fallback"].push(type2); + } else { + result[type2.kind][type2.tag] = result["fallback"][type2.tag] = type2; } - }); - result[newIndex] = currentType; - }); - return result; -} -function compileMap() { - var result = { - scalar: {}, - sequence: {}, - mapping: {}, - fallback: {}, - multi: { - scalar: [], - sequence: [], - mapping: [], - fallback: [] - } - }, index, length; - function collectType(type2) { - if (type2.multi) { - result.multi[type2.kind].push(type2); - result.multi["fallback"].push(type2); - } else { - result[type2.kind][type2.tag] = result["fallback"][type2.tag] = type2; } + for (let index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + return result; } - for (index = 0, length = arguments.length; index < length; index += 1) { - arguments[index].forEach(collectType); - } - return result; -} -function Schema$1(definition) { - return this.extend(definition); -} -Schema$1.prototype.extend = function extend2(definition) { - var implicit = []; - var explicit = []; - if (definition instanceof type) { - explicit.push(definition); - } else if (Array.isArray(definition)) { - explicit = explicit.concat(definition); - } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { - if (definition.implicit) implicit = implicit.concat(definition.implicit); - if (definition.explicit) explicit = explicit.concat(definition.explicit); - } else { - throw new exception("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })"); - } - implicit.forEach(function(type$1) { - if (!(type$1 instanceof type)) { - throw new exception("Specified list of YAML types (or a single Type object) contains a non-Type object."); + function Schema2(definition) { + return this.extend(definition); + } + Schema2.prototype.extend = function extend2(definition) { + let implicit = []; + let explicit = []; + if (definition instanceof Type2) { + explicit.push(definition); + } else if (Array.isArray(definition)) { + explicit = explicit.concat(definition); + } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { + if (definition.implicit) implicit = implicit.concat(definition.implicit); + if (definition.explicit) explicit = explicit.concat(definition.explicit); + } else { + throw new YAMLException2("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })"); } - if (type$1.loadKind && type$1.loadKind !== "scalar") { - throw new exception("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported."); + implicit.forEach(function(type2) { + if (!(type2 instanceof Type2)) { + throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object."); + } + if (type2.loadKind && type2.loadKind !== "scalar") { + throw new YAMLException2("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported."); + } + if (type2.multi) { + throw new YAMLException2("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit."); + } + }); + explicit.forEach(function(type2) { + if (!(type2 instanceof Type2)) { + throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object."); + } + }); + const result = Object.create(Schema2.prototype); + result.implicit = (this.implicit || []).concat(implicit); + result.explicit = (this.explicit || []).concat(explicit); + result.compiledImplicit = compileList(result, "implicit"); + result.compiledExplicit = compileList(result, "explicit"); + result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); + return result; + }; + schema = Schema2; + return schema; +} +var str; +var hasRequiredStr; +function requireStr() { + if (hasRequiredStr) return str; + hasRequiredStr = 1; + const Type2 = requireType(); + str = new Type2("tag:yaml.org,2002:str", { + kind: "scalar", + construct: function(data) { + return data !== null ? data : ""; } - if (type$1.multi) { - throw new exception("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit."); + }); + return str; +} +var seq; +var hasRequiredSeq; +function requireSeq() { + if (hasRequiredSeq) return seq; + hasRequiredSeq = 1; + const Type2 = requireType(); + seq = new Type2("tag:yaml.org,2002:seq", { + kind: "sequence", + construct: function(data) { + return data !== null ? data : []; } }); - explicit.forEach(function(type$1) { - if (!(type$1 instanceof type)) { - throw new exception("Specified list of YAML types (or a single Type object) contains a non-Type object."); + return seq; +} +var map; +var hasRequiredMap; +function requireMap() { + if (hasRequiredMap) return map; + hasRequiredMap = 1; + const Type2 = requireType(); + map = new Type2("tag:yaml.org,2002:map", { + kind: "mapping", + construct: function(data) { + return data !== null ? data : {}; } }); - var result = Object.create(Schema$1.prototype); - result.implicit = (this.implicit || []).concat(implicit); - result.explicit = (this.explicit || []).concat(explicit); - result.compiledImplicit = compileList(result, "implicit"); - result.compiledExplicit = compileList(result, "explicit"); - result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); - return result; -}; -var schema = Schema$1; -var str = new type("tag:yaml.org,2002:str", { - kind: "scalar", - construct: function(data) { - return data !== null ? data : ""; - } -}); -var seq = new type("tag:yaml.org,2002:seq", { - kind: "sequence", - construct: function(data) { - return data !== null ? data : []; - } -}); -var map = new type("tag:yaml.org,2002:map", { - kind: "mapping", - construct: function(data) { - return data !== null ? data : {}; - } -}); -var failsafe = new schema({ - explicit: [ - str, - seq, - map - ] -}); -function resolveYamlNull(data) { - if (data === null) return true; - var max = data.length; - return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL"); -} -function constructYamlNull() { - return null; -} -function isNull(object2) { - return object2 === null; -} -var _null = new type("tag:yaml.org,2002:null", { - kind: "scalar", - resolve: resolveYamlNull, - construct: constructYamlNull, - predicate: isNull, - represent: { - canonical: function() { - return "~"; - }, - lowercase: function() { - return "null"; - }, - uppercase: function() { - return "NULL"; + return map; +} +var failsafe; +var hasRequiredFailsafe; +function requireFailsafe() { + if (hasRequiredFailsafe) return failsafe; + hasRequiredFailsafe = 1; + const Schema2 = requireSchema(); + failsafe = new Schema2({ + explicit: [ + requireStr(), + requireSeq(), + requireMap() + ] + }); + return failsafe; +} +var _null; +var hasRequired_null; +function require_null() { + if (hasRequired_null) return _null; + hasRequired_null = 1; + const Type2 = requireType(); + function resolveYamlNull(data) { + if (data === null) return true; + const max = data.length; + return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL"); + } + function constructYamlNull() { + return null; + } + function isNull(object2) { + return object2 === null; + } + _null = new Type2("tag:yaml.org,2002:null", { + kind: "scalar", + resolve: resolveYamlNull, + construct: constructYamlNull, + predicate: isNull, + represent: { + canonical: function() { + return "~"; + }, + lowercase: function() { + return "null"; + }, + uppercase: function() { + return "NULL"; + }, + camelcase: function() { + return "Null"; + }, + empty: function() { + return ""; + } }, - camelcase: function() { - return "Null"; + defaultStyle: "lowercase" + }); + return _null; +} +var bool; +var hasRequiredBool; +function requireBool() { + if (hasRequiredBool) return bool; + hasRequiredBool = 1; + const Type2 = requireType(); + function resolveYamlBoolean(data) { + if (data === null) return false; + const max = data.length; + return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE"); + } + function constructYamlBoolean(data) { + return data === "true" || data === "True" || data === "TRUE"; + } + function isBoolean(object2) { + return Object.prototype.toString.call(object2) === "[object Boolean]"; + } + bool = new Type2("tag:yaml.org,2002:bool", { + kind: "scalar", + resolve: resolveYamlBoolean, + construct: constructYamlBoolean, + predicate: isBoolean, + represent: { + lowercase: function(object2) { + return object2 ? "true" : "false"; + }, + uppercase: function(object2) { + return object2 ? "TRUE" : "FALSE"; + }, + camelcase: function(object2) { + return object2 ? "True" : "False"; + } }, - empty: function() { - return ""; + defaultStyle: "lowercase" + }); + return bool; +} +var int; +var hasRequiredInt; +function requireInt() { + if (hasRequiredInt) return int; + hasRequiredInt = 1; + const common2 = requireCommon(); + const Type2 = requireType(); + function isHexCode(c) { + return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102; + } + function isOctCode(c) { + return c >= 48 && c <= 55; + } + function isDecCode(c) { + return c >= 48 && c <= 57; + } + function resolveYamlInteger(data) { + if (data === null) return false; + const max = data.length; + let index = 0; + let hasDigits = false; + if (!max) return false; + let ch = data[index]; + if (ch === "-" || ch === "+") { + ch = data[++index]; + } + if (ch === "0") { + if (index + 1 === max) return true; + ch = data[++index]; + if (ch === "b") { + index++; + for (; index < max; index++) { + ch = data[index]; + if (ch !== "0" && ch !== "1") return false; + hasDigits = true; + } + return hasDigits && isFinite(parseYamlInteger(data)); + } + if (ch === "x") { + index++; + for (; index < max; index++) { + if (!isHexCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && isFinite(parseYamlInteger(data)); + } + if (ch === "o") { + index++; + for (; index < max; index++) { + if (!isOctCode(data.charCodeAt(index))) return false; + hasDigits = true; + } + return hasDigits && isFinite(parseYamlInteger(data)); + } } - }, - defaultStyle: "lowercase" -}); -function resolveYamlBoolean(data) { - if (data === null) return false; - var max = data.length; - return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE"); -} -function constructYamlBoolean(data) { - return data === "true" || data === "True" || data === "TRUE"; -} -function isBoolean(object2) { - return Object.prototype.toString.call(object2) === "[object Boolean]"; -} -var bool = new type("tag:yaml.org,2002:bool", { - kind: "scalar", - resolve: resolveYamlBoolean, - construct: constructYamlBoolean, - predicate: isBoolean, - represent: { - lowercase: function(object2) { - return object2 ? "true" : "false"; - }, - uppercase: function(object2) { - return object2 ? "TRUE" : "FALSE"; + for (; index < max; index++) { + if (!isDecCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + if (!hasDigits) return false; + return isFinite(parseYamlInteger(data)); + } + function parseYamlInteger(data) { + let value = data; + let sign = 1; + let ch = value[0]; + if (ch === "-" || ch === "+") { + if (ch === "-") sign = -1; + value = value.slice(1); + ch = value[0]; + } + if (value === "0") return 0; + if (ch === "0") { + if (value[1] === "b") return sign * parseInt(value.slice(2), 2); + if (value[1] === "x") return sign * parseInt(value.slice(2), 16); + if (value[1] === "o") return sign * parseInt(value.slice(2), 8); + } + return sign * parseInt(value, 10); + } + function constructYamlInteger(data) { + return parseYamlInteger(data); + } + function isInteger(object2) { + return Object.prototype.toString.call(object2) === "[object Number]" && (object2 % 1 === 0 && !common2.isNegativeZero(object2)); + } + int = new Type2("tag:yaml.org,2002:int", { + kind: "scalar", + resolve: resolveYamlInteger, + construct: constructYamlInteger, + predicate: isInteger, + represent: { + binary: function(obj) { + return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1); + }, + octal: function(obj) { + return obj >= 0 ? "0o" + obj.toString(8) : "-0o" + obj.toString(8).slice(1); + }, + decimal: function(obj) { + return obj.toString(10); + }, + hexadecimal: function(obj) { + return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1); + } }, - camelcase: function(object2) { - return object2 ? "True" : "False"; + defaultStyle: "decimal", + styleAliases: { + binary: [2, "bin"], + octal: [8, "oct"], + decimal: [10, "dec"], + hexadecimal: [16, "hex"] } - }, - defaultStyle: "lowercase" -}); -function isHexCode(c) { - return 48 <= c && c <= 57 || 65 <= c && c <= 70 || 97 <= c && c <= 102; -} -function isOctCode(c) { - return 48 <= c && c <= 55; -} -function isDecCode(c) { - return 48 <= c && c <= 57; -} -function resolveYamlInteger(data) { - if (data === null) return false; - var max = data.length, index = 0, hasDigits = false, ch; - if (!max) return false; - ch = data[index]; - if (ch === "-" || ch === "+") { - ch = data[++index]; - } - if (ch === "0") { - if (index + 1 === max) return true; - ch = data[++index]; - if (ch === "b") { - index++; - for (; index < max; index++) { - ch = data[index]; - if (ch === "_") continue; - if (ch !== "0" && ch !== "1") return false; - hasDigits = true; - } - return hasDigits && ch !== "_"; - } - if (ch === "x") { - index++; - for (; index < max; index++) { - ch = data[index]; - if (ch === "_") continue; - if (!isHexCode(data.charCodeAt(index))) return false; - hasDigits = true; - } - return hasDigits && ch !== "_"; - } - if (ch === "o") { - index++; - for (; index < max; index++) { - ch = data[index]; - if (ch === "_") continue; - if (!isOctCode(data.charCodeAt(index))) return false; - hasDigits = true; - } - return hasDigits && ch !== "_"; - } - } - if (ch === "_") return false; - for (; index < max; index++) { - ch = data[index]; - if (ch === "_") continue; - if (!isDecCode(data.charCodeAt(index))) { + }); + return int; +} +var float; +var hasRequiredFloat; +function requireFloat() { + if (hasRequiredFloat) return float; + hasRequiredFloat = 1; + const common2 = requireCommon(); + const Type2 = requireType(); + const YAML_FLOAT_PATTERN = new RegExp( + // 2.5e4, 2.5 and integers + "^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$" + ); + const YAML_FLOAT_SPECIAL_PATTERN = new RegExp( + "^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$" + ); + function resolveYamlFloat(data) { + if (data === null) return false; + if (!YAML_FLOAT_PATTERN.test(data)) { return false; } - hasDigits = true; - } - if (!hasDigits || ch === "_") return false; - return true; -} -function constructYamlInteger(data) { - var value = data, sign = 1, ch; - if (value.indexOf("_") !== -1) { - value = value.replace(/_/g, ""); - } - ch = value[0]; - if (ch === "-" || ch === "+") { - if (ch === "-") sign = -1; - value = value.slice(1); - ch = value[0]; - } - if (value === "0") return 0; - if (ch === "0") { - if (value[1] === "b") return sign * parseInt(value.slice(2), 2); - if (value[1] === "x") return sign * parseInt(value.slice(2), 16); - if (value[1] === "o") return sign * parseInt(value.slice(2), 8); - } - return sign * parseInt(value, 10); -} -function isInteger(object2) { - return Object.prototype.toString.call(object2) === "[object Number]" && (object2 % 1 === 0 && !common.isNegativeZero(object2)); -} -var int = new type("tag:yaml.org,2002:int", { - kind: "scalar", - resolve: resolveYamlInteger, - construct: constructYamlInteger, - predicate: isInteger, - represent: { - binary: function(obj) { - return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1); - }, - octal: function(obj) { - return obj >= 0 ? "0o" + obj.toString(8) : "-0o" + obj.toString(8).slice(1); - }, - decimal: function(obj) { - return obj.toString(10); - }, - /* eslint-disable max-len */ - hexadecimal: function(obj) { - return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1); + if (isFinite(parseFloat(data, 10))) { + return true; } - }, - defaultStyle: "decimal", - styleAliases: { - binary: [2, "bin"], - octal: [8, "oct"], - decimal: [10, "dec"], - hexadecimal: [16, "hex"] - } -}); -var YAML_FLOAT_PATTERN = new RegExp( - // 2.5e4, 2.5 and integers - "^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$" -); -function resolveYamlFloat(data) { - if (data === null) return false; - if (!YAML_FLOAT_PATTERN.test(data) || // Quick hack to not allow integers end with `_` - // Probably should update regexp & check speed - data[data.length - 1] === "_") { + return YAML_FLOAT_SPECIAL_PATTERN.test(data); + } + function constructYamlFloat(data) { + let value = data.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".indexOf(value[0]) >= 0) { + value = value.slice(1); + } + if (value === ".inf") { + return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + } else if (value === ".nan") { + return NaN; + } + return sign * parseFloat(value, 10); + } + const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; + function representYamlFloat(object2, style) { + if (isNaN(object2)) { + switch (style) { + case "lowercase": + return ".nan"; + case "uppercase": + return ".NAN"; + case "camelcase": + return ".NaN"; + } + } else if (Number.POSITIVE_INFINITY === object2) { + switch (style) { + case "lowercase": + return ".inf"; + case "uppercase": + return ".INF"; + case "camelcase": + return ".Inf"; + } + } else if (Number.NEGATIVE_INFINITY === object2) { + switch (style) { + case "lowercase": + return "-.inf"; + case "uppercase": + return "-.INF"; + case "camelcase": + return "-.Inf"; + } + } else if (common2.isNegativeZero(object2)) { + return "-0.0"; + } + const res = object2.toString(10); + return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res; + } + function isFloat(object2) { + return Object.prototype.toString.call(object2) === "[object Number]" && (object2 % 1 !== 0 || common2.isNegativeZero(object2)); + } + float = new Type2("tag:yaml.org,2002:float", { + kind: "scalar", + resolve: resolveYamlFloat, + construct: constructYamlFloat, + predicate: isFloat, + represent: representYamlFloat, + defaultStyle: "lowercase" + }); + return float; +} +var json; +var hasRequiredJson; +function requireJson() { + if (hasRequiredJson) return json; + hasRequiredJson = 1; + json = requireFailsafe().extend({ + implicit: [ + require_null(), + requireBool(), + requireInt(), + requireFloat() + ] + }); + return json; +} +var core; +var hasRequiredCore; +function requireCore() { + if (hasRequiredCore) return core; + hasRequiredCore = 1; + core = requireJson(); + return core; +} +var timestamp; +var hasRequiredTimestamp; +function requireTimestamp() { + if (hasRequiredTimestamp) return timestamp; + hasRequiredTimestamp = 1; + const Type2 = requireType(); + const YAML_DATE_REGEXP = new RegExp( + "^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$" + ); + const YAML_TIMESTAMP_REGEXP = new RegExp( + "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$" + ); + function resolveYamlTimestamp(data) { + if (data === null) return false; + if (YAML_DATE_REGEXP.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; return false; } - return true; -} -function constructYamlFloat(data) { - var value, sign; - value = data.replace(/_/g, "").toLowerCase(); - sign = value[0] === "-" ? -1 : 1; - if ("+-".indexOf(value[0]) >= 0) { - value = value.slice(1); - } - if (value === ".inf") { - return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; - } else if (value === ".nan") { - return NaN; - } - return sign * parseFloat(value, 10); -} -var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; -function representYamlFloat(object2, style) { - var res; - if (isNaN(object2)) { - switch (style) { - case "lowercase": - return ".nan"; - case "uppercase": - return ".NAN"; - case "camelcase": - return ".NaN"; - } - } else if (Number.POSITIVE_INFINITY === object2) { - switch (style) { - case "lowercase": - return ".inf"; - case "uppercase": - return ".INF"; - case "camelcase": - return ".Inf"; - } - } else if (Number.NEGATIVE_INFINITY === object2) { - switch (style) { - case "lowercase": - return "-.inf"; - case "uppercase": - return "-.INF"; - case "camelcase": - return "-.Inf"; - } - } else if (common.isNegativeZero(object2)) { - return "-0.0"; - } - res = object2.toString(10); - return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res; -} -function isFloat(object2) { - return Object.prototype.toString.call(object2) === "[object Number]" && (object2 % 1 !== 0 || common.isNegativeZero(object2)); -} -var float = new type("tag:yaml.org,2002:float", { - kind: "scalar", - resolve: resolveYamlFloat, - construct: constructYamlFloat, - predicate: isFloat, - represent: representYamlFloat, - defaultStyle: "lowercase" -}); -var json = failsafe.extend({ - implicit: [ - _null, - bool, - int, - float - ] -}); -var core = json; -var YAML_DATE_REGEXP = new RegExp( - "^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$" -); -var YAML_TIMESTAMP_REGEXP = new RegExp( - "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$" -); -function resolveYamlTimestamp(data) { - if (data === null) return false; - if (YAML_DATE_REGEXP.exec(data) !== null) return true; - if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; - return false; -} -function constructYamlTimestamp(data) { - var match, year, month, day, hour, minute, second, fraction = 0, delta = null, tz_hour, tz_minute, date5; - match = YAML_DATE_REGEXP.exec(data); - if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); - if (match === null) throw new Error("Date resolve error"); - year = +match[1]; - month = +match[2] - 1; - day = +match[3]; - if (!match[4]) { - return new Date(Date.UTC(year, month, day)); - } - hour = +match[4]; - minute = +match[5]; - second = +match[6]; - if (match[7]) { - fraction = match[7].slice(0, 3); - while (fraction.length < 3) { - fraction += "0"; - } - fraction = +fraction; - } - if (match[9]) { - tz_hour = +match[10]; - tz_minute = +(match[11] || 0); - delta = (tz_hour * 60 + tz_minute) * 6e4; - if (match[9] === "-") delta = -delta; - } - date5 = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); - if (delta) date5.setTime(date5.getTime() - delta); - return date5; -} -function representYamlTimestamp(object2) { - return object2.toISOString(); -} -var timestamp = new type("tag:yaml.org,2002:timestamp", { - kind: "scalar", - resolve: resolveYamlTimestamp, - construct: constructYamlTimestamp, - instanceOf: Date, - represent: representYamlTimestamp -}); -function resolveYamlMerge(data) { - return data === "<<" || data === null; -} -var merge = new type("tag:yaml.org,2002:merge", { - kind: "scalar", - resolve: resolveYamlMerge -}); -var BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r"; -function resolveYamlBinary(data) { - if (data === null) return false; - var code, idx, bitlen = 0, max = data.length, map3 = BASE64_MAP; - for (idx = 0; idx < max; idx++) { - code = map3.indexOf(data.charAt(idx)); - if (code > 64) continue; - if (code < 0) return false; - bitlen += 6; - } - return bitlen % 8 === 0; -} -function constructYamlBinary(data) { - var idx, tailbits, input = data.replace(/[\r\n=]/g, ""), max = input.length, map3 = BASE64_MAP, bits = 0, result = []; - for (idx = 0; idx < max; idx++) { - if (idx % 4 === 0 && idx) { + function constructYamlTimestamp(data) { + let fraction = 0; + let delta = null; + let match = YAML_DATE_REGEXP.exec(data); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); + if (match === null) throw new Error("Date resolve error"); + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + return new Date(Date.UTC(year, month, day)); + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { + fraction += "0"; + } + fraction = +fraction; + } + if (match[9]) { + const tzHour = +match[10]; + const tzMinute = +(match[11] || 0); + delta = (tzHour * 60 + tzMinute) * 6e4; + if (match[9] === "-") delta = -delta; + } + const date5 = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + if (delta) date5.setTime(date5.getTime() - delta); + return date5; + } + function representYamlTimestamp(object2) { + return object2.toISOString(); + } + timestamp = new Type2("tag:yaml.org,2002:timestamp", { + kind: "scalar", + resolve: resolveYamlTimestamp, + construct: constructYamlTimestamp, + instanceOf: Date, + represent: representYamlTimestamp + }); + return timestamp; +} +var merge; +var hasRequiredMerge; +function requireMerge() { + if (hasRequiredMerge) return merge; + hasRequiredMerge = 1; + const Type2 = requireType(); + function resolveYamlMerge(data) { + return data === "<<" || data === null; + } + merge = new Type2("tag:yaml.org,2002:merge", { + kind: "scalar", + resolve: resolveYamlMerge + }); + return merge; +} +var binary; +var hasRequiredBinary; +function requireBinary() { + if (hasRequiredBinary) return binary; + hasRequiredBinary = 1; + const Type2 = requireType(); + const BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r"; + function resolveYamlBinary(data) { + if (data === null) return false; + let bitlen = 0; + const max = data.length; + const map22 = BASE64_MAP; + for (let idx = 0; idx < max; idx++) { + const code = map22.indexOf(data.charAt(idx)); + if (code > 64) continue; + if (code < 0) return false; + bitlen += 6; + } + return bitlen % 8 === 0; + } + function constructYamlBinary(data) { + const input = data.replace(/[\r\n=]/g, ""); + const max = input.length; + const map22 = BASE64_MAP; + let bits = 0; + const result = []; + for (let idx = 0; idx < max; idx++) { + if (idx % 4 === 0 && idx) { + result.push(bits >> 16 & 255); + result.push(bits >> 8 & 255); + result.push(bits & 255); + } + bits = bits << 6 | map22.indexOf(input.charAt(idx)); + } + const tailbits = max % 4 * 6; + if (tailbits === 0) { result.push(bits >> 16 & 255); result.push(bits >> 8 & 255); result.push(bits & 255); + } else if (tailbits === 18) { + result.push(bits >> 10 & 255); + result.push(bits >> 2 & 255); + } else if (tailbits === 12) { + result.push(bits >> 4 & 255); + } + return new Uint8Array(result); + } + function representYamlBinary(object2) { + let result = ""; + let bits = 0; + const max = object2.length; + const map22 = BASE64_MAP; + for (let idx = 0; idx < max; idx++) { + if (idx % 3 === 0 && idx) { + result += map22[bits >> 18 & 63]; + result += map22[bits >> 12 & 63]; + result += map22[bits >> 6 & 63]; + result += map22[bits & 63]; + } + bits = (bits << 8) + object2[idx]; + } + const tail = max % 3; + if (tail === 0) { + result += map22[bits >> 18 & 63]; + result += map22[bits >> 12 & 63]; + result += map22[bits >> 6 & 63]; + result += map22[bits & 63]; + } else if (tail === 2) { + result += map22[bits >> 10 & 63]; + result += map22[bits >> 4 & 63]; + result += map22[bits << 2 & 63]; + result += map22[64]; + } else if (tail === 1) { + result += map22[bits >> 2 & 63]; + result += map22[bits << 4 & 63]; + result += map22[64]; + result += map22[64]; } - bits = bits << 6 | map3.indexOf(input.charAt(idx)); - } - tailbits = max % 4 * 6; - if (tailbits === 0) { - result.push(bits >> 16 & 255); - result.push(bits >> 8 & 255); - result.push(bits & 255); - } else if (tailbits === 18) { - result.push(bits >> 10 & 255); - result.push(bits >> 2 & 255); - } else if (tailbits === 12) { - result.push(bits >> 4 & 255); - } - return new Uint8Array(result); -} -function representYamlBinary(object2) { - var result = "", bits = 0, idx, tail, max = object2.length, map3 = BASE64_MAP; - for (idx = 0; idx < max; idx++) { - if (idx % 3 === 0 && idx) { - result += map3[bits >> 18 & 63]; - result += map3[bits >> 12 & 63]; - result += map3[bits >> 6 & 63]; - result += map3[bits & 63]; - } - bits = (bits << 8) + object2[idx]; - } - tail = max % 3; - if (tail === 0) { - result += map3[bits >> 18 & 63]; - result += map3[bits >> 12 & 63]; - result += map3[bits >> 6 & 63]; - result += map3[bits & 63]; - } else if (tail === 2) { - result += map3[bits >> 10 & 63]; - result += map3[bits >> 4 & 63]; - result += map3[bits << 2 & 63]; - result += map3[64]; - } else if (tail === 1) { - result += map3[bits >> 2 & 63]; - result += map3[bits << 4 & 63]; - result += map3[64]; - result += map3[64]; + return result; } - return result; -} -function isBinary(obj) { - return Object.prototype.toString.call(obj) === "[object Uint8Array]"; -} -var binary = new type("tag:yaml.org,2002:binary", { - kind: "scalar", - resolve: resolveYamlBinary, - construct: constructYamlBinary, - predicate: isBinary, - represent: representYamlBinary -}); -var _hasOwnProperty$3 = Object.prototype.hasOwnProperty; -var _toString$2 = Object.prototype.toString; -function resolveYamlOmap(data) { - if (data === null) return true; - var objectKeys = [], index, length, pair, pairKey, pairHasKey, object2 = data; - for (index = 0, length = object2.length; index < length; index += 1) { - pair = object2[index]; - pairHasKey = false; - if (_toString$2.call(pair) !== "[object Object]") return false; - for (pairKey in pair) { - if (_hasOwnProperty$3.call(pair, pairKey)) { - if (!pairHasKey) pairHasKey = true; - else return false; - } - } - if (!pairHasKey) return false; - if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); - else return false; + function isBinary(obj) { + return Object.prototype.toString.call(obj) === "[object Uint8Array]"; } - return true; -} -function constructYamlOmap(data) { - return data !== null ? data : []; -} -var omap = new type("tag:yaml.org,2002:omap", { - kind: "sequence", - resolve: resolveYamlOmap, - construct: constructYamlOmap -}); -var _toString$1 = Object.prototype.toString; -function resolveYamlPairs(data) { - if (data === null) return true; - var index, length, pair, keys, result, object2 = data; - result = new Array(object2.length); - for (index = 0, length = object2.length; index < length; index += 1) { - pair = object2[index]; - if (_toString$1.call(pair) !== "[object Object]") return false; - keys = Object.keys(pair); - if (keys.length !== 1) return false; - result[index] = [keys[0], pair[keys[0]]]; + binary = new Type2("tag:yaml.org,2002:binary", { + kind: "scalar", + resolve: resolveYamlBinary, + construct: constructYamlBinary, + predicate: isBinary, + represent: representYamlBinary + }); + return binary; +} +var omap; +var hasRequiredOmap; +function requireOmap() { + if (hasRequiredOmap) return omap; + hasRequiredOmap = 1; + const Type2 = requireType(); + const _hasOwnProperty = Object.prototype.hasOwnProperty; + const _toString = Object.prototype.toString; + function resolveYamlOmap(data) { + if (data === null) return true; + const objectKeys = {}; + const object2 = data; + for (let index = 0, length = object2.length; index < length; index += 1) { + const pair = object2[index]; + let pairHasKey = false; + if (_toString.call(pair) !== "[object Object]") return false; + let pairKey; + for (pairKey in pair) { + if (_hasOwnProperty.call(pair, pairKey)) { + if (!pairHasKey) pairHasKey = true; + else return false; + } + } + if (!pairHasKey) return false; + if (_hasOwnProperty.call(objectKeys, pairKey)) return false; + Object.defineProperty(objectKeys, pairKey, { value: true }); + } + return true; } - return true; -} -function constructYamlPairs(data) { - if (data === null) return []; - var index, length, pair, keys, result, object2 = data; - result = new Array(object2.length); - for (index = 0, length = object2.length; index < length; index += 1) { - pair = object2[index]; - keys = Object.keys(pair); - result[index] = [keys[0], pair[keys[0]]]; + function constructYamlOmap(data) { + return data !== null ? data : []; } - return result; -} -var pairs = new type("tag:yaml.org,2002:pairs", { - kind: "sequence", - resolve: resolveYamlPairs, - construct: constructYamlPairs -}); -var _hasOwnProperty$2 = Object.prototype.hasOwnProperty; -function resolveYamlSet(data) { - if (data === null) return true; - var key, object2 = data; - for (key in object2) { - if (_hasOwnProperty$2.call(object2, key)) { - if (object2[key] !== null) return false; + omap = new Type2("tag:yaml.org,2002:omap", { + kind: "sequence", + resolve: resolveYamlOmap, + construct: constructYamlOmap + }); + return omap; +} +var pairs; +var hasRequiredPairs; +function requirePairs() { + if (hasRequiredPairs) return pairs; + hasRequiredPairs = 1; + const Type2 = requireType(); + const _toString = Object.prototype.toString; + function resolveYamlPairs(data) { + if (data === null) return true; + const object2 = data; + const result = new Array(object2.length); + for (let index = 0, length = object2.length; index < length; index += 1) { + const pair = object2[index]; + if (_toString.call(pair) !== "[object Object]") return false; + const keys = Object.keys(pair); + if (keys.length !== 1) return false; + result[index] = [keys[0], pair[keys[0]]]; } + return true; } - return true; -} -function constructYamlSet(data) { - return data !== null ? data : {}; -} -var set = new type("tag:yaml.org,2002:set", { - kind: "mapping", - resolve: resolveYamlSet, - construct: constructYamlSet -}); -var _default = core.extend({ - implicit: [ - timestamp, - merge - ], - explicit: [ - binary, - omap, - pairs, - set - ] -}); -var _hasOwnProperty$1 = Object.prototype.hasOwnProperty; -var CONTEXT_FLOW_IN = 1; -var CONTEXT_FLOW_OUT = 2; -var CONTEXT_BLOCK_IN = 3; -var CONTEXT_BLOCK_OUT = 4; -var CHOMPING_CLIP = 1; -var CHOMPING_STRIP = 2; -var CHOMPING_KEEP = 3; -var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; -var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; -var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; -var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; -var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; -function _class(obj) { - return Object.prototype.toString.call(obj); -} -function is_EOL(c) { - return c === 10 || c === 13; -} -function is_WHITE_SPACE(c) { - return c === 9 || c === 32; -} -function is_WS_OR_EOL(c) { - return c === 9 || c === 32 || c === 10 || c === 13; -} -function is_FLOW_INDICATOR(c) { - return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; -} -function fromHexCode(c) { - var lc; - if (48 <= c && c <= 57) { - return c - 48; + function constructYamlPairs(data) { + if (data === null) return []; + const object2 = data; + const result = new Array(object2.length); + for (let index = 0, length = object2.length; index < length; index += 1) { + const pair = object2[index]; + const keys = Object.keys(pair); + result[index] = [keys[0], pair[keys[0]]]; + } + return result; } - lc = c | 32; - if (97 <= lc && lc <= 102) { - return lc - 97 + 10; + pairs = new Type2("tag:yaml.org,2002:pairs", { + kind: "sequence", + resolve: resolveYamlPairs, + construct: constructYamlPairs + }); + return pairs; +} +var set; +var hasRequiredSet; +function requireSet() { + if (hasRequiredSet) return set; + hasRequiredSet = 1; + const Type2 = requireType(); + const _hasOwnProperty = Object.prototype.hasOwnProperty; + function resolveYamlSet(data) { + if (data === null) return true; + const object2 = data; + for (const key in object2) { + if (_hasOwnProperty.call(object2, key)) { + if (object2[key] !== null) return false; + } + } + return true; } - return -1; -} -function escapedHexLen(c) { - if (c === 120) { - return 2; + function constructYamlSet(data) { + return data !== null ? data : {}; } - if (c === 117) { - return 4; + set = new Type2("tag:yaml.org,2002:set", { + kind: "mapping", + resolve: resolveYamlSet, + construct: constructYamlSet + }); + return set; +} +var _default; +var hasRequired_default; +function require_default() { + if (hasRequired_default) return _default; + hasRequired_default = 1; + _default = requireCore().extend({ + implicit: [ + requireTimestamp(), + requireMerge() + ], + explicit: [ + requireBinary(), + requireOmap(), + requirePairs(), + requireSet() + ] + }); + return _default; +} +var hasRequiredLoader; +function requireLoader() { + if (hasRequiredLoader) return loader; + hasRequiredLoader = 1; + const common2 = requireCommon(); + const YAMLException2 = requireException(); + const makeSnippet = requireSnippet(); + const DEFAULT_SCHEMA2 = require_default(); + const _hasOwnProperty = Object.prototype.hasOwnProperty; + const CONTEXT_FLOW_IN = 1; + const CONTEXT_FLOW_OUT = 2; + const CONTEXT_BLOCK_IN = 3; + const CONTEXT_BLOCK_OUT = 4; + const CHOMPING_CLIP = 1; + const CHOMPING_STRIP = 2; + const CHOMPING_KEEP = 3; + const PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; + const PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; + const PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; + const PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; + const PATTERN_TAG_URI = /^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i; + function _class(obj) { + return Object.prototype.toString.call(obj); + } + function isEol(c) { + return c === 10 || c === 13; + } + function isWhiteSpace(c) { + return c === 9 || c === 32; + } + function isWsOrEol(c) { + return c === 9 || c === 32 || c === 10 || c === 13; + } + function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; + } + function fromHexCode(c) { + if (c >= 48 && c <= 57) { + return c - 48; + } + const lc = c | 32; + if (lc >= 97 && lc <= 102) { + return lc - 97 + 10; + } + return -1; + } + function escapedHexLen(c) { + if (c === 120) { + return 2; + } + if (c === 117) { + return 4; + } + if (c === 85) { + return 8; + } + return 0; + } + function fromDecimalCode(c) { + if (c >= 48 && c <= 57) { + return c - 48; + } + return -1; + } + function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } } - if (c === 85) { - return 8; + function charFromCodepoint(c) { + if (c <= 65535) { + return String.fromCharCode(c); + } + return String.fromCharCode( + (c - 65536 >> 10) + 55296, + (c - 65536 & 1023) + 56320 + ); } - return 0; -} -function fromDecimalCode(c) { - if (48 <= c && c <= 57) { - return c - 48; + function setProperty(object2, key, value) { + if (key === "__proto__") { + Object.defineProperty(object2, key, { + configurable: true, + enumerable: true, + writable: true, + value + }); + } else { + object2[key] = value; + } + } + const simpleEscapeCheck = new Array(256); + const simpleEscapeMap = new Array(256); + for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); + } + function State(input, options) { + this.input = input; + this.filename = options["filename"] || null; + this.schema = options["schema"] || DEFAULT_SCHEMA2; + this.onWarning = options["onWarning"] || null; + this.legacy = options["legacy"] || false; + this.json = options["json"] || false; + this.listener = options["listener"] || null; + this.maxDepth = typeof options["maxDepth"] === "number" ? options["maxDepth"] : 100; + this.maxTotalMergeKeys = typeof options["maxTotalMergeKeys"] === "number" ? options["maxTotalMergeKeys"] : 1e4; + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; + this.depth = 0; + this.totalMergeKeys = 0; + this.firstTabInLine = -1; + this.documents = []; + this.anchorMapTransactions = []; + } + function generateError(state, message) { + const mark = { + name: state.filename, + buffer: state.input.slice(0, -1), + // omit trailing \0 + position: state.position, + line: state.line, + column: state.position - state.lineStart + }; + mark.snippet = makeSnippet(mark); + return new YAMLException2(message, mark); } - return -1; -} -function simpleEscapeSequence(c) { - return c === 48 ? "\0" : c === 97 ? "\x07" : c === 98 ? "\b" : c === 116 ? " " : c === 9 ? " " : c === 110 ? "\n" : c === 118 ? "\v" : c === 102 ? "\f" : c === 114 ? "\r" : c === 101 ? "\x1B" : c === 32 ? " " : c === 34 ? '"' : c === 47 ? "/" : c === 92 ? "\\" : c === 78 ? "\x85" : c === 95 ? "\xA0" : c === 76 ? "\u2028" : c === 80 ? "\u2029" : ""; -} -function charFromCodepoint(c) { - if (c <= 65535) { - return String.fromCharCode(c); + function throwError(state, message) { + throw generateError(state, message); } - return String.fromCharCode( - (c - 65536 >> 10) + 55296, - (c - 65536 & 1023) + 56320 - ); -} -function setProperty(object2, key, value) { - if (key === "__proto__") { - Object.defineProperty(object2, key, { - configurable: true, - enumerable: true, - writable: true, - value - }); - } else { - object2[key] = value; - } -} -var simpleEscapeCheck = new Array(256); -var simpleEscapeMap = new Array(256); -for (i = 0; i < 256; i++) { - simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; - simpleEscapeMap[i] = simpleEscapeSequence(i); -} -var i; -function State$1(input, options) { - this.input = input; - this.filename = options["filename"] || null; - this.schema = options["schema"] || _default; - this.onWarning = options["onWarning"] || null; - this.legacy = options["legacy"] || false; - this.json = options["json"] || false; - this.listener = options["listener"] || null; - this.implicitTypes = this.schema.compiledImplicit; - this.typeMap = this.schema.compiledTypeMap; - this.length = input.length; - this.position = 0; - this.line = 0; - this.lineStart = 0; - this.lineIndent = 0; - this.firstTabInLine = -1; - this.documents = []; -} -function generateError(state, message) { - var mark = { - name: state.filename, - buffer: state.input.slice(0, -1), - // omit trailing \0 - position: state.position, - line: state.line, - column: state.position - state.lineStart - }; - mark.snippet = snippet(mark); - return new exception(message, mark); -} -function throwError(state, message) { - throw generateError(state, message); -} -function throwWarning(state, message) { - if (state.onWarning) { - state.onWarning.call(null, generateError(state, message)); - } -} -var directiveHandlers = { - YAML: function handleYamlDirective(state, name, args) { - var match, major, minor; - if (state.version !== null) { - throwError(state, "duplication of %YAML directive"); - } - if (args.length !== 1) { - throwError(state, "YAML directive accepts exactly one argument"); - } - match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); - if (match === null) { - throwError(state, "ill-formed argument of the YAML directive"); - } - major = parseInt(match[1], 10); - minor = parseInt(match[2], 10); - if (major !== 1) { - throwError(state, "unacceptable YAML version of the document"); - } - state.version = args[0]; - state.checkLineBreaks = minor < 2; - if (minor !== 1 && minor !== 2) { - throwWarning(state, "unsupported YAML version of the document"); - } - }, - TAG: function handleTagDirective(state, name, args) { - var handle, prefix; - if (args.length !== 2) { - throwError(state, "TAG directive accepts exactly two arguments"); + function throwWarning(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError(state, message)); } - handle = args[0]; - prefix = args[1]; - if (!PATTERN_TAG_HANDLE.test(handle)) { - throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); - } - if (_hasOwnProperty$1.call(state.tagMap, handle)) { - throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); - } - if (!PATTERN_TAG_URI.test(prefix)) { - throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); - } - try { - prefix = decodeURIComponent(prefix); - } catch (err) { - throwError(state, "tag prefix is malformed: " + prefix); - } - state.tagMap[handle] = prefix; } -}; -function captureSegment(state, start, end, checkJson) { - var _position, _length2, _character, _result; - if (start < end) { - _result = state.input.slice(start, end); - if (checkJson) { - for (_position = 0, _length2 = _result.length; _position < _length2; _position += 1) { - _character = _result.charCodeAt(_position); - if (!(_character === 9 || 32 <= _character && _character <= 1114111)) { - throwError(state, "expected valid JSON character"); - } + function storeAnchor(state, name, value) { + const transactions = state.anchorMapTransactions; + if (transactions.length !== 0) { + const transaction = transactions[transactions.length - 1]; + if (!_hasOwnProperty.call(transaction, name)) { + transaction[name] = { + existed: _hasOwnProperty.call(state.anchorMap, name), + value: state.anchorMap[name] + }; } - } else if (PATTERN_NON_PRINTABLE.test(_result)) { - throwError(state, "the stream contains non-printable characters"); } - state.result += _result; + state.anchorMap[name] = value; } -} -function mergeMappings(state, destination, source, overridableKeys) { - var sourceKeys, key, index, quantity; - if (!common.isObject(source)) { - throwError(state, "cannot merge mappings; the provided source object is unacceptable"); + function beginAnchorTransaction(state) { + state.anchorMapTransactions.push(/* @__PURE__ */ Object.create(null)); } - sourceKeys = Object.keys(source); - for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { - key = sourceKeys[index]; - if (!_hasOwnProperty$1.call(destination, key)) { - setProperty(destination, key, source[key]); - overridableKeys[key] = true; + function commitAnchorTransaction(state) { + const transaction = state.anchorMapTransactions.pop(); + const transactions = state.anchorMapTransactions; + if (transactions.length === 0) return; + const parent = transactions[transactions.length - 1]; + const names = Object.keys(transaction); + for (let index = 0, length = names.length; index < length; index += 1) { + const name = names[index]; + if (!_hasOwnProperty.call(parent, name)) { + parent[name] = transaction[name]; + } } } -} -function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) { - var index, quantity; - if (Array.isArray(keyNode)) { - keyNode = Array.prototype.slice.call(keyNode); - for (index = 0, quantity = keyNode.length; index < quantity; index += 1) { - if (Array.isArray(keyNode[index])) { - throwError(state, "nested arrays are not supported inside keys"); - } - if (typeof keyNode === "object" && _class(keyNode[index]) === "[object Object]") { - keyNode[index] = "[object Object]"; + function rollbackAnchorTransaction(state) { + const transaction = state.anchorMapTransactions.pop(); + const names = Object.keys(transaction); + for (let index = names.length - 1; index >= 0; index -= 1) { + const entry = transaction[names[index]]; + if (entry.existed) { + state.anchorMap[names[index]] = entry.value; + } else { + delete state.anchorMap[names[index]]; } } } - if (typeof keyNode === "object" && _class(keyNode) === "[object Object]") { - keyNode = "[object Object]"; - } - keyNode = String(keyNode); - if (_result === null) { - _result = {}; + function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + tag: state.tag, + anchor: state.anchor, + kind: state.kind, + result: state.result + }; } - if (keyTag === "tag:yaml.org,2002:merge") { - if (Array.isArray(valueNode)) { - for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { - mergeMappings(state, _result, valueNode[index], overridableKeys); + function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.tag = snapshot.tag; + state.anchor = snapshot.anchor; + state.kind = snapshot.kind; + state.result = snapshot.result; + } + const directiveHandlers = { + YAML: function handleYamlDirective(state, name, args) { + if (state.version !== null) { + throwError(state, "duplication of %YAML directive"); + } + if (args.length !== 1) { + throwError(state, "YAML directive accepts exactly one argument"); + } + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) { + throwError(state, "ill-formed argument of the YAML directive"); + } + const major = parseInt(match[1], 10); + const minor = parseInt(match[2], 10); + if (major !== 1) { + throwError(state, "unacceptable YAML version of the document"); + } + state.version = args[0]; + state.checkLineBreaks = minor < 2; + if (minor !== 1 && minor !== 2) { + throwWarning(state, "unsupported YAML version of the document"); } - } else { - mergeMappings(state, _result, valueNode, overridableKeys); + }, + TAG: function handleTagDirective(state, name, args) { + let prefix; + if (args.length !== 2) { + throwError(state, "TAG directive accepts exactly two arguments"); + } + const handle = args[0]; + prefix = args[1]; + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + } + if (_hasOwnProperty.call(state.tagMap, handle)) { + throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); + } + if (!PATTERN_TAG_URI.test(prefix)) { + throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + } + try { + prefix = decodeURIComponent(prefix); + } catch (err) { + throwError(state, "tag prefix is malformed: " + prefix); + } + state.tagMap[handle] = prefix; } - } else { - if (!state.json && !_hasOwnProperty$1.call(overridableKeys, keyNode) && _hasOwnProperty$1.call(_result, keyNode)) { - state.line = startLine || state.line; - state.lineStart = startLineStart || state.lineStart; - state.position = startPos || state.position; - throwError(state, "duplicated mapping key"); + }; + function captureSegment(state, start, end, checkJson) { + if (start < end) { + const _result = state.input.slice(start, end); + if (checkJson) { + for (let _position = 0, _length2 = _result.length; _position < _length2; _position += 1) { + const _character = _result.charCodeAt(_position); + if (!(_character === 9 || _character >= 32 && _character <= 1114111)) { + throwError(state, "expected valid JSON character"); + } + } + } else if (PATTERN_NON_PRINTABLE.test(_result)) { + throwError(state, "the stream contains non-printable characters"); + } + state.result += _result; } - setProperty(_result, keyNode, valueNode); - delete overridableKeys[keyNode]; } - return _result; -} -function readLineBreak(state) { - var ch; - ch = state.input.charCodeAt(state.position); - if (ch === 10) { - state.position++; - } else if (ch === 13) { - state.position++; - if (state.input.charCodeAt(state.position) === 10) { - state.position++; + function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) { + throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")"); } - } else { - throwError(state, "a line break is expected"); } - state.line += 1; - state.lineStart = state.position; - state.firstTabInLine = -1; -} -function skipSeparationSpace(state, allowComments, checkIndent) { - var lineBreaks = 0, ch = state.input.charCodeAt(state.position); - while (ch !== 0) { - while (is_WHITE_SPACE(ch)) { - if (ch === 9 && state.firstTabInLine === -1) { - state.firstTabInLine = state.position; + function mergeMappings(state, destination, source, overridableKeys) { + if (!common2.isObject(source)) { + throwError(state, "cannot merge mappings; the provided source object is unacceptable"); + } + chargeMergeWork(state); + const sourceKeys = Object.keys(source); + for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + const key = sourceKeys[index]; + chargeMergeWork(state); + if (!_hasOwnProperty.call(destination, key)) { + setProperty(destination, key, source[key]); + overridableKeys[key] = true; } - ch = state.input.charCodeAt(++state.position); } - if (allowComments && ch === 35) { - do { - ch = state.input.charCodeAt(++state.position); - } while (ch !== 10 && ch !== 13 && ch !== 0); + } + function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) { + if (Array.isArray(keyNode)) { + keyNode = Array.prototype.slice.call(keyNode); + for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) { + if (Array.isArray(keyNode[index])) { + throwError(state, "nested arrays are not supported inside keys"); + } + if (typeof keyNode === "object" && _class(keyNode[index]) === "[object Object]") { + keyNode[index] = "[object Object]"; + } + } } - if (is_EOL(ch)) { - readLineBreak(state); - ch = state.input.charCodeAt(state.position); - lineBreaks++; - state.lineIndent = 0; - while (ch === 32) { - state.lineIndent++; - ch = state.input.charCodeAt(++state.position); + if (typeof keyNode === "object" && _class(keyNode) === "[object Object]") { + keyNode = "[object Object]"; + } + keyNode = String(keyNode); + if (_result === null) { + _result = {}; + } + if (keyTag === "tag:yaml.org,2002:merge") { + if (Array.isArray(valueNode)) { + if (valueNode.length > 100) { + throwError(state, "abnormal merge sequence size"); + } + for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings(state, _result, valueNode[index], overridableKeys); + } + } else { + mergeMappings(state, _result, valueNode, overridableKeys); } } else { - break; + if (!state.json && !_hasOwnProperty.call(overridableKeys, keyNode) && _hasOwnProperty.call(_result, keyNode)) { + state.line = startLine || state.line; + state.lineStart = startLineStart || state.lineStart; + state.position = startPos || state.position; + throwError(state, "duplicated mapping key"); + } + setProperty(_result, keyNode, valueNode); + delete overridableKeys[keyNode]; } + return _result; } - if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { - throwWarning(state, "deficient indentation"); - } - return lineBreaks; -} -function testDocumentSeparator(state) { - var _position = state.position, ch; - ch = state.input.charCodeAt(_position); - if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) { - _position += 3; - ch = state.input.charCodeAt(_position); - if (ch === 0 || is_WS_OR_EOL(ch)) { - return true; + function readLineBreak(state) { + const ch = state.input.charCodeAt(state.position); + if (ch === 10) { + state.position++; + } else if (ch === 13) { + state.position++; + if (state.input.charCodeAt(state.position) === 10) { + state.position++; + } + } else { + throwError(state, "a line break is expected"); } + state.line += 1; + state.lineStart = state.position; + state.firstTabInLine = -1; } - return false; -} -function writeFoldedLines(state, count) { - if (count === 1) { - state.result += " "; - } else if (count > 1) { - state.result += common.repeat("\n", count - 1); + function skipSeparationSpace(state, allowComments, checkIndent) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + if (ch === 9 && state.firstTabInLine === -1) { + state.firstTabInLine = state.position; + } + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && ch === 35) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 10 && ch !== 13 && ch !== 0); + } + if (isEol(ch)) { + readLineBreak(state); + ch = state.input.charCodeAt(state.position); + lineBreaks++; + state.lineIndent = 0; + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } else { + break; + } + } + if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) { + throwWarning(state, "deficient indentation"); + } + return lineBreaks; } -} -function readPlainScalar(state, nodeIndent, withinFlowCollection) { - var preceding, following, captureStart, captureEnd, hasPendingContent, _line, _lineStart, _lineIndent, _kind = state.kind, _result = state.result, ch; - ch = state.input.charCodeAt(state.position); - if (is_WS_OR_EOL(ch) || is_FLOW_INDICATOR(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96) { + function testDocumentSeparator(state) { + let _position = state.position; + let ch = state.input.charCodeAt(_position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) { + _position += 3; + ch = state.input.charCodeAt(_position); + if (ch === 0 || isWsOrEol(ch)) { + return true; + } + } return false; } - if (ch === 63 || ch === 45) { - following = state.input.charCodeAt(state.position + 1); - if (is_WS_OR_EOL(following) || withinFlowCollection && is_FLOW_INDICATOR(following)) { + function writeFoldedLines(state, count) { + if (count === 1) { + state.result += " "; + } else if (count > 1) { + state.result += common2.repeat("\n", count - 1); + } + } + function readPlainScalar(state, nodeIndent, withinFlowCollection) { + let captureStart; + let captureEnd; + let hasPendingContent; + let _line; + let _lineStart; + let _lineIndent; + const _kind = state.kind; + const _result = state.result; + let ch = state.input.charCodeAt(state.position); + if (isWsOrEol(ch) || isFlowIndicator(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96) { return false; } - } - state.kind = "scalar"; - state.result = ""; - captureStart = captureEnd = state.position; - hasPendingContent = false; - while (ch !== 0) { - if (ch === 58) { - following = state.input.charCodeAt(state.position + 1); - if (is_WS_OR_EOL(following) || withinFlowCollection && is_FLOW_INDICATOR(following)) { - break; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) { + return false; } - } else if (ch === 35) { - preceding = state.input.charCodeAt(state.position - 1); - if (is_WS_OR_EOL(preceding)) { + } + state.kind = "scalar"; + state.result = ""; + captureStart = captureEnd = state.position; + hasPendingContent = false; + while (ch !== 0) { + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) { + break; + } + } else if (ch === 35) { + const preceding = state.input.charCodeAt(state.position - 1); + if (isWsOrEol(preceding)) { + break; + } + } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && isFlowIndicator(ch)) { break; + } else if (isEol(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace(state, false, -1); + if (state.lineIndent >= nodeIndent) { + hasPendingContent = true; + ch = state.input.charCodeAt(state.position); + continue; + } else { + state.position = captureEnd; + state.line = _line; + state.lineStart = _lineStart; + state.lineIndent = _lineIndent; + break; + } } - } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && is_FLOW_INDICATOR(ch)) { - break; - } else if (is_EOL(ch)) { - _line = state.line; - _lineStart = state.lineStart; - _lineIndent = state.lineIndent; - skipSeparationSpace(state, false, -1); - if (state.lineIndent >= nodeIndent) { - hasPendingContent = true; - ch = state.input.charCodeAt(state.position); - continue; - } else { - state.position = captureEnd; - state.line = _line; - state.lineStart = _lineStart; - state.lineIndent = _lineIndent; - break; + if (hasPendingContent) { + captureSegment(state, captureStart, captureEnd, false); + writeFoldedLines(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; } + if (!isWhiteSpace(ch)) { + captureEnd = state.position + 1; + } + ch = state.input.charCodeAt(++state.position); } - if (hasPendingContent) { - captureSegment(state, captureStart, captureEnd, false); - writeFoldedLines(state, state.line - _line); - captureStart = captureEnd = state.position; - hasPendingContent = false; - } - if (!is_WHITE_SPACE(ch)) { - captureEnd = state.position + 1; + captureSegment(state, captureStart, captureEnd, false); + if (state.result) { + return true; } - ch = state.input.charCodeAt(++state.position); - } - captureSegment(state, captureStart, captureEnd, false); - if (state.result) { - return true; - } - state.kind = _kind; - state.result = _result; - return false; -} -function readSingleQuotedScalar(state, nodeIndent) { - var ch, captureStart, captureEnd; - ch = state.input.charCodeAt(state.position); - if (ch !== 39) { + state.kind = _kind; + state.result = _result; return false; } - state.kind = "scalar"; - state.result = ""; - state.position++; - captureStart = captureEnd = state.position; - while ((ch = state.input.charCodeAt(state.position)) !== 0) { - if (ch === 39) { - captureSegment(state, captureStart, state.position, true); - ch = state.input.charCodeAt(++state.position); + function readSingleQuotedScalar(state, nodeIndent) { + let captureStart; + let captureEnd; + let ch = state.input.charCodeAt(state.position); + if (ch !== 39) { + return false; + } + state.kind = "scalar"; + state.result = ""; + state.position++; + captureStart = captureEnd = state.position; + while ((ch = state.input.charCodeAt(state.position)) !== 0) { if (ch === 39) { - captureStart = state.position; - state.position++; - captureEnd = state.position; + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + if (ch === 39) { + captureStart = state.position; + state.position++; + captureEnd = state.position; + } else { + return true; + } + } else if (isEol(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, "unexpected end of the document within a single quoted scalar"); } else { - return true; + state.position++; + if (!isWhiteSpace(ch)) { + captureEnd = state.position; + } } - } else if (is_EOL(ch)) { - captureSegment(state, captureStart, captureEnd, true); - writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); - captureStart = captureEnd = state.position; - } else if (state.position === state.lineStart && testDocumentSeparator(state)) { - throwError(state, "unexpected end of the document within a single quoted scalar"); - } else { - state.position++; - captureEnd = state.position; } + throwError(state, "unexpected end of the stream within a single quoted scalar"); } - throwError(state, "unexpected end of the stream within a single quoted scalar"); -} -function readDoubleQuotedScalar(state, nodeIndent) { - var captureStart, captureEnd, hexLength, hexResult, tmp, ch; - ch = state.input.charCodeAt(state.position); - if (ch !== 34) { - return false; - } - state.kind = "scalar"; - state.result = ""; - state.position++; - captureStart = captureEnd = state.position; - while ((ch = state.input.charCodeAt(state.position)) !== 0) { - if (ch === 34) { - captureSegment(state, captureStart, state.position, true); - state.position++; - return true; - } else if (ch === 92) { - captureSegment(state, captureStart, state.position, true); - ch = state.input.charCodeAt(++state.position); - if (is_EOL(ch)) { - skipSeparationSpace(state, false, nodeIndent); - } else if (ch < 256 && simpleEscapeCheck[ch]) { - state.result += simpleEscapeMap[ch]; + function readDoubleQuotedScalar(state, nodeIndent) { + let captureStart; + let captureEnd; + let tmp; + let ch = state.input.charCodeAt(state.position); + if (ch !== 34) { + return false; + } + state.kind = "scalar"; + state.result = ""; + state.position++; + captureStart = captureEnd = state.position; + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + if (ch === 34) { + captureSegment(state, captureStart, state.position, true); state.position++; - } else if ((tmp = escapedHexLen(ch)) > 0) { - hexLength = tmp; - hexResult = 0; - for (; hexLength > 0; hexLength--) { - ch = state.input.charCodeAt(++state.position); - if ((tmp = fromHexCode(ch)) >= 0) { - hexResult = (hexResult << 4) + tmp; - } else { - throwError(state, "expected hexadecimal character"); + return true; + } else if (ch === 92) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + if (isEol(ch)) { + skipSeparationSpace(state, false, nodeIndent); + } else if (ch < 256 && simpleEscapeCheck[ch]) { + state.result += simpleEscapeMap[ch]; + state.position++; + } else if ((tmp = escapedHexLen(ch)) > 0) { + let hexLength = tmp; + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); + if ((tmp = fromHexCode(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; + } else { + throwError(state, "expected hexadecimal character"); + } } + state.result += charFromCodepoint(hexResult); + state.position++; + } else { + throwError(state, "unknown escape sequence"); } - state.result += charFromCodepoint(hexResult); - state.position++; + captureStart = captureEnd = state.position; + } else if (isEol(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, "unexpected end of the document within a double quoted scalar"); } else { - throwError(state, "unknown escape sequence"); - } - captureStart = captureEnd = state.position; - } else if (is_EOL(ch)) { - captureSegment(state, captureStart, captureEnd, true); - writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); - captureStart = captureEnd = state.position; - } else if (state.position === state.lineStart && testDocumentSeparator(state)) { - throwError(state, "unexpected end of the document within a double quoted scalar"); + state.position++; + if (!isWhiteSpace(ch)) { + captureEnd = state.position; + } + } + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); + } + function readFlowCollection(state, nodeIndent) { + let readNext = true; + let _line; + let _lineStart; + let _pos; + const _tag = state.tag; + let _result; + const _anchor = state.anchor; + let terminator; + let isPair; + let isExplicitPair; + let isMapping; + const overridableKeys = /* @__PURE__ */ Object.create(null); + let keyNode; + let keyTag; + let valueNode; + let ch = state.input.charCodeAt(state.position); + if (ch === 91) { + terminator = 93; + isMapping = false; + _result = []; + } else if (ch === 123) { + terminator = 125; + isMapping = true; + _result = {}; } else { - state.position++; - captureEnd = state.position; - } - } - throwError(state, "unexpected end of the stream within a double quoted scalar"); -} -function readFlowCollection(state, nodeIndent) { - var readNext = true, _line, _lineStart, _pos, _tag = state.tag, _result, _anchor = state.anchor, following, terminator, isPair, isExplicitPair, isMapping, overridableKeys = /* @__PURE__ */ Object.create(null), keyNode, keyTag, valueNode, ch; - ch = state.input.charCodeAt(state.position); - if (ch === 91) { - terminator = 93; - isMapping = false; - _result = []; - } else if (ch === 123) { - terminator = 125; - isMapping = true; - _result = {}; - } else { - return false; - } - if (state.anchor !== null) { - state.anchorMap[state.anchor] = _result; - } - ch = state.input.charCodeAt(++state.position); - while (ch !== 0) { - skipSeparationSpace(state, true, nodeIndent); - ch = state.input.charCodeAt(state.position); - if (ch === terminator) { - state.position++; - state.tag = _tag; - state.anchor = _anchor; - state.kind = isMapping ? "mapping" : "sequence"; - state.result = _result; - return true; - } else if (!readNext) { - throwError(state, "missed comma between flow collection entries"); - } else if (ch === 44) { - throwError(state, "expected the node content, but found ','"); - } - keyTag = keyNode = valueNode = null; - isPair = isExplicitPair = false; - if (ch === 63) { - following = state.input.charCodeAt(state.position + 1); - if (is_WS_OR_EOL(following)) { - isPair = isExplicitPair = true; + return false; + } + if (state.anchor !== null) { + storeAnchor(state, state.anchor, _result); + } + ch = state.input.charCodeAt(++state.position); + while (ch !== 0) { + skipSeparationSpace(state, true, nodeIndent); + ch = state.input.charCodeAt(state.position); + if (ch === terminator) { state.position++; + state.tag = _tag; + state.anchor = _anchor; + state.kind = isMapping ? "mapping" : "sequence"; + state.result = _result; + return true; + } else if (!readNext) { + throwError(state, "missed comma between flow collection entries"); + } else if (ch === 44) { + throwError(state, "expected the node content, but found ','"); + } + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + if (ch === 63) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEol(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace(state, true, nodeIndent); + } + } + _line = state.line; + _lineStart = state.lineStart; + _pos = state.position; + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace(state, true, nodeIndent); + ch = state.input.charCodeAt(state.position); + if ((isExplicitPair || state.line === _line) && ch === 58) { + isPair = true; + ch = state.input.charCodeAt(++state.position); skipSeparationSpace(state, true, nodeIndent); + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + valueNode = state.result; + } + if (isMapping) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos); + } else if (isPair) { + _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)); + } else { + _result.push(keyNode); } - } - _line = state.line; - _lineStart = state.lineStart; - _pos = state.position; - composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); - keyTag = state.tag; - keyNode = state.result; - skipSeparationSpace(state, true, nodeIndent); - ch = state.input.charCodeAt(state.position); - if ((isExplicitPair || state.line === _line) && ch === 58) { - isPair = true; - ch = state.input.charCodeAt(++state.position); skipSeparationSpace(state, true, nodeIndent); - composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); - valueNode = state.result; - } - if (isMapping) { - storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos); - } else if (isPair) { - _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)); + ch = state.input.charCodeAt(state.position); + if (ch === 44) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } + throwError(state, "unexpected end of the stream within a flow collection"); + } + function readBlockScalar(state, nodeIndent) { + let folding; + let chomping = CHOMPING_CLIP; + let didReadContent = false; + let detectedIndent = false; + let textIndent = nodeIndent; + let emptyLines = 0; + let atMoreIndented = false; + let tmp; + let ch = state.input.charCodeAt(state.position); + if (ch === 124) { + folding = false; + } else if (ch === 62) { + folding = true; } else { - _result.push(keyNode); + return false; } - skipSeparationSpace(state, true, nodeIndent); - ch = state.input.charCodeAt(state.position); - if (ch === 44) { - readNext = true; + state.kind = "scalar"; + state.result = ""; + while (ch !== 0) { ch = state.input.charCodeAt(++state.position); - } else { - readNext = false; - } - } - throwError(state, "unexpected end of the stream within a flow collection"); -} -function readBlockScalar(state, nodeIndent) { - var captureStart, folding, chomping = CHOMPING_CLIP, didReadContent = false, detectedIndent = false, textIndent = nodeIndent, emptyLines = 0, atMoreIndented = false, tmp, ch; - ch = state.input.charCodeAt(state.position); - if (ch === 124) { - folding = false; - } else if (ch === 62) { - folding = true; - } else { - return false; - } - state.kind = "scalar"; - state.result = ""; - while (ch !== 0) { - ch = state.input.charCodeAt(++state.position); - if (ch === 43 || ch === 45) { - if (CHOMPING_CLIP === chomping) { - chomping = ch === 43 ? CHOMPING_KEEP : CHOMPING_STRIP; - } else { - throwError(state, "repeat of a chomping mode identifier"); - } - } else if ((tmp = fromDecimalCode(ch)) >= 0) { - if (tmp === 0) { - throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); - } else if (!detectedIndent) { - textIndent = nodeIndent + tmp - 1; - detectedIndent = true; + if (ch === 43 || ch === 45) { + if (CHOMPING_CLIP === chomping) { + chomping = ch === 43 ? CHOMPING_KEEP : CHOMPING_STRIP; + } else { + throwError(state, "repeat of a chomping mode identifier"); + } + } else if ((tmp = fromDecimalCode(ch)) >= 0) { + if (tmp === 0) { + throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + } else if (!detectedIndent) { + textIndent = nodeIndent + tmp - 1; + detectedIndent = true; + } else { + throwError(state, "repeat of an indentation width identifier"); + } } else { - throwError(state, "repeat of an indentation width identifier"); + break; } - } else { - break; } - } - if (is_WHITE_SPACE(ch)) { - do { - ch = state.input.charCodeAt(++state.position); - } while (is_WHITE_SPACE(ch)); - if (ch === 35) { + if (isWhiteSpace(ch)) { do { ch = state.input.charCodeAt(++state.position); - } while (!is_EOL(ch) && ch !== 0); - } - } - while (ch !== 0) { - readLineBreak(state); - state.lineIndent = 0; - ch = state.input.charCodeAt(state.position); - while ((!detectedIndent || state.lineIndent < textIndent) && ch === 32) { - state.lineIndent++; - ch = state.input.charCodeAt(++state.position); - } - if (!detectedIndent && state.lineIndent > textIndent) { - textIndent = state.lineIndent; - } - if (is_EOL(ch)) { - emptyLines++; - continue; + } while (isWhiteSpace(ch)); + if (ch === 35) { + do { + ch = state.input.charCodeAt(++state.position); + } while (!isEol(ch) && ch !== 0); + } } - if (state.lineIndent < textIndent) { - if (chomping === CHOMPING_KEEP) { - state.result += common.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); - } else if (chomping === CHOMPING_CLIP) { - if (didReadContent) { - state.result += "\n"; + while (ch !== 0) { + readLineBreak(state); + state.lineIndent = 0; + ch = state.input.charCodeAt(state.position); + while ((!detectedIndent || state.lineIndent < textIndent) && ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } + if (isEol(ch)) { + emptyLines++; + continue; + } + if (!detectedIndent && textIndent === 0) { + throwError(state, "missing indentation for block scalar"); + } + if (state.lineIndent < textIndent) { + if (chomping === CHOMPING_KEEP) { + state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); + } else if (chomping === CHOMPING_CLIP) { + if (didReadContent) { + state.result += "\n"; + } } + break; } - break; - } - if (folding) { - if (is_WHITE_SPACE(ch)) { - atMoreIndented = true; - state.result += common.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); - } else if (atMoreIndented) { - atMoreIndented = false; - state.result += common.repeat("\n", emptyLines + 1); - } else if (emptyLines === 0) { - if (didReadContent) { - state.result += " "; + if (folding) { + if (isWhiteSpace(ch)) { + atMoreIndented = true; + state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common2.repeat("\n", emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) { + state.result += " "; + } + } else { + state.result += common2.repeat("\n", emptyLines); } } else { - state.result += common.repeat("\n", emptyLines); + state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); } - } else { - state.result += common.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines); - } - didReadContent = true; - detectedIndent = true; - emptyLines = 0; - captureStart = state.position; - while (!is_EOL(ch) && ch !== 0) { - ch = state.input.charCodeAt(++state.position); - } - captureSegment(state, captureStart, state.position, false); - } - return true; -} -function readBlockSequence(state, nodeIndent) { - var _line, _tag = state.tag, _anchor = state.anchor, _result = [], following, detected = false, ch; - if (state.firstTabInLine !== -1) return false; - if (state.anchor !== null) { - state.anchorMap[state.anchor] = _result; - } - ch = state.input.charCodeAt(state.position); - while (ch !== 0) { - if (state.firstTabInLine !== -1) { - state.position = state.firstTabInLine; - throwError(state, "tab characters must not be used in indentation"); - } - if (ch !== 45) { - break; - } - following = state.input.charCodeAt(state.position + 1); - if (!is_WS_OR_EOL(following)) { - break; - } - detected = true; - state.position++; - if (skipSeparationSpace(state, true, -1)) { - if (state.lineIndent <= nodeIndent) { - _result.push(null); - ch = state.input.charCodeAt(state.position); - continue; + didReadContent = true; + detectedIndent = true; + emptyLines = 0; + const captureStart = state.position; + while (!isEol(ch) && ch !== 0) { + ch = state.input.charCodeAt(++state.position); } + captureSegment(state, captureStart, state.position, false); } - _line = state.line; - composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); - _result.push(state.result); - skipSeparationSpace(state, true, -1); - ch = state.input.charCodeAt(state.position); - if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) { - throwError(state, "bad indentation of a sequence entry"); - } else if (state.lineIndent < nodeIndent) { - break; - } - } - if (detected) { - state.tag = _tag; - state.anchor = _anchor; - state.kind = "sequence"; - state.result = _result; return true; } - return false; -} -function readBlockMapping(state, nodeIndent, flowIndent) { - var following, allowCompact, _line, _keyLine, _keyLineStart, _keyPos, _tag = state.tag, _anchor = state.anchor, _result = {}, overridableKeys = /* @__PURE__ */ Object.create(null), keyTag = null, keyNode = null, valueNode = null, atExplicitKey = false, detected = false, ch; - if (state.firstTabInLine !== -1) return false; - if (state.anchor !== null) { - state.anchorMap[state.anchor] = _result; - } - ch = state.input.charCodeAt(state.position); - while (ch !== 0) { - if (!atExplicitKey && state.firstTabInLine !== -1) { - state.position = state.firstTabInLine; - throwError(state, "tab characters must not be used in indentation"); - } - following = state.input.charCodeAt(state.position + 1); - _line = state.line; - if ((ch === 63 || ch === 58) && is_WS_OR_EOL(following)) { - if (ch === 63) { - if (atExplicitKey) { - storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); - keyTag = keyNode = valueNode = null; - } - detected = true; - atExplicitKey = true; - allowCompact = true; - } else if (atExplicitKey) { - atExplicitKey = false; - allowCompact = true; - } else { - throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"); + function readBlockSequence(state, nodeIndent) { + const _tag = state.tag; + const _anchor = state.anchor; + const _result = []; + let detected = false; + if (state.firstTabInLine !== -1) return false; + if (state.anchor !== null) { + storeAnchor(state, state.anchor, _result); + } + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); } - state.position += 1; - ch = following; - } else { - _keyLine = state.line; - _keyLineStart = state.lineStart; - _keyPos = state.position; - if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + if (ch !== 45) { break; } - if (state.line === _line) { - ch = state.input.charCodeAt(state.position); - while (is_WHITE_SPACE(ch)) { - ch = state.input.charCodeAt(++state.position); + const following = state.input.charCodeAt(state.position + 1); + if (!isWsOrEol(following)) { + break; + } + detected = true; + state.position++; + if (skipSeparationSpace(state, true, -1)) { + if (state.lineIndent <= nodeIndent) { + _result.push(null); + ch = state.input.charCodeAt(state.position); + continue; } - if (ch === 58) { - ch = state.input.charCodeAt(++state.position); - if (!is_WS_OR_EOL(ch)) { - throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); - } + } + const _line = state.line; + composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + _result.push(state.result); + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) { + throwError(state, "bad indentation of a sequence entry"); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = "sequence"; + state.result = _result; + return true; + } + return false; + } + function readBlockMapping(state, nodeIndent, flowIndent) { + let allowCompact; + let _keyLine; + let _keyLineStart; + let _keyPos; + const _tag = state.tag; + const _anchor = state.anchor; + const _result = {}; + const overridableKeys = /* @__PURE__ */ Object.create(null); + let keyTag = null; + let keyNode = null; + let valueNode = null; + let atExplicitKey = false; + let detected = false; + if (state.firstTabInLine !== -1) return false; + if (state.anchor !== null) { + storeAnchor(state, state.anchor, _result); + } + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const _line = state.line; + if ((ch === 63 || ch === 58) && isWsOrEol(following)) { + if (ch === 63) { if (atExplicitKey) { storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); keyTag = keyNode = valueNode = null; } detected = true; + atExplicitKey = true; + allowCompact = true; + } else if (atExplicitKey) { atExplicitKey = false; - allowCompact = false; - keyTag = state.tag; - keyNode = state.result; - } else if (detected) { - throwError(state, "can not read an implicit mapping pair; a colon is missed"); + allowCompact = true; } else { - state.tag = _tag; - state.anchor = _anchor; - return true; + throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"); } - } else if (detected) { - throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + state.position += 1; + ch = following; } else { - state.tag = _tag; - state.anchor = _anchor; - return true; - } - } - if (state.line === _line || state.lineIndent > nodeIndent) { - if (atExplicitKey) { _keyLine = state.line; _keyLineStart = state.lineStart; _keyPos = state.position; + if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + break; + } + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) { + ch = state.input.charCodeAt(++state.position); + } + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEol(ch)) { + throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + } + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; + } + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; + } else if (detected) { + throwError(state, "can not read an implicit mapping pair; a colon is missed"); + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; + } + } else if (detected) { + throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; + } } - if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (state.line === _line || state.lineIndent > nodeIndent) { if (atExplicitKey) { - keyNode = state.result; - } else { - valueNode = state.result; + _keyLine = state.line; + _keyLineStart = state.lineStart; + _keyPos = state.position; + } + if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } + if (!atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos); + keyTag = keyNode = valueNode = null; } + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); } - if (!atExplicitKey) { - storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos); - keyTag = keyNode = valueNode = null; + if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) { + throwError(state, "bad indentation of a mapping entry"); + } else if (state.lineIndent < nodeIndent) { + break; } - skipSeparationSpace(state, true, -1); - ch = state.input.charCodeAt(state.position); } - if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) { - throwError(state, "bad indentation of a mapping entry"); - } else if (state.lineIndent < nodeIndent) { - break; + if (atExplicitKey) { + storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); } + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = "mapping"; + state.result = _result; + } + return detected; } - if (atExplicitKey) { - storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos); - } - if (detected) { - state.tag = _tag; - state.anchor = _anchor; - state.kind = "mapping"; - state.result = _result; - } - return detected; -} -function readTagProperty(state) { - var _position, isVerbatim = false, isNamed = false, tagHandle, tagName, ch; - ch = state.input.charCodeAt(state.position); - if (ch !== 33) return false; - if (state.tag !== null) { - throwError(state, "duplication of a tag property"); - } - ch = state.input.charCodeAt(++state.position); - if (ch === 60) { - isVerbatim = true; - ch = state.input.charCodeAt(++state.position); - } else if (ch === 33) { - isNamed = true; - tagHandle = "!!"; + function readTagProperty(state) { + let isVerbatim = false; + let isNamed = false; + let tagHandle; + let tagName; + let ch = state.input.charCodeAt(state.position); + if (ch !== 33) return false; + if (state.tag !== null) { + throwError(state, "duplication of a tag property"); + } ch = state.input.charCodeAt(++state.position); - } else { - tagHandle = "!"; - } - _position = state.position; - if (isVerbatim) { - do { + if (ch === 60) { + isVerbatim = true; ch = state.input.charCodeAt(++state.position); - } while (ch !== 0 && ch !== 62); - if (state.position < state.length) { - tagName = state.input.slice(_position, state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; ch = state.input.charCodeAt(++state.position); } else { - throwError(state, "unexpected end of the stream within a verbatim tag"); + tagHandle = "!"; } - } else { - while (ch !== 0 && !is_WS_OR_EOL(ch)) { - if (ch === 33) { - if (!isNamed) { - tagHandle = state.input.slice(_position - 1, state.position + 1); - if (!PATTERN_TAG_HANDLE.test(tagHandle)) { - throwError(state, "named tag handle cannot contain such characters"); + let _position = state.position; + if (isVerbatim) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0 && ch !== 62); + if (state.position < state.length) { + tagName = state.input.slice(_position, state.position); + ch = state.input.charCodeAt(++state.position); + } else { + throwError(state, "unexpected end of the stream within a verbatim tag"); + } + } else { + while (ch !== 0 && !isWsOrEol(ch)) { + if (ch === 33) { + if (!isNamed) { + tagHandle = state.input.slice(_position - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) { + throwError(state, "named tag handle cannot contain such characters"); + } + isNamed = true; + _position = state.position + 1; + } else { + throwError(state, "tag suffix cannot contain exclamation marks"); } - isNamed = true; - _position = state.position + 1; - } else { - throwError(state, "tag suffix cannot contain exclamation marks"); } + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(_position, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError(state, "tag suffix cannot contain flow indicator characters"); } - ch = state.input.charCodeAt(++state.position); } - tagName = state.input.slice(_position, state.position); - if (PATTERN_FLOW_INDICATORS.test(tagName)) { - throwError(state, "tag suffix cannot contain flow indicator characters"); + if (tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError(state, "tag name cannot contain such characters: " + tagName); } + try { + tagName = decodeURIComponent(tagName); + } catch (err) { + throwError(state, "tag name is malformed: " + tagName); + } + if (isVerbatim) { + state.tag = tagName; + } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) { + state.tag = state.tagMap[tagHandle] + tagName; + } else if (tagHandle === "!") { + state.tag = "!" + tagName; + } else if (tagHandle === "!!") { + state.tag = "tag:yaml.org,2002:" + tagName; + } else { + throwError(state, 'undeclared tag handle "' + tagHandle + '"'); + } + return true; } - if (tagName && !PATTERN_TAG_URI.test(tagName)) { - throwError(state, "tag name cannot contain such characters: " + tagName); - } - try { - tagName = decodeURIComponent(tagName); - } catch (err) { - throwError(state, "tag name is malformed: " + tagName); - } - if (isVerbatim) { - state.tag = tagName; - } else if (_hasOwnProperty$1.call(state.tagMap, tagHandle)) { - state.tag = state.tagMap[tagHandle] + tagName; - } else if (tagHandle === "!") { - state.tag = "!" + tagName; - } else if (tagHandle === "!!") { - state.tag = "tag:yaml.org,2002:" + tagName; - } else { - throwError(state, 'undeclared tag handle "' + tagHandle + '"'); - } - return true; -} -function readAnchorProperty(state) { - var _position, ch; - ch = state.input.charCodeAt(state.position); - if (ch !== 38) return false; - if (state.anchor !== null) { - throwError(state, "duplication of an anchor property"); - } - ch = state.input.charCodeAt(++state.position); - _position = state.position; - while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + function readAnchorProperty(state) { + let ch = state.input.charCodeAt(state.position); + if (ch !== 38) return false; + if (state.anchor !== null) { + throwError(state, "duplication of an anchor property"); + } ch = state.input.charCodeAt(++state.position); + const _position = state.position; + while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) { + ch = state.input.charCodeAt(++state.position); + } + if (state.position === _position) { + throwError(state, "name of an anchor node must contain at least one character"); + } + state.anchor = state.input.slice(_position, state.position); + return true; } - if (state.position === _position) { - throwError(state, "name of an anchor node must contain at least one character"); - } - state.anchor = state.input.slice(_position, state.position); - return true; -} -function readAlias(state) { - var _position, alias, ch; - ch = state.input.charCodeAt(state.position); - if (ch !== 42) return false; - ch = state.input.charCodeAt(++state.position); - _position = state.position; - while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + function readAlias(state) { + let ch = state.input.charCodeAt(state.position); + if (ch !== 42) return false; ch = state.input.charCodeAt(++state.position); + const _position = state.position; + while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) { + ch = state.input.charCodeAt(++state.position); + } + if (state.position === _position) { + throwError(state, "name of an alias node must contain at least one character"); + } + const alias = state.input.slice(_position, state.position); + if (!_hasOwnProperty.call(state.anchorMap, alias)) { + throwError(state, 'unidentified alias "' + alias + '"'); + } + state.result = state.anchorMap[alias]; + skipSeparationSpace(state, true, -1); + return true; } - if (state.position === _position) { - throwError(state, "name of an alias node must contain at least one character"); - } - alias = state.input.slice(_position, state.position); - if (!_hasOwnProperty$1.call(state.anchorMap, alias)) { - throwError(state, 'unidentified alias "' + alias + '"'); + function tryReadBlockMappingFromProperty(state, propertyStart, nodeIndent, flowIndent) { + const fallbackState = snapshotState(state); + beginAnchorTransaction(state); + restoreState(state, propertyStart); + state.tag = null; + state.anchor = null; + state.kind = null; + state.result = null; + if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === "mapping") { + commitAnchorTransaction(state); + return true; + } + rollbackAnchorTransaction(state); + restoreState(state, fallbackState); + return false; } - state.result = state.anchorMap[alias]; - skipSeparationSpace(state, true, -1); - return true; -} -function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { - var allowBlockStyles, allowBlockScalars, allowBlockCollections, indentStatus = 1, atNewLine = false, hasContent = false, typeIndex, typeQuantity, typeList, type2, flowIndent, blockIndent; - if (state.listener !== null) { - state.listener("open", state); - } - state.tag = null; - state.anchor = null; - state.kind = null; - state.result = null; - allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext; - if (allowToSeek) { - if (skipSeparationSpace(state, true, -1)) { - atNewLine = true; - if (state.lineIndent > parentIndent) { - indentStatus = 1; - } else if (state.lineIndent === parentIndent) { - indentStatus = 0; - } else if (state.lineIndent < parentIndent) { - indentStatus = -1; - } - } - } - if (indentStatus === 1) { - while (readTagProperty(state) || readAnchorProperty(state)) { + function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + let allowBlockScalars; + let allowBlockCollections; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + let type2; + let flowIndent; + let blockIndent; + if (state.depth >= state.maxDepth) { + throwError(state, "nesting exceeded maxDepth (" + state.maxDepth + ")"); + } + state.depth += 1; + if (state.listener !== null) { + state.listener("open", state); + } + state.tag = null; + state.anchor = null; + state.kind = null; + state.result = null; + const allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext; + if (allowToSeek) { if (skipSeparationSpace(state, true, -1)) { atNewLine = true; - allowBlockCollections = allowBlockStyles; if (state.lineIndent > parentIndent) { indentStatus = 1; } else if (state.lineIndent === parentIndent) { @@ -1739,882 +2108,955 @@ function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact } else if (state.lineIndent < parentIndent) { indentStatus = -1; } - } else { - allowBlockCollections = false; } } - } - if (allowBlockCollections) { - allowBlockCollections = atNewLine || allowCompact; - } - if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) { - if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { - flowIndent = parentIndent; - } else { - flowIndent = parentIndent + 1; - } - blockIndent = state.position - state.lineStart; if (indentStatus === 1) { - if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) { - hasContent = true; + while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && (ch === 33 && state.tag !== null || ch === 38 && state.anchor !== null)) { + break; + } + if (!readTagProperty(state) && !readAnchorProperty(state)) { + break; + } + if (propertyStart === null) { + propertyStart = propertyState; + } + if (skipSeparationSpace(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } else { + allowBlockCollections = false; + } + } + } + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; } else { - if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) { - hasContent = true; - } else if (readAlias(state)) { + flowIndent = parentIndent + 1; + } + blockIndent = state.position - state.lineStart; + if (indentStatus === 1) { + if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) { hasContent = true; - if (state.tag !== null || state.anchor !== null) { - throwError(state, "alias node should not have any properties"); + } else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62 && tryReadBlockMappingFromProperty( + state, + propertyStart, + propertyStart.position - propertyStart.lineStart, + flowIndent + )) { + hasContent = true; + } else if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) { + hasContent = true; + } else if (readAlias(state)) { + hasContent = true; + if (state.tag !== null || state.anchor !== null) { + throwError(state, "alias node should not have any properties"); + } + } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) { + hasContent = true; + if (state.tag === null) { + state.tag = "?"; + } } - } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) { - hasContent = true; - if (state.tag === null) { - state.tag = "?"; + if (state.anchor !== null) { + storeAnchor(state, state.anchor, state.result); } } - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; - } + } else if (indentStatus === 0) { + hasContent = allowBlockCollections && readBlockSequence(state, blockIndent); } - } else if (indentStatus === 0) { - hasContent = allowBlockCollections && readBlockSequence(state, blockIndent); } - } - if (state.tag === null) { - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; - } - } else if (state.tag === "?") { - if (state.result !== null && state.kind !== "scalar") { - throwError(state, 'unacceptable node kind for ! tag; it should be "scalar", not "' + state.kind + '"'); - } - for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) { - type2 = state.implicitTypes[typeIndex]; - if (type2.resolve(state.result)) { - state.result = type2.construct(state.result); - state.tag = type2.tag; - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; + if (state.tag === null) { + if (state.anchor !== null) { + storeAnchor(state, state.anchor, state.result); + } + } else if (state.tag === "?") { + if (state.result !== null && state.kind !== "scalar") { + throwError(state, 'unacceptable node kind for ! tag; it should be "scalar", not "' + state.kind + '"'); + } + for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) { + type2 = state.implicitTypes[typeIndex]; + if (type2.resolve(state.result)) { + state.result = type2.construct(state.result); + state.tag = type2.tag; + if (state.anchor !== null) { + storeAnchor(state, state.anchor, state.result); + } + break; + } + } + } else if (state.tag !== "!") { + if (_hasOwnProperty.call(state.typeMap[state.kind || "fallback"], state.tag)) { + type2 = state.typeMap[state.kind || "fallback"][state.tag]; + } else { + type2 = null; + const typeList = state.typeMap.multi[state.kind || "fallback"]; + for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) { + if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) { + type2 = typeList[typeIndex]; + break; + } } - break; } - } - } else if (state.tag !== "!") { - if (_hasOwnProperty$1.call(state.typeMap[state.kind || "fallback"], state.tag)) { - type2 = state.typeMap[state.kind || "fallback"][state.tag]; - } else { - type2 = null; - typeList = state.typeMap.multi[state.kind || "fallback"]; - for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) { - if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) { - type2 = typeList[typeIndex]; - break; + if (!type2) { + throwError(state, "unknown tag !<" + state.tag + ">"); + } + if (state.result !== null && type2.kind !== state.kind) { + throwError(state, "unacceptable node kind for !<" + state.tag + '> tag; it should be "' + type2.kind + '", not "' + state.kind + '"'); + } + if (!type2.resolve(state.result, state.tag)) { + throwError(state, "cannot resolve a node with !<" + state.tag + "> explicit tag"); + } else { + state.result = type2.construct(state.result, state.tag); + if (state.anchor !== null) { + storeAnchor(state, state.anchor, state.result); } } } - if (!type2) { - throwError(state, "unknown tag !<" + state.tag + ">"); - } - if (state.result !== null && type2.kind !== state.kind) { - throwError(state, "unacceptable node kind for !<" + state.tag + '> tag; it should be "' + type2.kind + '", not "' + state.kind + '"'); - } - if (!type2.resolve(state.result, state.tag)) { - throwError(state, "cannot resolve a node with !<" + state.tag + "> explicit tag"); - } else { - state.result = type2.construct(state.result, state.tag); - if (state.anchor !== null) { - state.anchorMap[state.anchor] = state.result; - } + if (state.listener !== null) { + state.listener("close", state); } + state.depth -= 1; + return state.tag !== null || state.anchor !== null || hasContent; } - if (state.listener !== null) { - state.listener("close", state); - } - return state.tag !== null || state.anchor !== null || hasContent; -} -function readDocument(state) { - var documentStart = state.position, _position, directiveName, directiveArgs, hasDirectives = false, ch; - state.version = null; - state.checkLineBreaks = state.legacy; - state.tagMap = /* @__PURE__ */ Object.create(null); - state.anchorMap = /* @__PURE__ */ Object.create(null); - while ((ch = state.input.charCodeAt(state.position)) !== 0) { - skipSeparationSpace(state, true, -1); - ch = state.input.charCodeAt(state.position); - if (state.lineIndent > 0 || ch !== 37) { - break; - } - hasDirectives = true; - ch = state.input.charCodeAt(++state.position); - _position = state.position; - while (ch !== 0 && !is_WS_OR_EOL(ch)) { + function readDocument(state) { + const documentStart = state.position; + let hasDirectives = false; + let ch; + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = /* @__PURE__ */ Object.create(null); + state.anchorMap = /* @__PURE__ */ Object.create(null); + while ((ch = state.input.charCodeAt(state.position)) !== 0) { + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + if (state.lineIndent > 0 || ch !== 37) { + break; + } + hasDirectives = true; ch = state.input.charCodeAt(++state.position); - } - directiveName = state.input.slice(_position, state.position); - directiveArgs = []; - if (directiveName.length < 1) { - throwError(state, "directive name must not be less than one character in length"); - } - while (ch !== 0) { - while (is_WHITE_SPACE(ch)) { + let _position = state.position; + while (ch !== 0 && !isWsOrEol(ch)) { ch = state.input.charCodeAt(++state.position); } - if (ch === 35) { - do { + const directiveName = state.input.slice(_position, state.position); + const directiveArgs = []; + if (directiveName.length < 1) { + throwError(state, "directive name must not be less than one character in length"); + } + while (ch !== 0) { + while (isWhiteSpace(ch)) { ch = state.input.charCodeAt(++state.position); - } while (ch !== 0 && !is_EOL(ch)); - break; + } + if (ch === 35) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0 && !isEol(ch)); + break; + } + if (isEol(ch)) break; + _position = state.position; + while (ch !== 0 && !isWsOrEol(ch)) { + ch = state.input.charCodeAt(++state.position); + } + directiveArgs.push(state.input.slice(_position, state.position)); } - if (is_EOL(ch)) break; - _position = state.position; - while (ch !== 0 && !is_WS_OR_EOL(ch)) { - ch = state.input.charCodeAt(++state.position); + if (ch !== 0) readLineBreak(state); + if (_hasOwnProperty.call(directiveHandlers, directiveName)) { + directiveHandlers[directiveName](state, directiveName, directiveArgs); + } else { + throwWarning(state, 'unknown document directive "' + directiveName + '"'); } - directiveArgs.push(state.input.slice(_position, state.position)); } - if (ch !== 0) readLineBreak(state); - if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) { - directiveHandlers[directiveName](state, directiveName, directiveArgs); - } else { - throwWarning(state, 'unknown document directive "' + directiveName + '"'); - } - } - skipSeparationSpace(state, true, -1); - if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45) { - state.position += 3; skipSeparationSpace(state, true, -1); - } else if (hasDirectives) { - throwError(state, "directives end mark is expected"); - } - composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); - skipSeparationSpace(state, true, -1); - if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) { - throwWarning(state, "non-ASCII line breaks are interpreted as content"); - } - state.documents.push(state.result); - if (state.position === state.lineStart && testDocumentSeparator(state)) { - if (state.input.charCodeAt(state.position) === 46) { + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45) { state.position += 3; skipSeparationSpace(state, true, -1); + } else if (hasDirectives) { + throwError(state, "directives end mark is expected"); } - return; - } - if (state.position < state.length - 1) { - throwError(state, "end of the stream or a document separator is expected"); - } else { - return; - } -} -function loadDocuments(input, options) { - input = String(input); - options = options || {}; - if (input.length !== 0) { - if (input.charCodeAt(input.length - 1) !== 10 && input.charCodeAt(input.length - 1) !== 13) { - input += "\n"; + composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(state, true, -1); + if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) { + throwWarning(state, "non-ASCII line breaks are interpreted as content"); } - if (input.charCodeAt(0) === 65279) { - input = input.slice(1); + state.documents.push(state.result); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + if (state.input.charCodeAt(state.position) === 46) { + state.position += 3; + skipSeparationSpace(state, true, -1); + } + return; } - } - var state = new State$1(input, options); - var nullpos = input.indexOf("\0"); - if (nullpos !== -1) { - state.position = nullpos; - throwError(state, "null byte is not allowed in input"); - } - state.input += "\0"; - while (state.input.charCodeAt(state.position) === 32) { - state.lineIndent += 1; - state.position += 1; - } - while (state.position < state.length - 1) { - readDocument(state); - } - return state.documents; -} -function loadAll$1(input, iterator, options) { - if (iterator !== null && typeof iterator === "object" && typeof options === "undefined") { - options = iterator; - iterator = null; - } - var documents = loadDocuments(input, options); - if (typeof iterator !== "function") { - return documents; - } - for (var index = 0, length = documents.length; index < length; index += 1) { - iterator(documents[index]); - } -} -function load$1(input, options) { - var documents = loadDocuments(input, options); - if (documents.length === 0) { - return void 0; - } else if (documents.length === 1) { - return documents[0]; - } - throw new exception("expected a single document in the stream, but found more"); -} -var loadAll_1 = loadAll$1; -var load_1 = load$1; -var loader = { - loadAll: loadAll_1, - load: load_1 -}; -var _toString = Object.prototype.toString; -var _hasOwnProperty = Object.prototype.hasOwnProperty; -var CHAR_BOM = 65279; -var CHAR_TAB = 9; -var CHAR_LINE_FEED = 10; -var CHAR_CARRIAGE_RETURN = 13; -var CHAR_SPACE = 32; -var CHAR_EXCLAMATION = 33; -var CHAR_DOUBLE_QUOTE = 34; -var CHAR_SHARP = 35; -var CHAR_PERCENT = 37; -var CHAR_AMPERSAND = 38; -var CHAR_SINGLE_QUOTE = 39; -var CHAR_ASTERISK = 42; -var CHAR_COMMA = 44; -var CHAR_MINUS = 45; -var CHAR_COLON = 58; -var CHAR_EQUALS = 61; -var CHAR_GREATER_THAN = 62; -var CHAR_QUESTION = 63; -var CHAR_COMMERCIAL_AT = 64; -var CHAR_LEFT_SQUARE_BRACKET = 91; -var CHAR_RIGHT_SQUARE_BRACKET = 93; -var CHAR_GRAVE_ACCENT = 96; -var CHAR_LEFT_CURLY_BRACKET = 123; -var CHAR_VERTICAL_LINE = 124; -var CHAR_RIGHT_CURLY_BRACKET = 125; -var ESCAPE_SEQUENCES = {}; -ESCAPE_SEQUENCES[0] = "\\0"; -ESCAPE_SEQUENCES[7] = "\\a"; -ESCAPE_SEQUENCES[8] = "\\b"; -ESCAPE_SEQUENCES[9] = "\\t"; -ESCAPE_SEQUENCES[10] = "\\n"; -ESCAPE_SEQUENCES[11] = "\\v"; -ESCAPE_SEQUENCES[12] = "\\f"; -ESCAPE_SEQUENCES[13] = "\\r"; -ESCAPE_SEQUENCES[27] = "\\e"; -ESCAPE_SEQUENCES[34] = '\\"'; -ESCAPE_SEQUENCES[92] = "\\\\"; -ESCAPE_SEQUENCES[133] = "\\N"; -ESCAPE_SEQUENCES[160] = "\\_"; -ESCAPE_SEQUENCES[8232] = "\\L"; -ESCAPE_SEQUENCES[8233] = "\\P"; -var DEPRECATED_BOOLEANS_SYNTAX = [ - "y", - "Y", - "yes", - "Yes", - "YES", - "on", - "On", - "ON", - "n", - "N", - "no", - "No", - "NO", - "off", - "Off", - "OFF" -]; -var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; -function compileStyleMap(schema2, map3) { - var result, keys, index, length, tag, style, type2; - if (map3 === null) return {}; - result = {}; - keys = Object.keys(map3); - for (index = 0, length = keys.length; index < length; index += 1) { - tag = keys[index]; - style = String(map3[tag]); - if (tag.slice(0, 2) === "!!") { - tag = "tag:yaml.org,2002:" + tag.slice(2); - } - type2 = schema2.compiledTypeMap["fallback"][tag]; - if (type2 && _hasOwnProperty.call(type2.styleAliases, style)) { - style = type2.styleAliases[style]; - } - result[tag] = style; - } - return result; -} -function encodeHex(character) { - var string4, handle, length; - string4 = character.toString(16).toUpperCase(); - if (character <= 255) { - handle = "x"; - length = 2; - } else if (character <= 65535) { - handle = "u"; - length = 4; - } else if (character <= 4294967295) { - handle = "U"; - length = 8; - } else { - throw new exception("code point within a string may not be greater than 0xFFFFFFFF"); - } - return "\\" + handle + common.repeat("0", length - string4.length) + string4; -} -var QUOTING_TYPE_SINGLE = 1; -var QUOTING_TYPE_DOUBLE = 2; -function State(options) { - this.schema = options["schema"] || _default; - this.indent = Math.max(1, options["indent"] || 2); - this.noArrayIndent = options["noArrayIndent"] || false; - this.skipInvalid = options["skipInvalid"] || false; - this.flowLevel = common.isNothing(options["flowLevel"]) ? -1 : options["flowLevel"]; - this.styleMap = compileStyleMap(this.schema, options["styles"] || null); - this.sortKeys = options["sortKeys"] || false; - this.lineWidth = options["lineWidth"] || 80; - this.noRefs = options["noRefs"] || false; - this.noCompatMode = options["noCompatMode"] || false; - this.condenseFlow = options["condenseFlow"] || false; - this.quotingType = options["quotingType"] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE; - this.forceQuotes = options["forceQuotes"] || false; - this.replacer = typeof options["replacer"] === "function" ? options["replacer"] : null; - this.implicitTypes = this.schema.compiledImplicit; - this.explicitTypes = this.schema.compiledExplicit; - this.tag = null; - this.result = ""; - this.duplicates = []; - this.usedDuplicates = null; -} -function indentString(string4, spaces) { - var ind = common.repeat(" ", spaces), position = 0, next = -1, result = "", line, length = string4.length; - while (position < length) { - next = string4.indexOf("\n", position); - if (next === -1) { - line = string4.slice(position); - position = length; - } else { - line = string4.slice(position, next + 1); - position = next + 1; + if (state.position < state.length - 1) { + throwError(state, "end of the stream or a document separator is expected"); } - if (line.length && line !== "\n") result += ind; - result += line; } - return result; -} -function generateNextLine(state, level) { - return "\n" + common.repeat(" ", state.indent * level); -} -function testImplicitResolving(state, str2) { - var index, length, type2; - for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { - type2 = state.implicitTypes[index]; - if (type2.resolve(str2)) { - return true; + function loadDocuments(input, options) { + input = String(input); + options = options || {}; + if (input.length !== 0) { + if (input.charCodeAt(input.length - 1) !== 10 && input.charCodeAt(input.length - 1) !== 13) { + input += "\n"; + } + if (input.charCodeAt(0) === 65279) { + input = input.slice(1); + } } - } - return false; -} -function isWhitespace(c) { - return c === CHAR_SPACE || c === CHAR_TAB; -} -function isPrintable(c) { - return 32 <= c && c <= 126 || 161 <= c && c <= 55295 && c !== 8232 && c !== 8233 || 57344 <= c && c <= 65533 && c !== CHAR_BOM || 65536 <= c && c <= 1114111; -} -function isNsCharOrWhitespace(c) { - return isPrintable(c) && c !== CHAR_BOM && c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED; -} -function isPlainSafe(c, prev, inblock) { - var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c); - var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c); - return ( - // ns-plain-safe - (inblock ? ( - // c = flow-in - cIsNsCharOrWhitespace - ) : cIsNsCharOrWhitespace && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET) && c !== CHAR_SHARP && !(prev === CHAR_COLON && !cIsNsChar) || isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP || prev === CHAR_COLON && cIsNsChar - ); -} -function isPlainSafeFirst(c) { - return isPrintable(c) && c !== CHAR_BOM && !isWhitespace(c) && c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET && c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE && c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT; -} -function isPlainSafeLast(c) { - return !isWhitespace(c) && c !== CHAR_COLON; -} -function codePointAt(string4, pos) { - var first = string4.charCodeAt(pos), second; - if (first >= 55296 && first <= 56319 && pos + 1 < string4.length) { - second = string4.charCodeAt(pos + 1); - if (second >= 56320 && second <= 57343) { - return (first - 55296) * 1024 + second - 56320 + 65536; - } - } - return first; -} -function needIndentIndicator(string4) { - var leadingSpaceRe = /^\n* /; - return leadingSpaceRe.test(string4); -} -var STYLE_PLAIN = 1; -var STYLE_SINGLE = 2; -var STYLE_LITERAL = 3; -var STYLE_FOLDED = 4; -var STYLE_DOUBLE = 5; -function chooseScalarStyle(string4, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) { - var i2; - var char = 0; - var prevChar = null; - var hasLineBreak = false; - var hasFoldableLine = false; - var shouldTrackWidth = lineWidth !== -1; - var previousLineBreak = -1; - var plain = isPlainSafeFirst(codePointAt(string4, 0)) && isPlainSafeLast(codePointAt(string4, string4.length - 1)); - if (singleLineOnly || forceQuotes) { - for (i2 = 0; i2 < string4.length; char >= 65536 ? i2 += 2 : i2++) { - char = codePointAt(string4, i2); - if (!isPrintable(char)) { - return STYLE_DOUBLE; - } - plain = plain && isPlainSafe(char, prevChar, inblock); - prevChar = char; + const state = new State(input, options); + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) { + state.position = nullpos; + throwError(state, "null byte is not allowed in input"); } - } else { - for (i2 = 0; i2 < string4.length; char >= 65536 ? i2 += 2 : i2++) { - char = codePointAt(string4, i2); - if (char === CHAR_LINE_FEED) { - hasLineBreak = true; - if (shouldTrackWidth) { - hasFoldableLine = hasFoldableLine || // Foldable line = too long, and not more-indented. - i2 - previousLineBreak - 1 > lineWidth && string4[previousLineBreak + 1] !== " "; - previousLineBreak = i2; - } - } else if (!isPrintable(char)) { - return STYLE_DOUBLE; + state.input += "\0"; + while (state.input.charCodeAt(state.position) === 32) { + state.lineIndent += 1; + state.position += 1; + } + while (state.position < state.length - 1) { + readDocument(state); + } + return state.documents; + } + function loadAll2(input, iterator, options) { + if (iterator !== null && typeof iterator === "object" && typeof options === "undefined") { + options = iterator; + iterator = null; + } + const documents = loadDocuments(input, options); + if (typeof iterator !== "function") { + return documents; + } + for (let index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } + } + function load2(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) { + return void 0; + } else if (documents.length === 1) { + return documents[0]; + } + throw new YAMLException2("expected a single document in the stream, but found more"); + } + loader.loadAll = loadAll2; + loader.load = load2; + return loader; +} +var dumper = {}; +var hasRequiredDumper; +function requireDumper() { + if (hasRequiredDumper) return dumper; + hasRequiredDumper = 1; + const common2 = requireCommon(); + const YAMLException2 = requireException(); + const DEFAULT_SCHEMA2 = require_default(); + const _toString = Object.prototype.toString; + const _hasOwnProperty = Object.prototype.hasOwnProperty; + const CHAR_BOM = 65279; + const CHAR_TAB = 9; + const CHAR_LINE_FEED = 10; + const CHAR_CARRIAGE_RETURN = 13; + const CHAR_SPACE = 32; + const CHAR_EXCLAMATION = 33; + const CHAR_DOUBLE_QUOTE = 34; + const CHAR_SHARP = 35; + const CHAR_PERCENT = 37; + const CHAR_AMPERSAND = 38; + const CHAR_SINGLE_QUOTE = 39; + const CHAR_ASTERISK = 42; + const CHAR_COMMA = 44; + const CHAR_MINUS = 45; + const CHAR_COLON = 58; + const CHAR_EQUALS = 61; + const CHAR_GREATER_THAN = 62; + const CHAR_QUESTION = 63; + const CHAR_COMMERCIAL_AT = 64; + const CHAR_LEFT_SQUARE_BRACKET = 91; + const CHAR_RIGHT_SQUARE_BRACKET = 93; + const CHAR_GRAVE_ACCENT = 96; + const CHAR_LEFT_CURLY_BRACKET = 123; + const CHAR_VERTICAL_LINE = 124; + const CHAR_RIGHT_CURLY_BRACKET = 125; + const ESCAPE_SEQUENCES = {}; + ESCAPE_SEQUENCES[0] = "\\0"; + ESCAPE_SEQUENCES[7] = "\\a"; + ESCAPE_SEQUENCES[8] = "\\b"; + ESCAPE_SEQUENCES[9] = "\\t"; + ESCAPE_SEQUENCES[10] = "\\n"; + ESCAPE_SEQUENCES[11] = "\\v"; + ESCAPE_SEQUENCES[12] = "\\f"; + ESCAPE_SEQUENCES[13] = "\\r"; + ESCAPE_SEQUENCES[27] = "\\e"; + ESCAPE_SEQUENCES[34] = '\\"'; + ESCAPE_SEQUENCES[92] = "\\\\"; + ESCAPE_SEQUENCES[133] = "\\N"; + ESCAPE_SEQUENCES[160] = "\\_"; + ESCAPE_SEQUENCES[8232] = "\\L"; + ESCAPE_SEQUENCES[8233] = "\\P"; + const DEPRECATED_BOOLEANS_SYNTAX = [ + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" + ]; + const DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; + function compileStyleMap(schema2, map22) { + if (map22 === null) return {}; + const result = {}; + const keys = Object.keys(map22); + for (let index = 0, length = keys.length; index < length; index += 1) { + let tag = keys[index]; + let style = String(map22[tag]); + if (tag.slice(0, 2) === "!!") { + tag = "tag:yaml.org,2002:" + tag.slice(2); + } + const type2 = schema2.compiledTypeMap["fallback"][tag]; + if (type2 && _hasOwnProperty.call(type2.styleAliases, style)) { + style = type2.styleAliases[style]; + } + result[tag] = style; + } + return result; + } + function encodeHex(character) { + let handle; + let length; + const string4 = character.toString(16).toUpperCase(); + if (character <= 255) { + handle = "x"; + length = 2; + } else if (character <= 65535) { + handle = "u"; + length = 4; + } else if (character <= 4294967295) { + handle = "U"; + length = 8; + } else { + throw new YAMLException2("code point within a string may not be greater than 0xFFFFFFFF"); + } + return "\\" + handle + common2.repeat("0", length - string4.length) + string4; + } + const QUOTING_TYPE_SINGLE = 1; + const QUOTING_TYPE_DOUBLE = 2; + function State(options) { + this.schema = options["schema"] || DEFAULT_SCHEMA2; + this.indent = Math.max(1, options["indent"] || 2); + this.noArrayIndent = options["noArrayIndent"] || false; + this.skipInvalid = options["skipInvalid"] || false; + this.flowLevel = common2.isNothing(options["flowLevel"]) ? -1 : options["flowLevel"]; + this.styleMap = compileStyleMap(this.schema, options["styles"] || null); + this.sortKeys = options["sortKeys"] || false; + this.lineWidth = options["lineWidth"] || 80; + this.noRefs = options["noRefs"] || false; + this.noCompatMode = options["noCompatMode"] || false; + this.condenseFlow = options["condenseFlow"] || false; + this.quotingType = options["quotingType"] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE; + this.forceQuotes = options["forceQuotes"] || false; + this.replacer = typeof options["replacer"] === "function" ? options["replacer"] : null; + this.implicitTypes = this.schema.compiledImplicit; + this.explicitTypes = this.schema.compiledExplicit; + this.tag = null; + this.result = ""; + this.duplicates = []; + this.usedDuplicates = null; + } + function indentString(string4, spaces) { + const ind = common2.repeat(" ", spaces); + let position = 0; + let result = ""; + const length = string4.length; + while (position < length) { + let line; + const next = string4.indexOf("\n", position); + if (next === -1) { + line = string4.slice(position); + position = length; + } else { + line = string4.slice(position, next + 1); + position = next + 1; } - plain = plain && isPlainSafe(char, prevChar, inblock); - prevChar = char; + if (line.length && line !== "\n") result += ind; + result += line; } - hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i2 - previousLineBreak - 1 > lineWidth && string4[previousLineBreak + 1] !== " "); + return result; } - if (!hasLineBreak && !hasFoldableLine) { - if (plain && !forceQuotes && !testAmbiguousType(string4)) { - return STYLE_PLAIN; + function generateNextLine(state, level) { + return "\n" + common2.repeat(" ", state.indent * level); + } + function testImplicitResolving(state, str2) { + for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) { + const type2 = state.implicitTypes[index]; + if (type2.resolve(str2)) { + return true; + } } - return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE; + return false; } - if (indentPerLevel > 9 && needIndentIndicator(string4)) { - return STYLE_DOUBLE; - } - if (!forceQuotes) { - return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL; - } - return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE; -} -function writeScalar(state, string4, level, iskey, inblock) { - state.dump = (function() { - if (string4.length === 0) { - return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''"; - } - if (!state.noCompatMode) { - if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string4) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string4)) { - return state.quotingType === QUOTING_TYPE_DOUBLE ? '"' + string4 + '"' : "'" + string4 + "'"; - } - } - var indent = state.indent * Math.max(1, level); - var lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent); - var singleLineOnly = iskey || state.flowLevel > -1 && level >= state.flowLevel; - function testAmbiguity(string5) { - return testImplicitResolving(state, string5); - } - switch (chooseScalarStyle( - string4, - singleLineOnly, - state.indent, - lineWidth, - testAmbiguity, - state.quotingType, - state.forceQuotes && !iskey, - inblock - )) { - case STYLE_PLAIN: - return string4; - case STYLE_SINGLE: - return "'" + string4.replace(/'/g, "''") + "'"; - case STYLE_LITERAL: - return "|" + blockHeader(string4, state.indent) + dropEndingNewline(indentString(string4, indent)); - case STYLE_FOLDED: - return ">" + blockHeader(string4, state.indent) + dropEndingNewline(indentString(foldString(string4, lineWidth), indent)); - case STYLE_DOUBLE: - return '"' + escapeString(string4) + '"'; - default: - throw new exception("impossible error: invalid scalar style"); - } - })(); -} -function blockHeader(string4, indentPerLevel) { - var indentIndicator = needIndentIndicator(string4) ? String(indentPerLevel) : ""; - var clip = string4[string4.length - 1] === "\n"; - var keep = clip && (string4[string4.length - 2] === "\n" || string4 === "\n"); - var chomp = keep ? "+" : clip ? "" : "-"; - return indentIndicator + chomp + "\n"; -} -function dropEndingNewline(string4) { - return string4[string4.length - 1] === "\n" ? string4.slice(0, -1) : string4; -} -function foldString(string4, width) { - var lineRe = /(\n+)([^\n]*)/g; - var result = (function() { - var nextLF = string4.indexOf("\n"); - nextLF = nextLF !== -1 ? nextLF : string4.length; - lineRe.lastIndex = nextLF; - return foldLine(string4.slice(0, nextLF), width); - })(); - var prevMoreIndented = string4[0] === "\n" || string4[0] === " "; - var moreIndented; - var match; - while (match = lineRe.exec(string4)) { - var prefix = match[1], line = match[2]; - moreIndented = line[0] === " "; - result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width); - prevMoreIndented = moreIndented; + function isWhitespace(c) { + return c === CHAR_SPACE || c === CHAR_TAB; + } + function isPrintable(c) { + return c >= 32 && c <= 126 || c >= 161 && c <= 55295 && c !== 8232 && c !== 8233 || c >= 57344 && c <= 65533 && c !== CHAR_BOM || c >= 65536 && c <= 1114111; + } + function isNsCharOrWhitespace(c) { + return isPrintable(c) && c !== CHAR_BOM && // - b-char + c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED; + } + function isPlainSafe(c, prev, inblock) { + const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c); + const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c); + return ( + // ns-plain-safe + (inblock ? cIsNsCharOrWhitespace : cIsNsCharOrWhitespace && // - c-flow-indicator + c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET) && // ns-plain-char + c !== CHAR_SHARP && // false on '#' + !(prev === CHAR_COLON && !cIsNsChar) || // false on ': ' + isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP || // change to true on '[^ ]#' + prev === CHAR_COLON && cIsNsChar + ); } - return result; -} -function foldLine(line, width) { - if (line === "" || line[0] === " ") return line; - var breakRe = / [^ ]/g; - var match; - var start = 0, end, curr = 0, next = 0; - var result = ""; - while (match = breakRe.exec(line)) { - next = match.index; - if (next - start > width) { - end = curr > start ? curr : next; - result += "\n" + line.slice(start, end); - start = end + 1; - } - curr = next; - } - result += "\n"; - if (line.length - start > width && curr > start) { - result += line.slice(start, curr) + "\n" + line.slice(curr + 1); - } else { - result += line.slice(start); - } - return result.slice(1); -} -function escapeString(string4) { - var result = ""; - var char = 0; - var escapeSeq; - for (var i2 = 0; i2 < string4.length; char >= 65536 ? i2 += 2 : i2++) { - char = codePointAt(string4, i2); - escapeSeq = ESCAPE_SEQUENCES[char]; - if (!escapeSeq && isPrintable(char)) { - result += string4[i2]; - if (char >= 65536) result += string4[i2 + 1]; + function isPlainSafeFirst(c) { + return isPrintable(c) && c !== CHAR_BOM && !isWhitespace(c) && // - s-white + // - (c-indicator ::= + // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}” + c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET && // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"” + c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE && // | “%” | “@” | “`”) + c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT; + } + function isPlainSafeLast(c) { + return !isWhitespace(c) && c !== CHAR_COLON; + } + function codePointAt(string4, pos) { + const first = string4.charCodeAt(pos); + let second; + if (first >= 55296 && first <= 56319 && pos + 1 < string4.length) { + second = string4.charCodeAt(pos + 1); + if (second >= 56320 && second <= 57343) { + return (first - 55296) * 1024 + second - 56320 + 65536; + } + } + return first; + } + function needIndentIndicator(string4) { + const leadingSpaceRe = /^\n* /; + return leadingSpaceRe.test(string4); + } + const STYLE_PLAIN = 1; + const STYLE_SINGLE = 2; + const STYLE_LITERAL = 3; + const STYLE_FOLDED = 4; + const STYLE_DOUBLE = 5; + function chooseScalarStyle(string4, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) { + let i; + let char = 0; + let prevChar = null; + let hasLineBreak = false; + let hasFoldableLine = false; + const shouldTrackWidth = lineWidth !== -1; + let previousLineBreak = -1; + let plain = isPlainSafeFirst(codePointAt(string4, 0)) && isPlainSafeLast(codePointAt(string4, string4.length - 1)); + if (singleLineOnly || forceQuotes) { + for (i = 0; i < string4.length; char >= 65536 ? i += 2 : i++) { + char = codePointAt(string4, i); + if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char, prevChar, inblock); + prevChar = char; + } } else { - result += escapeSeq || encodeHex(char); + for (i = 0; i < string4.length; char >= 65536 ? i += 2 : i++) { + char = codePointAt(string4, i); + if (char === CHAR_LINE_FEED) { + hasLineBreak = true; + if (shouldTrackWidth) { + hasFoldableLine = hasFoldableLine || // Foldable line = too long, and not more-indented. + i - previousLineBreak - 1 > lineWidth && string4[previousLineBreak + 1] !== " "; + previousLineBreak = i; + } + } else if (!isPrintable(char)) { + return STYLE_DOUBLE; + } + plain = plain && isPlainSafe(char, prevChar, inblock); + prevChar = char; + } + hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i - previousLineBreak - 1 > lineWidth && string4[previousLineBreak + 1] !== " "); } - } - return result; -} -function writeFlowSequence(state, level, object2) { - var _result = "", _tag = state.tag, index, length, value; - for (index = 0, length = object2.length; index < length; index += 1) { - value = object2[index]; - if (state.replacer) { - value = state.replacer.call(object2, String(index), value); + if (!hasLineBreak && !hasFoldableLine) { + if (plain && !forceQuotes && !testAmbiguousType(string4)) { + return STYLE_PLAIN; + } + return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE; } - if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) { - if (_result !== "") _result += "," + (!state.condenseFlow ? " " : ""); - _result += state.dump; + if (indentPerLevel > 9 && needIndentIndicator(string4)) { + return STYLE_DOUBLE; } - } - state.tag = _tag; - state.dump = "[" + _result + "]"; -} -function writeBlockSequence(state, level, object2, compact) { - var _result = "", _tag = state.tag, index, length, value; - for (index = 0, length = object2.length; index < length; index += 1) { - value = object2[index]; - if (state.replacer) { - value = state.replacer.call(object2, String(index), value); + if (!forceQuotes) { + return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL; } - if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) { - if (!compact || _result !== "") { - _result += generateNextLine(state, level); + return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE; + } + function writeScalar(state, string4, level, iskey, inblock) { + state.dump = (function() { + if (string4.length === 0) { + return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''"; } - if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { - _result += "-"; - } else { - _result += "- "; + if (!state.noCompatMode) { + if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string4) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string4)) { + return state.quotingType === QUOTING_TYPE_DOUBLE ? '"' + string4 + '"' : "'" + string4 + "'"; + } } - _result += state.dump; + const indent = state.indent * Math.max(1, level); + const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent); + const singleLineOnly = iskey || // No block styles in flow mode. + state.flowLevel > -1 && level >= state.flowLevel; + function testAmbiguity(string22) { + return testImplicitResolving(state, string22); + } + switch (chooseScalarStyle( + string4, + singleLineOnly, + state.indent, + lineWidth, + testAmbiguity, + state.quotingType, + state.forceQuotes && !iskey, + inblock + )) { + case STYLE_PLAIN: + return string4; + case STYLE_SINGLE: + return "'" + string4.replace(/'/g, "''") + "'"; + case STYLE_LITERAL: + return "|" + blockHeader(string4, state.indent) + dropEndingNewline(indentString(string4, indent)); + case STYLE_FOLDED: + return ">" + blockHeader(string4, state.indent) + dropEndingNewline(indentString(foldString(string4, lineWidth), indent)); + case STYLE_DOUBLE: + return '"' + escapeString(string4) + '"'; + default: + throw new YAMLException2("impossible error: invalid scalar style"); + } + })(); + } + function blockHeader(string4, indentPerLevel) { + const indentIndicator = needIndentIndicator(string4) ? String(indentPerLevel) : ""; + const clip = string4[string4.length - 1] === "\n"; + const keep = clip && (string4[string4.length - 2] === "\n" || string4 === "\n"); + const chomp = keep ? "+" : clip ? "" : "-"; + return indentIndicator + chomp + "\n"; + } + function dropEndingNewline(string4) { + return string4[string4.length - 1] === "\n" ? string4.slice(0, -1) : string4; + } + function foldString(string4, width) { + const lineRe = /(\n+)([^\n]*)/g; + let result = (function() { + let nextLF = string4.indexOf("\n"); + nextLF = nextLF !== -1 ? nextLF : string4.length; + lineRe.lastIndex = nextLF; + return foldLine(string4.slice(0, nextLF), width); + })(); + let prevMoreIndented = string4[0] === "\n" || string4[0] === " "; + let moreIndented; + let match; + while (match = lineRe.exec(string4)) { + const prefix = match[1]; + const line = match[2]; + moreIndented = line[0] === " "; + result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width); + prevMoreIndented = moreIndented; } + return result; } - state.tag = _tag; - state.dump = _result || "[]"; -} -function writeFlowMapping(state, level, object2) { - var _result = "", _tag = state.tag, objectKeyList = Object.keys(object2), index, length, objectKey, objectValue, pairBuffer; - for (index = 0, length = objectKeyList.length; index < length; index += 1) { - pairBuffer = ""; - if (_result !== "") pairBuffer += ", "; - if (state.condenseFlow) pairBuffer += '"'; - objectKey = objectKeyList[index]; - objectValue = object2[objectKey]; - if (state.replacer) { - objectValue = state.replacer.call(object2, objectKey, objectValue); - } - if (!writeNode(state, level, objectKey, false, false)) { - continue; - } - if (state.dump.length > 1024) pairBuffer += "? "; - pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " "); - if (!writeNode(state, level, objectValue, false, false)) { - continue; + function foldLine(line, width) { + if (line === "" || line[0] === " ") return line; + const breakRe = / [^ ]/g; + let match; + let start = 0; + let end; + let curr = 0; + let next = 0; + let result = ""; + while (match = breakRe.exec(line)) { + next = match.index; + if (next - start > width) { + end = curr > start ? curr : next; + result += "\n" + line.slice(start, end); + start = end + 1; + } + curr = next; + } + result += "\n"; + if (line.length - start > width && curr > start) { + result += line.slice(start, curr) + "\n" + line.slice(curr + 1); + } else { + result += line.slice(start); + } + return result.slice(1); + } + function escapeString(string4) { + let result = ""; + let char = 0; + for (let i = 0; i < string4.length; char >= 65536 ? i += 2 : i++) { + char = codePointAt(string4, i); + const escapeSeq = ESCAPE_SEQUENCES[char]; + if (!escapeSeq && isPrintable(char)) { + result += string4[i]; + if (char >= 65536) result += string4[i + 1]; + } else { + result += escapeSeq || encodeHex(char); + } } - pairBuffer += state.dump; - _result += pairBuffer; - } - state.tag = _tag; - state.dump = "{" + _result + "}"; -} -function writeBlockMapping(state, level, object2, compact) { - var _result = "", _tag = state.tag, objectKeyList = Object.keys(object2), index, length, objectKey, objectValue, explicitPair, pairBuffer; - if (state.sortKeys === true) { - objectKeyList.sort(); - } else if (typeof state.sortKeys === "function") { - objectKeyList.sort(state.sortKeys); - } else if (state.sortKeys) { - throw new exception("sortKeys must be a boolean or a function"); + return result; } - for (index = 0, length = objectKeyList.length; index < length; index += 1) { - pairBuffer = ""; - if (!compact || _result !== "") { - pairBuffer += generateNextLine(state, level); + function writeFlowSequence(state, level, object2) { + let _result = ""; + const _tag = state.tag; + for (let index = 0, length = object2.length; index < length; index += 1) { + let value = object2[index]; + if (state.replacer) { + value = state.replacer.call(object2, String(index), value); + } + if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) { + if (_result !== "") _result += "," + (!state.condenseFlow ? " " : ""); + _result += state.dump; + } } - objectKey = objectKeyList[index]; - objectValue = object2[objectKey]; - if (state.replacer) { - objectValue = state.replacer.call(object2, objectKey, objectValue); + state.tag = _tag; + state.dump = "[" + _result + "]"; + } + function writeBlockSequence(state, level, object2, compact) { + let _result = ""; + const _tag = state.tag; + for (let index = 0, length = object2.length; index < length; index += 1) { + let value = object2[index]; + if (state.replacer) { + value = state.replacer.call(object2, String(index), value); + } + if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) { + if (!compact || _result !== "") { + _result += generateNextLine(state, level); + } + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + _result += "-"; + } else { + _result += "- "; + } + _result += state.dump; + } } - if (!writeNode(state, level + 1, objectKey, true, true, true)) { - continue; + state.tag = _tag; + state.dump = _result || "[]"; + } + function writeFlowMapping(state, level, object2) { + let _result = ""; + const _tag = state.tag; + const objectKeyList = Object.keys(object2); + for (let index = 0, length = objectKeyList.length; index < length; index += 1) { + let pairBuffer = ""; + if (_result !== "") pairBuffer += ", "; + if (state.condenseFlow) pairBuffer += '"'; + const objectKey = objectKeyList[index]; + let objectValue = object2[objectKey]; + if (state.replacer) { + objectValue = state.replacer.call(object2, objectKey, objectValue); + } + if (!writeNode(state, level, objectKey, false, false)) { + continue; + } + if (state.dump.length > 1024) pairBuffer += "? "; + pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " "); + if (!writeNode(state, level, objectValue, false, false)) { + continue; + } + pairBuffer += state.dump; + _result += pairBuffer; } - explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024; - if (explicitPair) { + state.tag = _tag; + state.dump = "{" + _result + "}"; + } + function writeBlockMapping(state, level, object2, compact) { + let _result = ""; + const _tag = state.tag; + const objectKeyList = Object.keys(object2); + if (state.sortKeys === true) { + objectKeyList.sort(); + } else if (typeof state.sortKeys === "function") { + objectKeyList.sort(state.sortKeys); + } else if (state.sortKeys) { + throw new YAMLException2("sortKeys must be a boolean or a function"); + } + for (let index = 0, length = objectKeyList.length; index < length; index += 1) { + let pairBuffer = ""; + if (!compact || _result !== "") { + pairBuffer += generateNextLine(state, level); + } + const objectKey = objectKeyList[index]; + let objectValue = object2[objectKey]; + if (state.replacer) { + objectValue = state.replacer.call(object2, objectKey, objectValue); + } + if (!writeNode(state, level + 1, objectKey, true, true, true)) { + continue; + } + const explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024; + if (explicitPair) { + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += "?"; + } else { + pairBuffer += "? "; + } + } + pairBuffer += state.dump; + if (explicitPair) { + pairBuffer += generateNextLine(state, level); + } + if (!writeNode(state, level + 1, objectValue, true, explicitPair)) { + continue; + } if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { - pairBuffer += "?"; + pairBuffer += ":"; } else { - pairBuffer += "? "; + pairBuffer += ": "; } + pairBuffer += state.dump; + _result += pairBuffer; } - pairBuffer += state.dump; - if (explicitPair) { - pairBuffer += generateNextLine(state, level); - } - if (!writeNode(state, level + 1, objectValue, true, explicitPair)) { - continue; - } - if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { - pairBuffer += ":"; - } else { - pairBuffer += ": "; - } - pairBuffer += state.dump; - _result += pairBuffer; - } - state.tag = _tag; - state.dump = _result || "{}"; -} -function detectType(state, object2, explicit) { - var _result, typeList, index, length, type2, style; - typeList = explicit ? state.explicitTypes : state.implicitTypes; - for (index = 0, length = typeList.length; index < length; index += 1) { - type2 = typeList[index]; - if ((type2.instanceOf || type2.predicate) && (!type2.instanceOf || typeof object2 === "object" && object2 instanceof type2.instanceOf) && (!type2.predicate || type2.predicate(object2))) { - if (explicit) { - if (type2.multi && type2.representName) { - state.tag = type2.representName(object2); + state.tag = _tag; + state.dump = _result || "{}"; + } + function detectType(state, object2, explicit) { + const typeList = explicit ? state.explicitTypes : state.implicitTypes; + for (let index = 0, length = typeList.length; index < length; index += 1) { + const type2 = typeList[index]; + if ((type2.instanceOf || type2.predicate) && (!type2.instanceOf || typeof object2 === "object" && object2 instanceof type2.instanceOf) && (!type2.predicate || type2.predicate(object2))) { + if (explicit) { + if (type2.multi && type2.representName) { + state.tag = type2.representName(object2); + } else { + state.tag = type2.tag; + } } else { - state.tag = type2.tag; + state.tag = "?"; } - } else { - state.tag = "?"; - } - if (type2.represent) { - style = state.styleMap[type2.tag] || type2.defaultStyle; - if (_toString.call(type2.represent) === "[object Function]") { - _result = type2.represent(object2, style); - } else if (_hasOwnProperty.call(type2.represent, style)) { - _result = type2.represent[style](object2, style); - } else { - throw new exception("!<" + type2.tag + '> tag resolver accepts not "' + style + '" style'); + if (type2.represent) { + const style = state.styleMap[type2.tag] || type2.defaultStyle; + let _result; + if (_toString.call(type2.represent) === "[object Function]") { + _result = type2.represent(object2, style); + } else if (_hasOwnProperty.call(type2.represent, style)) { + _result = type2.represent[style](object2, style); + } else { + throw new YAMLException2("!<" + type2.tag + '> tag resolver accepts not "' + style + '" style'); + } + state.dump = _result; } - state.dump = _result; + return true; } - return true; } + return false; } - return false; -} -function writeNode(state, level, object2, block, compact, iskey, isblockseq) { - state.tag = null; - state.dump = object2; - if (!detectType(state, object2, false)) { - detectType(state, object2, true); - } - var type2 = _toString.call(state.dump); - var inblock = block; - var tagStr; - if (block) { - block = state.flowLevel < 0 || state.flowLevel > level; - } - var objectOrArray = type2 === "[object Object]" || type2 === "[object Array]", duplicateIndex, duplicate; - if (objectOrArray) { - duplicateIndex = state.duplicates.indexOf(object2); - duplicate = duplicateIndex !== -1; - } - if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) { - compact = false; - } - if (duplicate && state.usedDuplicates[duplicateIndex]) { - state.dump = "*ref_" + duplicateIndex; - } else { - if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { - state.usedDuplicates[duplicateIndex] = true; - } - if (type2 === "[object Object]") { - if (block && Object.keys(state.dump).length !== 0) { - writeBlockMapping(state, level, state.dump, compact); - if (duplicate) { - state.dump = "&ref_" + duplicateIndex + state.dump; - } - } else { - writeFlowMapping(state, level, state.dump); - if (duplicate) { - state.dump = "&ref_" + duplicateIndex + " " + state.dump; + function writeNode(state, level, object2, block, compact, iskey, isblockseq) { + state.tag = null; + state.dump = object2; + if (!detectType(state, object2, false)) { + detectType(state, object2, true); + } + const type2 = _toString.call(state.dump); + const inblock = block; + if (block) { + block = state.flowLevel < 0 || state.flowLevel > level; + } + const objectOrArray = type2 === "[object Object]" || type2 === "[object Array]"; + let duplicateIndex; + let duplicate; + if (objectOrArray) { + duplicateIndex = state.duplicates.indexOf(object2); + duplicate = duplicateIndex !== -1; + } + if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) { + compact = false; + } + if (duplicate && state.usedDuplicates[duplicateIndex]) { + state.dump = "*ref_" + duplicateIndex; + } else { + if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { + state.usedDuplicates[duplicateIndex] = true; + } + if (type2 === "[object Object]") { + if (block && Object.keys(state.dump).length !== 0) { + writeBlockMapping(state, level, state.dump, compact); + if (duplicate) { + state.dump = "&ref_" + duplicateIndex + state.dump; + } + } else { + writeFlowMapping(state, level, state.dump); + if (duplicate) { + state.dump = "&ref_" + duplicateIndex + " " + state.dump; + } } - } - } else if (type2 === "[object Array]") { - if (block && state.dump.length !== 0) { - if (state.noArrayIndent && !isblockseq && level > 0) { - writeBlockSequence(state, level - 1, state.dump, compact); + } else if (type2 === "[object Array]") { + if (block && state.dump.length !== 0) { + if (state.noArrayIndent && !isblockseq && level > 0) { + writeBlockSequence(state, level - 1, state.dump, compact); + } else { + writeBlockSequence(state, level, state.dump, compact); + } + if (duplicate) { + state.dump = "&ref_" + duplicateIndex + state.dump; + } } else { - writeBlockSequence(state, level, state.dump, compact); + writeFlowSequence(state, level, state.dump); + if (duplicate) { + state.dump = "&ref_" + duplicateIndex + " " + state.dump; + } } - if (duplicate) { - state.dump = "&ref_" + duplicateIndex + state.dump; + } else if (type2 === "[object String]") { + if (state.tag !== "?") { + writeScalar(state, state.dump, level, iskey, inblock); } + } else if (type2 === "[object Undefined]") { + return false; } else { - writeFlowSequence(state, level, state.dump); - if (duplicate) { - state.dump = "&ref_" + duplicateIndex + " " + state.dump; + if (state.skipInvalid) return false; + throw new YAMLException2("unacceptable kind of an object to dump " + type2); + } + if (state.tag !== null && state.tag !== "?") { + let tagStr = encodeURI( + state.tag[0] === "!" ? state.tag.slice(1) : state.tag + ).replace(/!/g, "%21"); + if (state.tag[0] === "!") { + tagStr = "!" + tagStr; + } else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") { + tagStr = "!!" + tagStr.slice(18); + } else { + tagStr = "!<" + tagStr + ">"; } + state.dump = tagStr + " " + state.dump; } - } else if (type2 === "[object String]") { - if (state.tag !== "?") { - writeScalar(state, state.dump, level, iskey, inblock); - } - } else if (type2 === "[object Undefined]") { - return false; - } else { - if (state.skipInvalid) return false; - throw new exception("unacceptable kind of an object to dump " + type2); - } - if (state.tag !== null && state.tag !== "?") { - tagStr = encodeURI( - state.tag[0] === "!" ? state.tag.slice(1) : state.tag - ).replace(/!/g, "%21"); - if (state.tag[0] === "!") { - tagStr = "!" + tagStr; - } else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") { - tagStr = "!!" + tagStr.slice(18); - } else { - tagStr = "!<" + tagStr + ">"; - } - state.dump = tagStr + " " + state.dump; } + return true; } - return true; -} -function getDuplicateReferences(object2, state) { - var objects = [], duplicatesIndexes = [], index, length; - inspectNode(object2, objects, duplicatesIndexes); - for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) { - state.duplicates.push(objects[duplicatesIndexes[index]]); - } - state.usedDuplicates = new Array(length); -} -function inspectNode(object2, objects, duplicatesIndexes) { - var objectKeyList, index, length; - if (object2 !== null && typeof object2 === "object") { - index = objects.indexOf(object2); - if (index !== -1) { - if (duplicatesIndexes.indexOf(index) === -1) { - duplicatesIndexes.push(index); - } - } else { - objects.push(object2); - if (Array.isArray(object2)) { - for (index = 0, length = object2.length; index < length; index += 1) { - inspectNode(object2[index], objects, duplicatesIndexes); + function getDuplicateReferences(object2, state) { + const objects = []; + const duplicatesIndexes = []; + inspectNode(object2, objects, duplicatesIndexes); + const length = duplicatesIndexes.length; + for (let index = 0; index < length; index += 1) { + state.duplicates.push(objects[duplicatesIndexes[index]]); + } + state.usedDuplicates = new Array(length); + } + function inspectNode(object2, objects, duplicatesIndexes) { + if (object2 !== null && typeof object2 === "object") { + const index = objects.indexOf(object2); + if (index !== -1) { + if (duplicatesIndexes.indexOf(index) === -1) { + duplicatesIndexes.push(index); } } else { - objectKeyList = Object.keys(object2); - for (index = 0, length = objectKeyList.length; index < length; index += 1) { - inspectNode(object2[objectKeyList[index]], objects, duplicatesIndexes); + objects.push(object2); + if (Array.isArray(object2)) { + for (let i = 0, length = object2.length; i < length; i += 1) { + inspectNode(object2[i], objects, duplicatesIndexes); + } + } else { + const objectKeyList = Object.keys(object2); + for (let i = 0, length = objectKeyList.length; i < length; i += 1) { + inspectNode(object2[objectKeyList[i]], objects, duplicatesIndexes); + } } } } } -} -function dump$1(input, options) { - options = options || {}; - var state = new State(options); - if (!state.noRefs) getDuplicateReferences(input, state); - var value = input; - if (state.replacer) { - value = state.replacer.call({ "": value }, "", value); + function dump2(input, options) { + options = options || {}; + const state = new State(options); + if (!state.noRefs) getDuplicateReferences(input, state); + let value = input; + if (state.replacer) { + value = state.replacer.call({ "": value }, "", value); + } + if (writeNode(state, 0, value, true, true)) return state.dump + "\n"; + return ""; } - if (writeNode(state, 0, value, true, true)) return state.dump + "\n"; - return ""; -} -var dump_1 = dump$1; -var dumper = { - dump: dump_1 -}; -function renamed(from, to) { - return function() { - throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default."); - }; -} -var Type = type; -var Schema = schema; -var FAILSAFE_SCHEMA = failsafe; -var JSON_SCHEMA = json; -var CORE_SCHEMA = core; -var DEFAULT_SCHEMA = _default; -var load = loader.load; -var loadAll = loader.loadAll; -var dump = dumper.dump; -var YAMLException = exception; -var types = { - binary, - float, - map, - null: _null, - pairs, - set, - timestamp, - bool, - int, - merge, - omap, - seq, - str -}; -var safeLoad = renamed("safeLoad", "load"); -var safeLoadAll = renamed("safeLoadAll", "loadAll"); -var safeDump = renamed("safeDump", "dump"); -var jsYaml = { + dumper.dump = dump2; + return dumper; +} +var hasRequiredJsYaml; +function requireJsYaml() { + if (hasRequiredJsYaml) return jsYaml; + hasRequiredJsYaml = 1; + const loader2 = requireLoader(); + const dumper2 = requireDumper(); + function renamed(from, to) { + return function() { + throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default."); + }; + } + jsYaml.Type = requireType(); + jsYaml.Schema = requireSchema(); + jsYaml.FAILSAFE_SCHEMA = requireFailsafe(); + jsYaml.JSON_SCHEMA = requireJson(); + jsYaml.CORE_SCHEMA = requireCore(); + jsYaml.DEFAULT_SCHEMA = require_default(); + jsYaml.load = loader2.load; + jsYaml.loadAll = loader2.loadAll; + jsYaml.dump = dumper2.dump; + jsYaml.YAMLException = requireException(); + jsYaml.types = { + binary: requireBinary(), + float: requireFloat(), + map: requireMap(), + null: require_null(), + pairs: requirePairs(), + set: requireSet(), + timestamp: requireTimestamp(), + bool: requireBool(), + int: requireInt(), + merge: requireMerge(), + omap: requireOmap(), + seq: requireSeq(), + str: requireStr() + }; + jsYaml.safeLoad = renamed("safeLoad", "load"); + jsYaml.safeLoadAll = renamed("safeLoadAll", "loadAll"); + jsYaml.safeDump = renamed("safeDump", "dump"); + return jsYaml; +} +var jsYamlExports = requireJsYaml(); +var yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports); +var { Type, Schema, FAILSAFE_SCHEMA, @@ -2629,7 +3071,7 @@ var jsYaml = { safeLoad, safeLoadAll, safeDump -}; +} = yaml; // ../../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js var external_exports = {}; @@ -2753,7 +3195,7 @@ __export(external_exports, { flattenError: () => flattenError, float32: () => float32, float64: () => float64, - formatError: () => formatError2, + formatError: () => formatError, fromJSONSchema: () => fromJSONSchema, function: () => _function, getErrorMap: () => getErrorMap, @@ -3122,7 +3564,7 @@ __export(core_exports2, { extractDefs: () => extractDefs, finalize: () => finalize, flattenError: () => flattenError, - formatError: () => formatError2, + formatError: () => formatError, globalConfig: () => globalConfig, globalRegistry: () => globalRegistry, initializeContext: () => initializeContext, @@ -3174,8 +3616,8 @@ function $constructor(name, initializer3, params) { initializer3(inst, def); const proto = _.prototype; const keys = Object.keys(proto); - for (let i2 = 0; i2 < keys.length; i2++) { - const k = keys[i2]; + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; if (!(k in inst)) { inst[k] = proto[k].bind(inst); } @@ -3251,7 +3693,7 @@ __export(util_exports, { defineLazy: () => defineLazy, esc: () => esc, escapeRegex: () => escapeRegex, - extend: () => extend3, + extend: () => extend, finalizeIssue: () => finalizeIssue, floatSafeRemainder: () => floatSafeRemainder, getElementAtPath: () => getElementAtPath, @@ -3260,7 +3702,7 @@ __export(util_exports, { getParsedType: () => getParsedType, getSizableOrigin: () => getSizableOrigin, hexToUint8Array: () => hexToUint8Array, - isObject: () => isObject2, + isObject: () => isObject, isPlainObject: () => isPlainObject, issue: () => issue, joinValues: () => joinValues, @@ -3408,8 +3850,8 @@ function promiseAllObject(promisesObj) { const promises = keys.map((key) => promisesObj[key]); return Promise.all(promises).then((results) => { const resolvedObj = {}; - for (let i2 = 0; i2 < keys.length; i2++) { - resolvedObj[keys[i2]] = results[i2]; + for (let i = 0; i < keys.length; i++) { + resolvedObj[keys[i]] = results[i]; } return resolvedObj; }); @@ -3417,7 +3859,7 @@ function promiseAllObject(promisesObj) { function randomString(length = 10) { const chars = "abcdefghijklmnopqrstuvwxyz"; let str2 = ""; - for (let i2 = 0; i2 < length; i2++) { + for (let i = 0; i < length; i++) { str2 += chars[Math.floor(Math.random() * chars.length)]; } return str2; @@ -3430,7 +3872,7 @@ function slugify(input) { } var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => { }; -function isObject2(data) { +function isObject(data) { return typeof data === "object" && data !== null && !Array.isArray(data); } var allowsEval = cached(() => { @@ -3446,7 +3888,7 @@ var allowsEval = cached(() => { } }); function isPlainObject(o) { - if (isObject2(o) === false) + if (isObject(o) === false) return false; const ctor = o.constructor; if (ctor === void 0) @@ -3454,7 +3896,7 @@ function isPlainObject(o) { if (typeof ctor !== "function") return true; const prot = ctor.prototype; - if (isObject2(prot) === false) + if (isObject(prot) === false) return false; if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) { return false; @@ -3654,7 +4096,7 @@ function omit(schema2, mask) { }); return clone(schema2, def); } -function extend3(schema2, shape) { +function extend(schema2, shape) { if (!isPlainObject(shape)) { throw new Error("Invalid input to extend: expected a plain object"); } @@ -3777,8 +4219,8 @@ function required(Class2, schema2, mask) { function aborted(x, startIndex = 0) { if (x.aborted === true) return true; - for (let i2 = startIndex; i2 < x.issues.length; i2++) { - if (x.issues[i2]?.continue !== true) { + for (let i = startIndex; i < x.issues.length; i++) { + if (x.issues[i]?.continue !== true) { return true; } } @@ -3865,15 +4307,15 @@ function cleanEnum(obj) { function base64ToUint8Array(base643) { const binaryString = atob(base643); const bytes = new Uint8Array(binaryString.length); - for (let i2 = 0; i2 < binaryString.length; i2++) { - bytes[i2] = binaryString.charCodeAt(i2); + for (let i = 0; i < binaryString.length; i++) { + bytes[i] = binaryString.charCodeAt(i); } return bytes; } function uint8ArrayToBase64(bytes) { let binaryString = ""; - for (let i2 = 0; i2 < bytes.length; i2++) { - binaryString += String.fromCharCode(bytes[i2]); + for (let i = 0; i < bytes.length; i++) { + binaryString += String.fromCharCode(bytes[i]); } return btoa(binaryString); } @@ -3891,8 +4333,8 @@ function hexToUint8Array(hex3) { throw new Error("Invalid hex string length"); } const bytes = new Uint8Array(cleanHex.length / 2); - for (let i2 = 0; i2 < cleanHex.length; i2 += 2) { - bytes[i2 / 2] = Number.parseInt(cleanHex.slice(i2, i2 + 2), 16); + for (let i = 0; i < cleanHex.length; i += 2) { + bytes[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16); } return bytes; } @@ -3936,7 +4378,7 @@ function flattenError(error48, mapper = (issue2) => issue2.message) { } return { formErrors, fieldErrors }; } -function formatError2(error48, mapper = (issue2) => issue2.message) { +function formatError(error48, mapper = (issue2) => issue2.message) { const fieldErrors = { _errors: [] }; const processError = (error49) => { for (const issue2 of error49.issues) { @@ -3950,10 +4392,10 @@ function formatError2(error48, mapper = (issue2) => issue2.message) { fieldErrors._errors.push(mapper(issue2)); } else { let curr = fieldErrors; - let i2 = 0; - while (i2 < issue2.path.length) { - const el = issue2.path[i2]; - const terminal = i2 === issue2.path.length - 1; + let i = 0; + while (i < issue2.path.length) { + const el = issue2.path[i]; + const terminal = i === issue2.path.length - 1; if (!terminal) { curr[el] = curr[el] || { _errors: [] }; } else { @@ -3961,7 +4403,7 @@ function formatError2(error48, mapper = (issue2) => issue2.message) { curr[el]._errors.push(mapper(issue2)); } curr = curr[el]; - i2++; + i++; } } } @@ -3987,10 +4429,10 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) { continue; } let curr = result; - let i2 = 0; - while (i2 < fullpath.length) { - const el = fullpath[i2]; - const terminal = i2 === fullpath.length - 1; + let i = 0; + while (i < fullpath.length) { + const el = fullpath[i]; + const terminal = i === fullpath.length - 1; if (typeof el === "string") { curr.properties ?? (curr.properties = {}); (_a2 = curr.properties)[el] ?? (_a2[el] = { errors: [] }); @@ -4003,7 +4445,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) { if (terminal) { curr.errors.push(mapper(issue2)); } - i2++; + i++; } } } @@ -5500,16 +5942,16 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => { } payload.value = Array(input.length); const proms = []; - for (let i2 = 0; i2 < input.length; i2++) { - const item = input[i2]; + for (let i = 0; i < input.length; i++) { + const item = input[i]; const result = def.element._zod.run({ value: item, issues: [] }, ctx); if (result instanceof Promise) { - proms.push(result.then((result2) => handleArrayResult(result2, payload, i2))); + proms.push(result.then((result2) => handleArrayResult(result2, payload, i))); } else { - handleArrayResult(result, payload, i2); + handleArrayResult(result, payload, i); } } if (proms.length) { @@ -5612,13 +6054,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => { } return propValues; }); - const isObject3 = isObject2; + const isObject2 = isObject; const catchall = def.catchall; let value; inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject3(input)) { + if (!isObject2(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -5716,7 +6158,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => return (payload, ctx) => fn(shape, payload, ctx); }; let fastpass; - const isObject3 = isObject2; + const isObject2 = isObject; const jit = !globalConfig.jitless; const allowsEval2 = allowsEval; const fastEnabled = jit && allowsEval2.value; @@ -5725,7 +6167,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject3(input)) { + if (!isObject2(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -5903,7 +6345,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio }); inst._zod.parse = (payload, ctx) => { const input = payload.value; - if (!isObject2(input)) { + if (!isObject(input)) { payload.issues.push({ code: "invalid_type", expected: "object", @@ -6060,35 +6502,35 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => { return payload; } } - let i2 = -1; + let i = -1; for (const item of items) { - i2++; - if (i2 >= input.length) { - if (i2 >= optStart) + i++; + if (i >= input.length) { + if (i >= optStart) continue; } const result = item._zod.run({ - value: input[i2], + value: input[i], issues: [] }, ctx); if (result instanceof Promise) { - proms.push(result.then((result2) => handleTupleResult(result2, payload, i2))); + proms.push(result.then((result2) => handleTupleResult(result2, payload, i))); } else { - handleTupleResult(result, payload, i2); + handleTupleResult(result, payload, i); } } if (def.rest) { const rest = input.slice(items.length); for (const el of rest) { - i2++; + i++; const result = def.rest._zod.run({ value: el, issues: [] }, ctx); if (result instanceof Promise) { - proms.push(result.then((result2) => handleTupleResult(result2, payload, i2))); + proms.push(result.then((result2) => handleTupleResult(result2, payload, i))); } else { - handleTupleResult(result, payload, i2); + handleTupleResult(result, payload, i); } } } @@ -14158,9 +14600,9 @@ var objectProcessor = (schema2, ctx, _json, params) => { var unionProcessor = (schema2, ctx, json3, params) => { const def = schema2._zod.def; const isExclusive = def.inclusive === false; - const options = def.options.map((x, i2) => process(x, ctx, { + const options = def.options.map((x, i) => process(x, ctx, { ...params, - path: [...params.path, isExclusive ? "oneOf" : "anyOf", i2] + path: [...params.path, isExclusive ? "oneOf" : "anyOf", i] })); if (isExclusive) { json3.oneOf = options; @@ -14191,9 +14633,9 @@ var tupleProcessor = (schema2, ctx, _json, params) => { json3.type = "array"; const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items"; const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems"; - const prefixItems = def.items.map((x, i2) => process(x, ctx, { + const prefixItems = def.items.map((x, i) => process(x, ctx, { ...params, - path: [...params.path, prefixPath, i2] + path: [...params.path, prefixPath, i] })); const rest = def.rest ? process(def.rest, ctx, { ...params, @@ -14744,7 +15186,7 @@ var initializer2 = (inst, issues) => { inst.name = "ZodError"; Object.defineProperties(inst, { format: { - value: (mapper) => formatError2(inst, mapper) + value: (mapper) => formatError(inst, mapper) // enumerable: false, }, flatten: { @@ -16223,8 +16665,8 @@ function convertBaseSchema(schema2, ctx) { zodSchema = schemasToIntersect[0]; } else { let result = z.intersection(schemasToIntersect[0], schemasToIntersect[1]); - for (let i2 = 2; i2 < schemasToIntersect.length; i2++) { - result = z.intersection(result, schemasToIntersect[i2]); + for (let i = 2; i < schemasToIntersect.length; i++) { + result = z.intersection(result, schemasToIntersect[i]); } zodSchema = result; } @@ -16319,8 +16761,8 @@ function convertSchema(schema2, ctx) { } else { let result = hasExplicitType ? baseSchema : convertSchema(schema2.allOf[0], ctx); const startIdx = hasExplicitType ? 0 : 1; - for (let i2 = startIdx; i2 < schema2.allOf.length; i2++) { - result = z.intersection(result, convertSchema(schema2.allOf[i2], ctx)); + for (let i = startIdx; i < schema2.allOf.length; i++) { + result = z.intersection(result, convertSchema(schema2.allOf[i], ctx)); } baseSchema = result; } @@ -16424,12 +16866,28 @@ PLATFORM_ADMIN_EMAIL={{PLATFORM_ADMIN_EMAIL}} AUTH_REQUIRED=true ENVIRONMENT=production SECURITY_HEADERS_ENABLED=true +# A2A/UAID cross-gateway routing is unused here (this gateway federates MCP servers +# only), so the subsystem is off rather than carrying its startup noise and an unused +# routing surface. Two of the gateway's UAID checks gate on this flag and go quiet on +# any image; a third does not, and needs a gateway build that gates it. +MCPGATEWAY_A2A_ENABLED=false +# ContextForge 1.0.7 flips CSRF_ENABLED's default to true. Traffic here is +# Bearer-authenticated MCP or credential-less, which the CSRF middleware exempts +# anyway; pinning false keeps the 1.0.6.3 behaviour and one fewer moving part +# per upgrade. Hub-path requests carry no browser CSRF cookie to protect. +CSRF_ENABLED=false # \u2500\u2500\u2500 Logging \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 LOG_LEVEL={{LOG_LEVEL}} STRUCTURED_LOGGING_DATABASE_ENABLED=false AUDIT_TRAIL_ENABLED=false DISABLE_ACCESS_LOG=false +# CPEX control-execution telemetry (new in ContextForge 1.0.7). Both sinks are +# inert without OBSERVABILITY_ENABLED=true, which this template leaves off; pinned +# off so a future observability flip cannot start writing telemetry rows to mcp.db +# unasked. Belt-and-braces, not load-bearing. +CPEX_CONTROL_TELEMETRY_ENABLED=false +CPEX_CONTROL_TELEMETRY_DB_ENABLED=false # \u2500\u2500\u2500 Server \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 # Worker count is pinned to 1 until three multi-worker prerequisites land: @@ -16453,6 +16911,7 @@ ALLOWED_ORIGINS={{ALLOWED_ORIGINS}} # \u2500\u2500\u2500 SOTW (State of the World) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 SOTW_ENABLED={{SOTW_ENABLED}} SOTW_FILE_PATH={{SOTW_FILE_PATH}} +SOTW_DELETE_POLICY={{SOTW_DELETE_POLICY}} # \u2500\u2500\u2500 Pulse \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 PULSE_ENABLED={{PULSE_ENABLED}} @@ -16471,9 +16930,10 @@ SSRF_ALLOWED_NETWORKS={{SSRF_ALLOWED_NETWORKS}} SSRF_DNS_FAIL_CLOSED={{SSRF_DNS_FAIL_CLOSED}} # \u2500\u2500\u2500 Multi-tenancy (ADR-015) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -# Each gateway is single-tenant by deployment; D2_TENANT_ID anchors the -# session-state scope key (ADR-015 \xA7"Tenant-scope provenance"). Without it, -# session writes silently no-op (no event, no apply). +# A gateway is single-tenant by deployment (an allowMultiTenantAuth gateway +# still scopes to its owner here); D2_TENANT_ID anchors the session-state +# scope key (ADR-015 \xA7"Tenant-scope provenance"). Without it, session writes +# silently no-op (no event, no apply). D2_TENANT_ID={{D2_TENANT_ID}} `; var OPTIONAL_ENV_SECTIONS = [ @@ -16509,11 +16969,13 @@ var OPTIONAL_ENV_SECTIONS = [ // (armed). The session_clear plugin refuses to mint when // SESSION_CONTROL_CLIENT_ID is absent, so omitting the section is what // keeps clearing inert on unarmed gateways. SESSION_CONTROL_REDIRECT_URI - // is deliberately NOT reserved here — contextforge derives it from its - // own public host, and `gateway.advanced` stays available as the - // override escape hatch. + // is rendered only when `session_control.redirect_uri` names one; + // otherwise contextforge derives it from the gateway's own audience. + // Listing it here reserves the key, so the typed field is the only way to + // set it and `gateway.advanced` can no longer shadow what the platform + // allow-lists on the IdP application. header: "# \u2500\u2500\u2500 Session Control (human-gated clearing) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500", - keys: ["SESSION_CONTROL_CLIENT_ID", "SESSION_CONTROL_ISSUER"] + keys: ["SESSION_CONTROL_CLIENT_ID", "SESSION_CONTROL_ISSUER", "SESSION_CONTROL_REDIRECT_URI"] } ]; var SECRET_KEYS = ["AUTH_ENCRYPTION_SECRET", "JWT_SECRET_KEY", "PLATFORM_ADMIN_PASSWORD"]; @@ -16543,7 +17005,7 @@ function innerWrapper(type2) { } function unwrap(node) { let cursor = node; - for (let i2 = 0; i2 < WRAPPER_CAP; i2++) { + for (let i = 0; i < WRAPPER_CAP; i++) { const def = cursor.def; if (!def) break; if (innerWrapper(def.type) && def.innerType) { @@ -16560,7 +17022,7 @@ function unwrap(node) { } function readTarget(node) { let cursor = node; - for (let i2 = 0; i2 < WRAPPER_CAP; i2++) { + for (let i = 0; i < WRAPPER_CAP; i++) { const meta4 = typeof cursor.meta === "function" ? cursor.meta() : void 0; const target = meta4?.target; if (typeof target === "string") return target; @@ -16660,6 +17122,18 @@ function isNormalizedHttpsIssuer(value) { } return url2.protocol === "https:"; } +var REDIRECT_LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function isRenderableRedirectUri(value) { + if (CONTROL_OR_WHITESPACE_RE.test(value)) return false; + let url2; + try { + url2 = new URL(value); + } catch { + return false; + } + if (url2.protocol === "https:") return true; + return url2.protocol === "http:" && REDIRECT_LOOPBACK_HOSTS.has(url2.hostname); +} var SYMMETRIC_ALGORITHMS = ["HS256", "HS384", "HS512"]; var ASYMMETRIC_ALGORITHMS = ["RS256", "RS384", "RS512", "ES256", "ES384", "ES512"]; var JWT_ALGORITHM_TYPES = [...SYMMETRIC_ALGORITHMS, ...ASYMMETRIC_ALGORITHMS]; @@ -16954,7 +17428,7 @@ var SsrfSchema = external_exports.object({ target: "SSRF_ALLOWED_NETWORKS", deployDefault: "[]", audience: "user", - rationale: "Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts \u2014 prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface." + rationale: "Set to the specific CIDRs your MCP servers live on when the gateway must reach private hosts \u2014 prefer this surgical allowlist over the blanket `allow_private_networks=true`, since every range you add widens the gateway's outbound attack surface. Shared address space `100.64.0.0/10` (CGNAT \u2014 every Tailscale node address, for example) is blocked on every server registration and config import since ContextForge 1.0.7, above every other SSRF setting; a CIDR here that lies wholly inside `100.64.0.0/10` (e.g. `100.64.0.0/10` itself or your tailnet subnet) re-permits those addresses. Broad entries such as `100.0.0.0/8` or `0.0.0.0/0` do not." }) ), dns_fail_closed: external_exports.boolean().optional().meta( @@ -17002,19 +17476,29 @@ var SessionControlClearingSchema = external_exports.object({ description: "Arm human-gated clearing of session intent and markers. Unset follows `gateway.intent.enabled`. `false` while intent is enabled is a deploy error (clearing cannot be withdrawn where markers can block).", target: "platform.session_control.clearing.enabled", audience: "user", - rationale: "Leave unset in almost all cases \u2014 clearing arms automatically wherever intent capture is on and this block is configured. Set `true` explicitly on a gateway that runs marker-writing policies WITHOUT intent capture, which otherwise has no targeted clear path and can only wait for a marker to expire." + rationale: "Write `true` whenever you want clearing. It is only strictly *required* on a gateway that runs marker-writing policies WITHOUT intent capture \u2014 with intent capture on, the block arms on its own \u2014 but stating it makes the block say what it does rather than leaving that to `gateway.intent.enabled`, and it keeps clearing armed if intent capture is later turned off. `false` while intent capture is on is rejected: clearing cannot be withdrawn where markers can block." }) ) }).strict(); var SessionControlSchema = external_exports.object({ client_id: external_exports.string().min(1).regex(SESSION_CONTROL_CLIENT_ID_RE, { message: "client_id must be printable non-whitespace ASCII (no spaces, newlines, or control characters). It is rendered as a SESSION_CONTROL_CLIENT_ID= line in the gateway env file; whitespace or a newline could inject a second assignment." - }).meta( + }).optional().meta( meta3({ - description: "Public client id of the dedicated session-control OAuth app (native, PKCE, no client secret).", + description: "Public client id of the dedicated session-control OAuth app (native, PKCE, no client secret). Optional on a gateway authenticating against Dtwo's Auth0: the platform provisions one per organization and renders it at deploy. An explicit value always wins.", target: "SESSION_CONTROL_CLIENT_ID", audience: "user", - rationale: "Register a dedicated public client at your IdP for the clear ceremony (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client." + rationale: "Leave unset on a gateway using Dtwo authentication. Set it only when the gateway trusts your own IdP: the ceremony app must live in the IdP that issues the gateway's inbound tokens, so register a dedicated public client there (authorization-code + PKCE, no refresh grant) and paste its client id here. Do not reuse the gateway API client." + }) + ), + redirect_uri: external_exports.string().min(1).refine(isRenderableRedirectUri, { + message: "redirect_uri must be an absolute https:// URL (http:// only on localhost, 127.0.0.1, or [::1]) with no whitespace or control characters. It is rendered as a SESSION_CONTROL_REDIRECT_URI= line in the gateway env file; whitespace or a newline could inject a second assignment." + }).optional().meta( + meta3({ + description: "Callback URL the browser clear ceremony redirects to, overriding the one the gateway derives from its own token audience. Must be an absolute `https://` URL (`http://` only on localhost, 127.0.0.1, or [::1]). Optional: leave it unset unless the browser reaches the gateway at a different origin than its audience. An explicit value always wins, and the platform allow-lists it verbatim on the IdP application.", + target: "SESSION_CONTROL_REDIRECT_URI", + audience: "user", + rationale: "Leave unset in almost all cases \u2014 the gateway derives `/session-control/clear/callback` and the platform registers that. Set it when a reverse proxy or split-horizon DNS puts the browser on a different origin than the audience: give the URL the browser can actually reach, at the root path (`/mcp/*` routes to the streamable-HTTP handler, which rejects browser GETs)." }) ), // There is deliberately NO `issuer` field. The ceremony's issuer is always @@ -17031,11 +17515,13 @@ var SessionControlSchema = external_exports.object({ ) }).strict().meta( meta3({ - description: "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. The ceremony issuer is not configured here \u2014 it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it.", + description: "Human-gated session clearing (session-control) registration: the IdP app the browser ceremony authenticates against. Arms the platform clear tools and the browser clear ceremony when `intent.enabled: true`, or when `clearing.enabled: true` on a gateway that uses markers without intent capture. A gateway using Dtwo authentication needs no credentials here \u2014 it gets its organization's platform-provisioned app \u2014 but prefer `clearing: {enabled: true}` over an empty block, so the block states what it does: an empty one arms only while `intent.enabled` is true and parks inert otherwise. `client_id` is only needed for a gateway trusting a customer-run IdP, and `redirect_uri` only for one the browser reaches at a different origin than its token audience. The ceremony issuer is not configured here \u2014 it is always `gateway.authentication.jwks_info.jwt_issuer` (the same tenant issues both the inbound tokens and the browser-login ID tokens), and the deploy derives `SESSION_CONTROL_ISSUER` from it.", crossFieldConstraints: [ "`clearing.enabled` unset follows `gateway.intent.enabled`; an explicit `true` arms clearing even with intent capture off (the markers-only deployment).", "`clearing.enabled: false` while `gateway.intent.enabled: true` is rejected (clearing cannot be withdrawn where markers can block).", "While clearing is armed, `gateway.authentication` must be enabled with `jwks_info` \u2014 the ceremony binds every clear to the authenticated caller identity, so an unauthenticated inbound leg has nothing to bind.", + "A gateway that authenticates against an IdP other than Dtwo's Auth0 must set `client_id`: the platform provisions a ceremony app only in its own tenant, and the deploy fails rather than arming a gateway whose ceremony has no application to authenticate against.", + "`redirect_uri`, when set, replaces the callback the gateway would derive from the first entry of `jwt_audience`, and is the URL the platform allow-lists on the IdP application. Unset, ordering within a comma-separated `jwt_audience` decides the callback.", "While clearing is armed, `jwt_issuer` must be a normalized HTTPS URL (it becomes the ceremony issuer via `SESSION_CONTROL_ISSUER`) and `jwt_audience` must not be blank." ] }) @@ -17050,10 +17536,10 @@ var GatewaySchema = external_exports.object({ }) ), advanced: external_exports.array(external_exports.string().min(1)).superRefine((arr, ctx) => { - for (let i2 = 0; i2 < arr.length; i2++) { - const reason = validateAdvancedEntry(arr[i2]); + for (let i = 0; i < arr.length; i++) { + const reason = validateAdvancedEntry(arr[i]); if (reason) { - ctx.addIssue({ code: "custom", path: [i2], message: reason }); + ctx.addIssue({ code: "custom", path: [i], message: reason }); } } }).optional().meta( @@ -17085,7 +17571,7 @@ var GatewaySchema = external_exports.object({ }) ), intent: IntentSchema.optional(), - session_control: SessionControlSchema.optional(), + session_control: external_exports.preprocess((value) => value ?? {}, SessionControlSchema).optional(), log_level: external_exports.enum(LOG_LEVELS).optional().meta( meta3({ description: "ContextForge log level.", @@ -17222,6 +17708,8 @@ var queryParamType = external_exports.object({ }) ) }); +var TOKEN_ENDPOINT_AUTH_METHODS = ["client_secret_basic", "client_secret_post"]; +var tokenEndpointAuthMethod = external_exports.string().transform((s) => s.toLowerCase()).pipe(external_exports.enum(TOKEN_ENDPOINT_AUTH_METHODS)); var oAuthType = external_exports.object({ type: external_exports.literal("oauth").meta(meta3({ description: "Discriminator for OAuth 2.0 auth." })), grant_type: external_exports.string().min(1).meta( @@ -17249,6 +17737,14 @@ var oAuthType = external_exports.object({ rationale: "The OAuth client secret paired with `client_id`. Omit for public clients or when using DCR." }) ), + token_endpoint_auth_method: tokenEndpointAuthMethod.optional().meta( + meta3({ + description: "How the client authenticates to the token endpoint.", + target: "sotw.oauth_config.token_endpoint_auth_method", + audience: "user", + rationale: "Defaults to `client_secret_post`, which sends `client_id`/`client_secret` in the request body. Set `client_secret_basic` for providers that require an HTTP Basic header and reject a body secret with `invalid_client` \u2014 Airtable is one. Ignored on the DCR path: when `issuer` drives dynamic client registration the gateway overwrites this with the method it registered under, so set it only alongside an explicit `client_id`/`client_secret`." + }) + ), token_url: external_exports.url().optional().meta( meta3({ description: "OAuth token endpoint.", @@ -17281,12 +17777,20 @@ var oAuthType = external_exports.object({ rationale: "Set to enable dynamic client registration \u2014 the gateway discovers token/authorize URLs and registers itself automatically." }) ), - scopes: external_exports.array(external_exports.string().min(1)).min(1).meta( + // Optional, and defaulted to `[]` rather than left `undefined` on purpose: + // the deploy path drops undefined auth fields from the SOTW, and the + // gateway treats an ABSENT `oauth_config.scopes` as "unchanged — keep what + // was persisted", so only an explicit empty list actually clears scopes a + // user removed. An empty list is what makes the gateway send no `scope` + // parameter at all. The preprocess folds a bare `scopes:` (YAML null — the + // editor path of deleting every list item and leaving the key) into the + // same empty list, mirroring `session_control` above. + scopes: external_exports.preprocess((value) => value ?? [], external_exports.array(external_exports.string().min(1)).default([])).meta( meta3({ - description: "OAuth scopes requested.", + description: "OAuth scopes requested. Optional: omitted or empty, the gateway sends no `scope` parameter to the provider.", target: "sotw.oauth_config.scopes", audience: "user", - rationale: "Scopes the gateway requests from the provider; match the provider's documented scope strings." + rationale: "Scopes the gateway requests from the provider; match the provider's documented scope strings. Leave it out (or set `[]`) for providers that reject any `scope` parameter with `invalid_scope` \u2014 Docebo is one. With no `scope` parameter the provider applies its own default (RFC 6749 \xA73.3), usually the access configured on the client registration; confirm the issued token carries what the upstream server needs. On the Dynamic Client Registration path (`issuer` without `client_id`/`client_secret`) an omitted `scopes` registers the client with no scopes \u2014 the gateway's own DCR default scope does not apply to configs authored here." }) ), pkce_enabled: external_exports.boolean().optional().meta( @@ -17297,6 +17801,14 @@ var oAuthType = external_exports.object({ rationale: "Enable for public clients where leaking the `client_secret` is a risk." }) ), + omit_resource: external_exports.boolean().optional().meta( + meta3({ + description: "Omit the RFC 8707 resource parameter from OAuth authorize/token requests.", + target: "sotw.oauth_config.omit_resource", + audience: "user", + rationale: "Escape hatch for providers that reject or mishandle the `resource` parameter on authorize, token-exchange, and refresh requests." + }) + ), oauth_quirks: external_exports.array(external_exports.string().min(1)).min(1).optional().meta( meta3({ description: "Provider-specific compatibility flags.", @@ -17339,10 +17851,16 @@ var oAuthType = external_exports.object({ }).refine((data) => data.issuer || data.client_id && data.client_secret && data.token_url, { message: 'OAuth requires either "issuer" or all of "client_id", "client_secret", and "token_url"', path: ["issuer"] +}).refine((data) => data.token_endpoint_auth_method !== "client_secret_basic" || !!data.client_secret, { + message: '"token_endpoint_auth_method: client_secret_basic" requires "client_secret" \u2014 with DCR the gateway registers its own client and picks the method itself', + path: ["token_endpoint_auth_method"] }).meta( meta3({ description: "OAuth 2.0 authentication configuration.", - crossFieldConstraints: ['OAuth requires either "issuer" or all of "client_id", "client_secret", and "token_url"'] + crossFieldConstraints: [ + 'OAuth requires either "issuer" or all of "client_id", "client_secret", and "token_url"', + '"token_endpoint_auth_method: client_secret_basic" requires "client_secret"' + ] }) ); var clientCertType = external_exports.object({ @@ -17364,15 +17882,34 @@ var noneAuthType = external_exports.object({ audience: "internal" }) ); -var McpServerAuthSchema = external_exports.discriminatedUnion("type", [ - bearerType, - basicAuthType, - authHeadersType, - queryParamType, - oAuthType, - clientCertType, - noneAuthType -]); +var isAbsentOrEmptyScopes = (scopes) => scopes === void 0 || scopes === null || Array.isArray(scopes) && scopes.length === 0; +var McpServerAuthSchema = external_exports.preprocess( + (value, ctx) => { + if (value && typeof value === "object" && !Array.isArray(value)) { + const record3 = value; + if (record3.type === "oauth" && isAbsentOrEmptyScopes(record3.scopes)) { + const typo = Object.keys(record3).find((key) => key.toLowerCase() === "scope"); + if (typo !== void 0) { + ctx.addIssue({ + code: "custom", + path: [typo], + message: `Unknown key "${typo}" \u2014 did you mean "scopes" (a list)?` + }); + } + } + } + return value; + }, + external_exports.discriminatedUnion("type", [ + bearerType, + basicAuthType, + authHeadersType, + queryParamType, + oAuthType, + clientCertType, + noneAuthType + ]) +); var VISIBILITY_TYPES = ["public", "team", "private"]; var McpServerSchema = external_exports.object({ name: external_exports.string().min(1).meta( @@ -17488,7 +18025,7 @@ function parseConfig(raw) { } let parsed; try { - parsed = jsYaml.load(raw); + parsed = yaml.load(raw); } catch (e) { return { success: false, error: `Invalid YAML: ${e instanceof Error ? e.message : String(e)}` }; } @@ -17505,7 +18042,7 @@ function parseConfig(raw) { } // src/internal/validator-bundle-entry.ts -var VALIDATOR_BUNDLE_VERSION = "2.0.0"; +var VALIDATOR_BUNDLE_VERSION = "4.0.0"; export { ConfigSchema, VALIDATOR_BUNDLE_VERSION,