# Models: W

> API models starting with W.

## `WaitingOn`

The run it waits (or waited) for, and until when; kept as the record of the wait.

- `run_id: uuid.UUID` (`runId` on the wire)
- `until: AwareDatetime | None` (optional)

## `Warning`

- `code: str`
- `message: str`

## `Warning1`

- `code: Literal['erasure-unmatchable']`
- `message: str`

## `WebhookDelivery`

- `delivery_id: str` (`deliveryId` on the wire)
- `endpoint_id: str` (`endpointId` on the wire)
- `event: kindgi.client.RunFinishedEvent | kindgi.client.ImprovementPassFinishedEvent | kindgi.client.ApprovalRequestedEvent | kindgi.client.WebhookTestEvent`
- `status: Literal['pending', 'delivered', 'failed']`
- `attempts: int`
- `next_attempt_at: AwareDatetime | None` (`nextAttemptAt` on the wire)
- `last_attempt_at: AwareDatetime | None` (`lastAttemptAt` on the wire)
- `last_response_status: int | None` (`lastResponseStatus` on the wire)
- `last_error: str | None` (`lastError` on the wire)
- `created_at: AwareDatetime` (`createdAt` on the wire)
- `delivered_at: AwareDatetime | None` (`deliveredAt` on the wire)

## `WebhookDeliveryCollectionPage`

- `data: list[kindgi.client.WebhookDelivery]`
- `next_cursor: str | None` (`nextCursor` on the wire) (optional)
- `has_more: bool` (`hasMore` on the wire)

## `WebhookEndpoint`

- `endpoint_id: str` (`endpointId` on the wire)
- `url: AnyUrl`
- `events: list[Literal['run.finished', 'improvement-pass.finished', 'approval.requested']]`
- `filter: kindgi.client.WebhookEndpointFilter`
- `description: str | None`
- `secret_ref: kindgi.client.WebhookSecretRef` (`secretRef` on the wire)
- `created_at: AwareDatetime` (`createdAt` on the wire)
- `updated_at: AwareDatetime` (`updatedAt` on the wire)

## `WebhookEndpointCollectionPage`

- `data: list[kindgi.client.WebhookEndpoint]`
- `next_cursor: str | None` (`nextCursor` on the wire) (optional)
- `has_more: bool` (`hasMore` on the wire)

## `WebhookEndpointFilter`

Which events reach the endpoint. Every field narrows; absent fields do not. `run.finished` is sent for top-level runs only.

- `project_id: str | None` (`projectId` on the wire) (optional)
- `flow_ids: list[kindgi.client.FlowId] | None` (`flowIds` on the wire) (optional)
- `include_dry_runs: bool | None` (`includeDryRuns` on the wire) (optional)

## `WebhookEndpointUnregisterResult`

- `endpoint_id: str` (`endpointId` on the wire)
- `unregistered: bool`

## `WebhookFire`

One delivery to a webhook trigger and what came of it. A fire keeps the delivery's event only until its run starts; then only the run has it.

- `fire_id: str` (`fireId` on the wire)
- `trigger_id: str` (`triggerId` on the wire)
- `fired_at: AwareDatetime` (`firedAt` on the wire)
- `outcome: Literal['pending', 'started', 'skipped', 'refused', 'failed']`
- `run_id: uuid.UUID | None` (`runId` on the wire) (optional)
- `detail: str | None` (optional)
- `counts_toward_pause: bool | None` (`countsTowardPause` on the wire) (optional)
- `duplicates: int | None` (optional)
- `last_duplicate_at: AwareDatetime | None` (`lastDuplicateAt` on the wire) (optional)

## `WebhookFirePage`

- `data: list[kindgi.client.WebhookFire]`
- `has_more: bool` (`hasMore` on the wire)
- `next_cursor: str | None` (`nextCursor` on the wire) (optional)

## `WebhookReceipt`

What the receiver did with a delivery.

