helpdesk
Helpdesk inbox: an anonymous browser client (GET /helpdesk/client.js) submits questions, contact requests, bug reports and wishes behind a honeypot, a minimum submit time and a single-use proof-of-work challenge; signed-in users file reports from the admin. Every request is stored platform-wide and every SystemAdmin is notified by mail, optionally also in a Telegram chat (option telegram, off by default); the notification names only the kind, the app and a link, never name, address, phone, subject or message, because mail and Telegram cannot be shredded. SystemAdmins reply by mail (Reply-To set, attachments, quoting the original) and mark requests done; a website sender gets a fixed acknowledgement, a signed-in reporter a copy and an in-app note. Personal data is crypto-shredding-ready and the EXT_USER_DATA hooks export and erase a user’s requests.
Quick example
Section titled “Quick example”From recipes-helpdesk — the smallest working mount:
// Helpdesk sample//// A public website form (question, contact request, problem report) that lands with the// SystemAdmins: mail, optional Telegram, a copy to the sender. Spam is handled without a// captcha: honeypot field, single-use proof-of-work challenge, minimum submit time, per-IP// and per-email rate limits. Rejected submits answer 200 with the normal body.//// The website embeds the anonymous client the feature serves itself. The client posts to the// relative paths /api/query and /api/write, so the page must share its origin with the app// (or forward /api to it on its own origin):// <script src="/helpdesk/client.js"></script>// const { kinds, phone } = await window.KumikoHelpdesk.load();// const result = await window.KumikoHelpdesk.submit({ kind, name, email, message, locale });// // result.kind: "sent" | "rate-limited" (retryAfterSeconds) | "failed"//// Prerequisites the app wires itself:// - `anonymousAccess` (defaultTenantId = SYSTEM_TENANT_ID) so the form needs no login// - delivery with a mail channel (channel-telegram only with `telegram: true`, off by default)// - config, user-data-rights and notes-history (required features)// - files with a file provider, because the entities carry file fields// - `kumiko schema generate` for the new tables
import { createHelpdeskFeature } from "@cosmicdrift/kumiko-bundled-features/helpdesk";
export const helpdeskFeature = createHelpdeskFeature({ appName: "Sample App", fields: { phone: "optional" }, // Lowered only to keep the sample test fast; the default (19 bits, 3 seconds) suits production. spamProtection: { proofOfWorkBits: 8, minSubmitSeconds: 0 },});📄 On GitHub: samples/recipes/helpdesk/src/feature.ts
Live preview
Section titled “Live preview”
How it fits
Section titled “How it fits”What this feature needs to run (Requires, top) and the write commands this feature provides (Provides, bottom).
flowchart TB
n_helpdesk["helpdesk"]
subgraph how_reqs["Requires / optional"]
n_config["config"]
n_delivery["delivery"]
n_user_data_rights["user-data-rights"]
n_files["files"]
n_notes_history["notes-history"]
n_channel_telegram["channel-telegram"]
end
subgraph how_provides["Provides"]
n_cmd_helpdesk_write_forward_request(["forward-request"])
n_cmd_helpdesk_write_mark_done(["mark-done"])
n_cmd_helpdesk_write_notify_reporter_in_app(["notify-reporter-in-app"])
n_cmd_helpdesk_write_reply(["reply"])
n_cmd_helpdesk_write_report(["report"])
n_cmd_helpdesk_write_send_reply_mail(["send-reply-mail"])
n_cmd_more(["+1 more"])
end
n_config --> n_helpdesk
n_delivery --> n_helpdesk
n_user_data_rights --> n_helpdesk
n_files --> n_helpdesk
n_notes_history --> n_helpdesk
n_channel_telegram -.->|optional| n_helpdesk
n_helpdesk --> n_cmd_helpdesk_write_forward_request
n_helpdesk --> n_cmd_helpdesk_write_mark_done
n_helpdesk --> n_cmd_helpdesk_write_notify_reporter_in_app
n_helpdesk --> n_cmd_helpdesk_write_reply
n_helpdesk --> n_cmd_helpdesk_write_report
n_helpdesk --> n_cmd_helpdesk_write_send_reply_mail
n_helpdesk --> n_cmd_more
Provides — write commands this feature registers (dispatch them through the command bus):
helpdesk:write:forward-requesthelpdesk:write:mark-donehelpdesk:write:notify-reporter-in-apphelpdesk:write:replyhelpdesk:write:reporthelpdesk:write:send-reply-mailhelpdesk:write:submit
Getting started
Section titled “Getting started”Start with recipes-helpdesk for a step-by-step walkthrough with runnable code and integration tests.
Dependencies
Section titled “Dependencies”- Requires:
config,delivery,user-data-rights,files,notes-history - Optional:
channel-telegram - Activation: always on (not toggleable)
Configuration
Section titled “Configuration”Per-tenant config keys, set via the tenant-admin UI or a seed. 🔒 = encrypted at rest.
| Key | Type | Default | Scope | Who can write | Who can read |
|---|---|---|---|---|---|
reply-to | text | "" | system | SystemAdmin | SystemAdmin |
Extensions & cross-feature APIs
Section titled “Extensions & cross-feature APIs”- Registers extension:
userData→helpdesk-request,userData→helpdesk-reply