Widget

Ticket Form

Current structured widget intake behavior and availability

The widget has chat, form, and hybrid modes. The form can collect an email, name, subject, message, and selected intake media behind the same in-memory widget session. The bundle is published (see Widget Installation Boundary); an installed-widget customer journey is not available yet.

Source configuration

The intended source initializer uses a public installation ID:

window.Keva.init({
  publicId: 'keva_widget_…',
  mode: 'form',
  primaryColor: '#3b82f6',
  intakeModes: {
    paste: true,
    voice: true,
    screenshot: true,
    recording: false,
  },
});

This is the shape the published bundle exposes. Install it with the snippet in Widget Installation Boundary; mode: 'form' is also settable with data-mode="form" on the script tag.

Intake behavior in source

  • Paste: sends pasted text to the authenticated extraction route. Provider availability and paid-work safeguards are not available yet.
  • Voice: uses the browser speech-recognition interface when the browser exposes it; unsupported browsers show no cloud fallback.
  • Screenshots and recordings: use presign, upload, confirmation, and same-session attachment IDs in structured-form mode locally. Storage, encryption metadata, processing, retention, and deletion are not available for customer use yet.
  • Submit: atomically creates the scoped ticket, first message, session binding, and durable acceptance row locally when the prospective schema is present.

Chat-mode file selection is different: current source sends file data to the message route, but the route stores only a textual attachment marker. It is not a durable attachment and should remain disabled or clearly treated as blocked until it uses the confirmed attachment path.

Idempotency and continuation

Form submission uses a browser-generated UUID idempotency key. Repeating the same key and payload can return the accepted result; changing the payload with the same key conflicts locally.

Sessions expire after 15 minutes. Renewal and continuation of a bound ticket are not implemented, so a long-running form or conversation can lose authority.

Rate-limit boundary

Active session minting, conversation and structured-ticket acceptance, and attachment-upload issuance use separate strict Redis boundaries at their documented route-specific cutoffs. Missing or unavailable Redis returns 503; an exhausted bucket returns 429 before that boundary's later effects. Widget extraction and transcription are suspended before route-level limiter, storage, or provider work, so retained historical limits are not active guarantees. The ticket-creation database email cap remains separate. Forwarded-source trust, configured Redis behavior, deployed enforcement, edge protection, and universal coverage are not available as customer-facing guarantees.

Security and retention boundary

Server source binds structured-form attachment registration and claiming to the same widget session. That does not prove object-store encryption, audit-provider delivery, PII segregation, retention deletion, legal hold, or recovery. Those claims still require provider and database checks after the ordered migrations and deployment.