Repository navigation
Description
Summary
Support agent-initiated, secure credential collection in the embeddable <dewee-chat> widget. When an agent needs an API key, token or client secret, display a native Credentials form or a secure Dewee-hosted form link. Never ask the visitor to paste a secret into chat.
Companion gateway issue: https://github.com/nextlevelbuilder/dewee/issues/931
This repository owns widget rendering, HTTP/SSE protocol and TS/PHP backend adapters. The Dewee gateway owns authorization, credential encryption/storage, request lifecycle, and credential_ref. Do not introduce a second secret vault.
Current architecture (codebase findings)
packages/dewee-webchat/src/widget/element.ts: Shadow DOM web component, floating/inline UI, SSE, conversation history.packages/dewee-webchat/src/protocol.ts: sharedChatStreamEvent/HistoryMessage; only generictool_callandtool_resultare supported today.packages/dewee-webchat/src/server/gateway-client.ts: gateway v3 WStool.call/tool.resultare forwarded as generic SSE and folded into history.packages/dewee-webchat/src/server/handler.ts: TypeScript backend (/config,/session,/chat,/history).php/dewee-webchat.php: independent PHP backend with the same protocol.docs/http-contract.md: contract shared by both backends and widget.- A signed webchat visitor token is not owner/admin authorization for modifying workspace-wide credentials.
Functional requirements
1. Safe agent-to-widget request
- Consume a server-authorized
secret_request/ credential-request event from Dewee #931. The payload contains metadata only: request ID, schema version, status, trusted target/destination, purpose, allowed field descriptors, expiry, and optionally a trusted secure-form URL. - Add typed contract to
protocol.ts. Map only validated gateway data, bound to the correct tenant, user, agent and conversation. Do not let the model supply arbitrary HTML, scripts, destination URLs or phishing fields. - Do not treat this as a normal tool result: prevent secret-related raw tool arguments/results from appearing in SSE, transcript/history, UI debug views or observability.
2. Native Credentials form in webchat
- Render a secure form/card in
<dewee-chat>for both floating and inline modes, supporting mobile, accessibility, light/dark themes and existingen/vilocalization. - Display trustworthy destination, intended access/scope, required/optional fields, masked secret inputs, explicit Save/Connect and Cancel, spinner, success, error, expired and rotate/replace confirmation states.
- Keep secret values only in the active form's volatile memory, clear on completion/cancel/expiry/unmount. Never persist them in localStorage/sessionStorage, chat messages, history, markdown, clipboard copy, custom widget events, error messages or analytics.
- Form submission must be a separate HTTPS request to an authorized first-party backend or verified Dewee-hosted form, never
send(text)/POST /chat/ model prompts.
3. Authorization boundary for public website visitors
Important: This widget accepts anonymous visitors. Their HMAC-signed visitor ID alone cannot authorize writing global workspace credentials (provider, MCP, channel, CLI, etc.).
- Feature is disabled by default unless the host/gateway provides explicit credential-request capabilities and a trusted identity/authorization integration.
- Support only server-verified Dewee user identity / account linking and actor-scoped destinations. Credential grants, writes and rotations must be authorized server-side on creation, display, submission and completion.
- User-scoped credentials may be supported only if the gateway enforces strict per-actor ownership and isolation. Never silently save a visitor's secret into tenant-global settings.
- If inline authorization cannot be proven in an embedded third-party site, render a first-party authenticated Dewee secure-form handoff URL. Do not collect secrets directly in the untrusted page.
- Keep operator gateway token exclusively on server. Existing playground-only
allowClientCredentialsis a separate feature and is not authorization for this flow.
4. Backend and gateway integration
- Extend
/api/dewee/*contract with secure request status and submit/cancel or hosted-form handoff, as supported by Dewee #931. - Enforce strict binding to tenant, actor, agent, conversation, credential target and request ID; user authorization, TTL, single-use/idempotency, anti-replay, CSRF/origin controls, allowed gateway host and destination, safe redirects, no-store, rate limits and redacted errors.
- Never expose gateway secret/token to browser. Never include entered values in SSE/WS frames, generic tool results, chat callbacks (
onChat), logs, metrics, error payloads or URLs. - Keep TypeScript handler and PHP backend fully equivalent. No insecure fallback on unsupported PHP deployments.
- Restore pending/resolved/cancelled/expired cards in history without restoring field contents. Avoid duplicate cards from event replay.
- On success, Dewee stores the secret encrypted and returns only sanitized status / scoped
credential_ref; notify/resume the originating agent session once.
Acceptance criteria
- Agent-triggered credential request renders secure form in floating and inline embedded webchat.
- Authorized users can submit credentials without those values entering chat/LLM context/session history.
- Unauthenticated visitor cannot create/rotate/write workspace-global credentials.
- When inline auth is unavailable, offer authenticated first-party Dewee form link with expiry, one-use, identity binding; forwarded/expired links fail closed.
- Correct agent/session gets only sanitized completion status /
credential_ref; no duplicate continuation. - Reload restores only request metadata/status, never secrets.
- TS and PHP backends implement equivalent status, submit and rejection behavior.
- Tests cover actor/tenant isolation, unauthorized visitor, wrong conversation, expired/replay/forwarded request, CSRF, forged tool event, field validation, cancellation, and multi-secret forms.
- Regression tests prove no secret in SSE, tool arguments/results, history, custom events, logs, analytics callbacks or browser storage.
- Update
docs/http-contract.md, package docs, PHP docs, examples, i18n and test suites.
Implementation sequence
- Agree on the safe credential-request schema and authorized submit/handoff APIs from dewee#931.
- Extend TS gateway adapter, HTTP contract and history redaction.
- Add native Shadow DOM card and trusted hosted-form fallback.
- Mirror PHP adapter; verify security tests and docs.
Out of scope: passwords or MFA recovery codes for Dewee accounts, arbitrary agent-generated forms, and any second credential store inside the widget.
Activity
mrgoonie commentedon Nov 8, 2026
The current Gateway tool and public ingress do not expose a verified, actor- and conversation-bound credential request event or authorized handoff to this widget. The required contract and runtime/CCP work are tracked in nextlevelbuilder/dewee#2233. The existing external-channel link path cannot be used to grant anonymous website visitors workspace credential authority. Implementation can resume when that contract is available.
mrgoonie commentedon Nov 8, 2026
Wire contract for credential requests, implemented in nextlevelbuilder/dewee#2233 (off by default, signed-in visitors only). The widget can build against this.
Negotiation
credential-requestsinX-Dewee-Webchat-Featuresonchat,historyand the routes below.credential_requests: boolean. Show nothing when it is false or the visitor is anonymous.SSE event
{"type":"credential_request","credential_request": view}. The raw tool frame is never forwarded; the view is rebuilt from the stored request.View (
schema_version: "webchat-credential-request.v1")expires_atreadsexpired.Public routes (
POST /api/public/webchat/v1/{integrationId}/…; same headers aschat){conversation_id, credential_request_id, identity_session, agent?}.credential-request→200 {credential_request: view}. Poll it while the hosted form is open.credential-request-handoff→200 {credential_request_id, url, expires_at},no-store.urlin a new tab and never persist it.credential-request-cancel→200 {credential_request: view}.Resume and history
chatwithcredential_request_idand an emptymessage, once the status is completed.409 credential_request_not_ready: still pending, keep polling.409 credential_request_resumed: already resumed, ignore.historyreturnscredential_requests[](oldest first). Restore cards from it; the composed resume turn is never inmessages.Errors (by
details.reason)403 credential_requests_unavailable: hide the card.404 credential_request_not_found: drop the card.429 rate_limited.The widget never collects the secret; the hosted form does, and it requires a signed-in workspace admin.
Refs nextlevelbuilder/dewee#2233
Generated by Claude Code
mrgoonie commentedon Nov 8, 2026
PRs #45 and #47 are merged on main: the widget now renders the value-free card, opens only the configured Dewee HTTPS form origin, supports status/cancel/resume and restores metadata without storing the token. Node/Workers and PHP implement the same CCP contract; legacy direct-Gateway streams/history suppress credential-tool payloads. The feature is off unless the host explicitly configures it and the visitor has verified identity.
The CCP
configcapability reflects its default agent. A signed-in integration may bind a different agent, so the adapters declare the host capability for the verified request and let the Gateway authorize the actual agent on every operation instead of rejecting it based on the default-agent flag. Gateway/CCP remain the authority.Validation: independent security review; Windows full suite 404 passed/5 skipped, typecheck/build/bundler passed; clean Linux focused suite 51 passed; both PR and post-merge CI passed. Surface parity: Node/Workers, PHP, widget and docs updated; Gateway and trace/CLI rationale in nextlevelbuilder/dewee#2240. Public docs follow-up: nextlevelbuilder/dewee-web-v2#133.
Keep this issue open for a deployed signed-in end-to-end journey, including completion, cancellation, replay/expiry and history recovery. The latest successful Gateway and CCP staging deployments predate the required Gateway commit; no deployed support is claimed yet.
mrgoonie commentedon Nov 8, 2026
Gateway and CCP staging deployments have now succeeded at
e8cb2a16, which includes the actor-bound credential-request handoff. The currently observed staging.agentkit.best webchat config reports backend version0.4.1and does not includecredentialFormOrigin; that integration has not been shown to run the beta.4 backend or to have the opt-in and verified identity required for this feature.A staging host running the new backend, explicit trusted form origin and verified signed-in identity is still needed for the hosted-form journey, cancellation, expiry/replay and history recovery checks. Keep this issue open until those checks are demonstrated.