- `fire_id: str | None` (`fireId` on the wire) (optional)
- `duplicate: bool | None` (optional)
- `skipped: Optional[Literal['paused', 'tenant-suspended', 'project-suspended']]` (optional)
- `received: Optional[Literal['ping']]` (optional)

## `WebhookSecretRef`

A secret by name in the deployment's secrets store, resolved at tenant scope (the same shape as a provider's `secret_ref`). The value is `whsec_` + base64 of at least 24 random bytes (or that base64 alone); the store keeps it, the endpoint keeps only this reference.

- `env_name: str` (`envName` on the wire)
- `name: str`

## `WebhookSignature1`

How a webhook trigger's sender signs. `hmac-sha256`: an HMAC-SHA256 of the raw body under the secret's UTF-8 bytes, in `header`, `hex` or `base64`, after an optional `prefix` (GitHub and Drupal's Webhooks module: `X-Hub-Signature-256`, hex, `sha256=`; WooCommerce: `X-WC-Webhook-Signature`, base64; Shopify: `X-Shopify-Hmac-Sha256`, base64). No timestamp is signed, so only the trigger's dedupe catches a replay. `standard-webhooks`: the Standard Webhooks format (`webhook-id`, `webhook-timestamp`, `webhook-signature: v1,<base64>` over `{id}.{timestamp}.{body}`, a `whsec_` secret), refused past `toleranceSeconds` (default 300) from the receiver's clock; it dedupes on its `webhook-id`.

- `kind: Literal['hmac-sha256']`
- `encoding: Literal['hex', 'base64']`
- `header: str`
- `prefix: str | None` (optional)

## `WebhookSignature2`

How a webhook trigger's sender signs. `hmac-sha256`: an HMAC-SHA256 of the raw body under the secret's UTF-8 bytes, in `header`, `hex` or `base64`, after an optional `prefix` (GitHub and Drupal's Webhooks module: `X-Hub-Signature-256`, hex, `sha256=`; WooCommerce: `X-WC-Webhook-Signature`, base64; Shopify: `X-Shopify-Hmac-Sha256`, base64). No timestamp is signed, so only the trigger's dedupe catches a replay. `standard-webhooks`: the Standard Webhooks format (`webhook-id`, `webhook-timestamp`, `webhook-signature: v1,<base64>` over `{id}.{timestamp}.{body}`, a `whsec_` secret), refused past `toleranceSeconds` (default 300) from the receiver's clock; it dedupes on its `webhook-id`.

- `kind: Literal['standard-webhooks']`
- `tolerance_seconds: int | None` (`toleranceSeconds` on the wire) (optional)

## `WebhookTestEvent`

- `id: str`
- `type: Literal['webhook.test']`
- `created_at: AwareDatetime` (`createdAt` on the wire)
- `data: kindgi.client.Data2`

## `WebhookTriggerCollectionPage`

- `data: list[kindgi.client.WebhookTriggerRecord]`
- `next_cursor: str | None` (`nextCursor` on the wire) (optional)
- `has_more: bool` (`hasMore` on the wire)

## `WebhookTriggerRecord`

A webhook trigger: a signed request to its `receiveUrl` starts a run of its flow, as its owner. The signing secret is never on it, only its name.

- `trigger_id: str` (`triggerId` on the wire)
- `webhook_id: str` (`webhookId` on the wire)
- `receive_url: AnyUrl | None` (`receiveUrl` on the wire) (optional)
- `flow_id: str` (`flowId` on the wire)
- `flow_version: str` (`flowVersion` on the wire)
- `project_id: uuid.UUID` (`projectId` on the wire)
- `owner: kindgi.client.TriggerOwner`
- `input: Any | None` (optional)
- `hmac_secret_name: str` (`hmacSecretName` on the wire)
- `hmac_secret_scope: kindgi.client.RecordedSecretScope1 | kindgi.client.RecordedSecretScope2 | kindgi.client.RecordedSecretScope3 | None` (`hmacSecretScope` on the wire) (optional)
- `signing_secret: str | None` (`signingSecret` on the wire) (optional)
- `signature: kindgi.client.WebhookSignature1 | kindgi.client.WebhookSignature2`
- `delivery_id_header: str | None` (`deliveryIdHeader` on the wire) (optional)
- `body_limit_bytes: int` (`bodyLimitBytes` on the wire)
- `rate_limit_per_minute: int` (`rateLimitPerMinute` on the wire)
- `label: str | None`
- `status: Literal['active', 'paused']`
- `status_reason: str | None` (`statusReason` on the wire) (optional)
- `suppressed_refusals: kindgi.client.SuppressedRefusals | None` (`suppressedRefusals` on the wire) (optional)
- `last_fired_at: AwareDatetime | None` (`lastFiredAt` on the wire)
- `created_at: AwareDatetime` (`createdAt` on the wire)
- `updated_at: AwareDatetime` (`updatedAt` on the wire)

## `WebhookTriggerUnregisterResult`

- `trigger_id: str` (`triggerId` on the wire)
- `unregistered: bool`

## `WhoamiResult`

Introspection of the caller's current authentication context. Always carries `tenantId` and `scopes` (empty for static bearer tokens), plus `userId` when the token carries one; `principal` says whom the caller acts as, and an API key adds `tokenId`, its `role` and the `projectId` it is limited to; session-token callers additionally see `sessionId`, `providerId`, and `expiresAt`. `user` is the caller's directory record, present when the deployment wires an identity directory and it knows the `userId`. `reviewerRole` is set when the caller is a reviewer — its token carries a reviewer role, or its user is a registered reviewer — so clients can gate reviewer-only UI (the approvals surface) without a second round trip.

- `tenant_id: uuid.UUID` (`tenantId` on the wire)
- `actor: str | None` (optional)
- `user_id: str | None` (`userId` on the wire) (optional)
- `session_id: str | None` (`sessionId` on the wire) (optional)
- `provider_id: str | None` (`providerId` on the wire) (optional)
- `scopes: list[str]`
- `expires_at: AwareDatetime | None` (`expiresAt` on the wire) (optional)
- `reviewer_role: Optional[Literal['standard', 'senior', 'admin']]` (`reviewerRole` on the wire) (optional)
- `user: kindgi.client.UserRecord | None` (optional)
- `principal: kindgi.client.ApiKeyPrincipal | None` (optional)
- `token_id: str | None` (`tokenId` on the wire) (optional)
- `role: Optional[Literal['admin', 'member']]` (optional)
- `project_id: str | None` (`projectId` on the wire) (optional)
- `tenant_admin: bool | None` (`tenantAdmin` on the wire) (optional)

## `WireError`

- `error: kindgi.client.Error`

## `WithdrawProposalBody`

- `reason: str`

## `Withdrawn`

- `at: AwareDatetime`
- `by: str`
- `reason: str`

## `WriteFactBody`

Write a fact. `type` selects the retrieval-policy (which indexes populate); `scope.tenantId` MUST match the caller's tenant. Optional `retention` overrides tenant defaults; optional `contentHash` is a caller-supplied idempotence hint (runtime computes its own hash regardless). `subjects` names whom it is about; `validFrom`/`validUntil` when it is true in the world; `observedAt` when it was said or seen.

- `type: str`
- `scope: kindgi.client.FactScope`
- `content: Any`
- `retention: kindgi.client.Retention | None` (optional)
- `content_hash: str | None` (`contentHash` on the wire) (optional)
- `subjects: list[kindgi.client.FactSubject] | None` (optional)
- `valid_from: AwareDatetime | None` (`validFrom` on the wire) (optional)
- `valid_until: AwareDatetime | None` (`validUntil` on the wire) (optional)
- `observed_at: AwareDatetime | None` (`observedAt` on the wire) (optional)
