Developer docs/Extension reference
Architecture / codebase map
Every crate and module of the Rust workspace with the summary from its //! doc, generated from source. Big crates group modules by domain folder (for example pelty-database/src/billing/, pelty-api/src/routes/finance/); old flat paths still work through pub use re-exports. A test fails when a module has no //! doc.
#pelty-api
HTTP layer: routing, extractors, error mapping. Business logic lives in service crates; SQL lives in pelty-database.
| Module | What it does |
|---|---|
access/captcha.rs | Captcha protection for public forms (WHMCS "Captcha Form Protection"). |
access/duo.rs | Duo Security two-factor (Duo Universal Prompt, OIDC auth-code flow). |
access/fraud.rs | Order fraud screening: built-in rules plus pluggable FraudHooks (e.g. a MaxMind or FraudLabs integration). Scores add up (capped at 100); the settings thresholds pick accept / review / reject. A hook that errors is logged and ignored (fail-open) so an outage never blocks sales. |
access/mod.rs | Access and security: OAuth login, the OIDC provider, SAML, Duo, captcha, security policy, security headers, trusted proxies and fraud checks. |
access/oauth.rs | Social / SSO login (OAuth 2.0 authorization code + PKCE, OpenID Connect). |
access/oidc_provider.rs | PeltyCMS as an OAuth 2.0 / OpenID Connect provider ("Sign in with Pelty"). |
access/saml.rs | SAML 2.0 Service Provider (addon sso-saml). |
access/security.rs | Admin security tools: configurable security policy (password rules, session lifetimes, login rate limit), IP ban list + admin IP allow-list (middleware), "Login as client / user" impersonation with audit and a return path, and client close / merge. |
access/security_headers.rs | Baseline security headers on every response. Handlers that already set a stricter value (e.g. file downloads with sandbox CSP) keep theirs. |
access/trusted_proxy.rs | Trusted proxies (WHMCS System > Trusted Proxies, plus PELTY_TRUSTED_PROXIES): when the TCP peer is a trusted proxy, the client address is taken from X-Forwarded-For (read right to left, skipping other trusted hops), else from X-Real-IP / CF-Connecting-IP. Every later layer (IP rules, rate limits, sessions, audit) then sees the real client in ConnectInfo, and X-Forwarded-Proto becomes a ClientScheme extension. From any other peer these headers are removed, so nothing downstream can be fooled. |
addon_host/addon_events.rs | Addon event lifecycle (ABI 0.3) and mixins. |
addon_host/addon_ext.rs | WASM addon extension points beyond the per-kind contracts: synchronous pre-action hooks, addon HTTP routes under /api/v1/addons/<id>/… and declarative admin/client UI. All of them go through the addon's call export (ABI 0.2): op hook, op http. See make docs. |
addon_host/addon_filters.rs | Value filters (capabilities.filters): the host passes a value through every subscribed addon in priority order (op filter, input {filter, value, context}, reply {value}). A reply is kept only when it has the same JSON schema as the value; money keys follow the money.modify rules. Filters always fail open. |
addon_host/addon_functions.rs | Core-function mixins: addons wrap a named host function (pelty_extensions::functions::FUNCTIONS) with a mixin whose target is fn <name>. Op mixin, input {function, at, phase: "before", context, input} → reply {input?, state?}, then {function, at, phase: "after", context, input, output, state} → reply {output?}. Replies keep the JSON schema and never change money values; mixins fail open and honour the per-addon kill switch. |
addon_host/addon_health.rs | Addon call isolation: every hook, mixin and filter call goes through guarded_call, which - gives the wasm store the listener's own deadline and fuel (the store is interrupted, not merely abandoned, when the budget runs out), - records per-addon statistics (calls, failures, timeouts, latency), and - trips a per-addon circuit breaker after PELTY_ADDON_BREAKER_FAILS (default 5) consecutive failures: the addon is skipped for PELTY_ADDON_BREAKER_COOLDOWN_SECS (default 60) and then retried. |
addon_host/addon_power.rs | Host side of the addon power interface: core reads with fixed column lists, typed audited writes, SQL limited to the addon's own tables, and background jobs. The runtime has already checked the capability; every function here re-checks its own scope (defence in depth). |
addon_host/addon_secrets.rs | Addon settings of kind secret (API secrets, OAuth client secrets) are sealed at rest with the app encryption key and never returned to the browser: reads get MASK, and saving MASK back keeps the old value. |
addon_host/addon_trust.rs | Operator trust is separate from package hashes and publisher-supplied metadata. |
addon_host/addon_upgrade.rs | Pre-extraction replacement policy. In-place upgrades never change schema or approvals. |
addon_host/addons.rs | Addon system: catalog (built-in + on-disk manifests), install / enable / disable / uninstall, schema-validated settings and the runtime gate that keeps uninstalled provisioning modules and gateways from running. See make docs. |
addon_host/mod.rs | Addon runtime host: loading WASM addons, their events, filters, functions, secrets, trust, health, upgrades and plugin hooks. |
addon_host/plugin_hooks.rs | Durable webhook delivery of domain events to external plugins. |
addon_host/wasm_addons.rs | Runtime side of WASM addons: compile the component of an installed and enabled addon and register it with the matching host registry (gateways, provisioning, registrars) or keep it for captcha / SSO lookups. Disabling or uninstalling unregisters it again. See make docs. |
comms/chat_bus.rs | Presence and durable-message invalidation hints. Transcript content stays in Postgres. |
comms/event_mail.rs | Customer emails driven by domain events (WHMCS "email on event"): welcome, order confirmation, payment receipt, refund, service lifecycle and ticket opened. Each send respects the operator's disabled list. |
comms/mail.rs | Rendering + queueing of transactional email. Requests only enqueue an email.send job; the worker renders and delivers it, so SMTP latency or outages never block a request and failures retry with backoff. |
comms/mailbox.rs | Mailbox fetchers for ticket piping: minimal POP3 (RFC 1939) and IMAP4rev1 (RFC 3501) clients plus a small RFC 5322/MIME reader. The clients run over any async stream, so tests drive them with an in-memory scripted server; production connects with TcpConnector (TLS via rustls + webpki roots). |
comms/mod.rs | Communication: outgoing mail, inbound mailbox/pipe, notifications, event mail, outgoing webhooks, the chat bus and support automation. |
comms/notify.rs | Staff notifications (Slack / Discord / Teams / Telegram / SMS gateway / email-to-SMS / HMAC-signed generic webhook) fanned out from domain events through the job queue, with a per-delivery log. The HTTP transport is a trait so tests can record deliveries instead of reaching the network. |
comms/pipe.rs | Shared inbound email intake for department mailboxes, signed webhooks and local MTA pipes. All transports use the same sender and upload policy. |
comms/support_ext.rs | Support automation: department auto-replies and mailbox piping runs. |
comms/webhooks_out.rs | Outgoing webhooks: every domain event is POSTed to each enabled webhook_endpoints row whose event filter matches (*, invoice.* or an exact name). |
error.rs | Error → HTTP. Handlers return ApiError; the localize_errors middleware turns the stable code into a translated JSON body with the request id. |
hosting/cluster.rs | Several instances behind one Redis (PELTY_REDIS_URL): change notifications and the live instance list. Without Redis every function here is a no-op and an instance only sees its own changes (as before). |
hosting/domains.rs | Domain lifecycle driven by the job queue: register/transfer paid orders, apply paid renewals, raise auto-renew invoices, expire lapsed domains and send expiry reminders. Registrar calls go through RegistrarModule. |
hosting/mod.rs | Hosting backends: provisioning, domains and registrant verification, SSL probing and the cluster coordinator. |
hosting/provision.rs | Provisioning job runner: loads the service + server, decrypts the panel key, runs the module action and records the outcome. Transient errors are retried by the queue; config errors and 4xx rejections go dead at once. |
hosting/registrant_verify.rs | ICANN WHOIS accuracy: after a registration, transfer or registrant e-mail change the registrant must confirm their address within 15 days. An address confirmed once is trusted for later domains. Reminders go out 10 and 5 days before the deadline; past it the request is overdue (the registrar suspends such names on its side; staff see it here). |
hosting/ssl_probe.rs | TLS certificate probe for client domains (WHMCS "SSL Sync"). Connects to port 443, verifies the chain against webpki roots and reads the leaf certificate's validity window and issuer. Private and loopback addresses are refused so a client domain cannot point the probe inward. |
lib.rs | HTTP layer: routing, extractors, error mapping. Business logic lives in service crates; SQL lives in pelty-database. |
money/autopay.rs | Daily billing.autopay job: charge due invoices off-session with the customer's default saved method, retry on the configured schedule and mail a dunning notice after each failed attempt. |
money/einvoice.rs | E-invoicing: UBL 2.1 export following Peppol BIS Billing 3.0 (EN 16931), optionally with the Romanian CIUS-RO customization used by RO e-Factura. |
money/exchange_rates.rs | Daily exchange-rate update: fetch the configured feed through the swappable HTTP transport, apply rates (+ markup) and optionally re-sync prices. Admin routes live in routes::currencies. |
money/mod.rs | Billing engine pieces outside HTTP: overdue processing, autopay, exchange rates, e-invoices, PDF rendering and VIES VAT checks. |
money/overdue.rs | Glue for the daily billing.overdue job: runs the DB automation, then mails reminders / suspension notices, queues panel actions and emits events. |
money/pdf.rs | Server-side invoice PDF (A4, embedded subset DejaVu Sans, full Unicode text incl. Romanian diacritics). Pure layout from an already-localized InvoiceDoc; no I/O. |
money/vies.rs | EU VAT number verification against VIES (REST API) through the swappable HTTP transport. The result is stored on the customer and, when the tax setting require_vies is on, gates the reverse charge. |
platform/approval.rs | Order auto-approval (rules evaluated on order.created / invoice.paid), shared order activation, and the daily pre-due invoice reminders. |
platform/backup.rs | Database backups via pg_dump -Fc, run as a background job. Files live in PELTY_BACKUP_DIR (default ./backups); names are generated server-side. |
platform/changes.rs | Glue between payments / the scheduler and plan changes & cancellations. |
platform/cron.rs | Cron expressions for scheduled tasks (built-in and <addon>:<op>). |
platform/csv.rs | Minimal RFC 4180 CSV writer with spreadsheet formula-injection guard. |
platform/dev_docs.rs | Serves the generated docs (make docs → target/docs) at /docs: the user docs at /docs/, the developer docs at /docs/developers/. Staff only unless PELTY_DOCS_PUBLIC is true. |
platform/extract.rs | Session authentication, CSRF and permission extractors. |
platform/mod.rs | Platform services: the background worker and cron, backups, updates, change log, approvals, CSV/extract helpers, developer docs, the WHMCS-compatible API, translations and static files. |
platform/static_files.rs | Static file serving for frontend bundles and theme assets. |
platform/translations.rs | Translation editor (WHMCS "Translation editor"): staff override any shipped string per language; overrides win over locales/*.json in the UI (/i18n/{lang}) and in server-rendered text (mails, errors). |
platform/updates.rs | Update checker ("automatic updates", WHMCS system/updates). |
platform/whmcs_api.rs | WHMCS-compatible API (POST /includes/api.php, also /api/v1/compat/whmcs), see make docs. |
platform/worker.rs | Background job worker over the Postgres queue. Multiple server instances can run it concurrently (SKIP LOCKED); the daily recurring-billing job is deduplicated by its idempotency key. |
routes/clients/account.rs | Password reset and email verification. Every public endpoint here is rate-limited (AuthGuard) and never reveals whether an account exists. |
routes/clients/affiliate_extras.rs | Affiliate extras: per-product rates, tiers, promotional materials. |
routes/clients/affiliates.rs | Affiliate program: public referral link (sets a tracking cookie), client dashboard + payout requests, admin management (affiliates.manage). |
routes/clients/avatars.rs | Profile pictures. Uploads are sniffed by magic bytes (PNG/JPEG/WebP only, must match the declared Content-Type), decoded with dimension and memory limits, centre-cropped and re-encoded to PNG, so no original bytes (metadata, appended payloads, polyglots) are ever stored or served. |
routes/clients/banned_emails.rs | Admin CRUD for banned e-mail domains (checked at registration). |
routes/clients/client_extras.rs | Client notes and custom client field values (customers.manage), field definitions (customers.manage), the client's own editable fields, and the admin to-do list (todos.manage). |
routes/clients/client_group_rules.rs | Automatic client-group assignment rules (client_groups.manage). |
routes/clients/client_groups.rs | Admin client groups (client_groups.manage). |
routes/clients/customer_workspace.rs | Unified customer workspace reads; section permissions use scoped CurrentUser permissions. |
routes/clients/customers.rs | Customer profiles. /client/* is always scoped to the caller's own customer record; /admin/customers* requires customers.manage. |
routes/clients/fraud.rs | Admin fraud screening: settings, results and the manual review queue. |
routes/clients/gdpr.rs | GDPR: self-service data export and erasure requests; admin review. /account/* is session-only (API keys are refused by the extractor). |
routes/clients/kyc.rs | KYC endpoints: customers upload identity documents (images/PDF, sniffed by magic bytes), staff review them; ordering can be gated on the result. |
routes/clients/mod.rs | Client HTTP routes: customers, workspaces, groups, client extras, KYC, GDPR, fraud, banned emails, affiliates, avatars and the client account. |
routes/commerce/bundles.rs | Bundles and upsell / cross-sell: public catalog reads, admin management (catalog.manage), and the order-time bundle check. |
routes/commerce/catalog.rs | Catalog: public listing and admin management (catalog.manage). |
routes/commerce/data_feeds.rs | Data feeds (WHMCS feeds/productsinfo.php, domainprice.php): tiny public JavaScript snippets that print a product's name, description or price on an external site via <script src=...>. |
routes/commerce/mod.rs | Commerce HTTP routes: catalog, bundles, order forms, the public store and data feeds. |
routes/commerce/order_forms.rs | Order form templates (admin CRUD, per-group template) and product free-domain rules; the public form lookup for the client order page. |
routes/commerce/store.rs | Public storefront (no login): carts with a live price/tax preview, storefront checkout for a signed-in customer, the client order status page, the client home widgets, contacts / sub-accounts, email preferences, login history and the cart-recovery email job. |
routes/config/automation.rs | Automation (cron) dashboard: the built-in scheduled tasks, their last outcome and next run, plus a manual "run now" (jobs.manage). |
routes/config/general_settings.rs | General Settings (WHMCS Setup → General Settings) and admin-only custom code. |
routes/config/i18n.rs | Translation HTTP routes: serve UI string bundles per locale to the frontend. |
routes/config/mod.rs | Settings HTTP routes: settings, general settings, automation, site/branding, i18n and the setup wizard. |
routes/config/settings.rs | Admin-editable system settings (non-secret). |
routes/config/setup_wizard.rs | First-run setup wizard / getting-started checklist. |
routes/config/site.rs | Public website configuration (brand, menus, footer, homepage) and CMS pages made of declarative blocks rendered natively by the frontend. |
routes/extensibility/extensions.rs | Themes, plugins and gateway administration. |
routes/extensibility/headless.rs | Headless commerce API: the whole purchase flow (catalog → cart → checkout → payment → status) for custom storefronts, mobile apps and integrations. Authenticated with a customer API key (Authorization: Bearer pelty_…); interactive sessions are refused so the flow is never CSRF-exposed and the checkout captcha (meant for browsers) does not apply. Prices are always computed server-side. |
routes/extensibility/mod.rs | Extension HTTP routes: plugins, extensions, vendor data and the headless API. |
routes/extensibility/plugins.rs | Plugin extension points over HTTP: - GET /plugins/ui UI slot entries for the current user - GET /admin/plugins/{id}/settings schema + current values - PUT /admin/plugins/{id}/settings validated against the schema - /plugins/{id}/... routes of built-in modules, only reachable while the plugin is enabled (see modules). |
routes/extensibility/vendor.rs | Vendor marketplace (MarketConnect-style resale): sync a vendor server's catalog through its provisioning module, import items as products with a markup, and re-price them. Ordering/provisioning use the normal flow. |
routes/finance/billable.rs | Billable items, one-off draft invoice lines, and the per-product "generate invoice N days before due" setting. |
routes/finance/billing.rs | Orders, invoices, services and jobs. Every /client/* handler resolves the caller's customer from the session and filters by it in SQL, so a customer can never read another customer's records (404, not 403, to avoid leaking existence). |
routes/finance/coupons.rs | Coupons: admin management (coupons.manage) and a client-side code check. |
routes/finance/credit.rs | Customer credit balance: client view + apply to invoice, staff adjust. |
routes/finance/currencies.rs | Currency administration (settings.manage): exchange rates, default currency, and price recalculation from the default currency. |
routes/finance/einvoice.rs | E-invoicing: UBL 2.1 / Peppol BIS 3.0 (optionally CIUS-RO for RO e-Factura) download for issued invoices, credit notes and debit notes, plus the legal-field settings. See crate::einvoice for the builder. |
routes/finance/gateways.rs | Payment gateway administration (enable/disable, settings rendered from each gateway's schema, custom HTTP gateways, test-webhook tool, delivery log) and the client-side gateway picker / return-time completion. |
routes/finance/invoice_ops.rs | Invoice merge / split / duplicate / notes (staff), client mass-pay merge, and gift cards (staff issue, client redeem). |
routes/finance/invoice_pdf.rs | Branded invoice PDF download (client: own invoices; staff: any) and the branding settings. |
routes/finance/legal_entities.rs | Legal entities (selling companies): numbering, terms, bank details. |
routes/finance/mod.rs | Billing HTTP routes: invoices (admin, client, PDF, e-invoice), quotes, payments, gateways, credit, coupons, tax, currencies, refunds, renewals, overdue rules and usage billing. |
routes/finance/overdue.rs | Admin overdue automation settings and a manual run. |
routes/finance/payment_methods.rs | Saved payment methods, the auto-pay toggle and auto-pay settings. |
routes/finance/quote_pdf.rs | Quote PDF download (client: own sent/decided quotes; staff: any), rendered with the same branded layout as invoices. |
routes/finance/quotes.rs | Quotes / proposals: admin drafts and sends (quotes.manage); the customer views, accepts (→ finalized invoice) or declines. |
routes/finance/refunds.rs | Refunds against payments (partial or full) through the payment gateway, and the credit notes they produce. |
routes/finance/renewals.rs | On-demand renewals (WHMCS Billing > On-Demand Renewals): a client or staff member invoices the next period of a service ahead of the cron. |
routes/finance/tax.rs | Admin tax configuration: global settings and rules per country/region. |
routes/finance/usage.rs | Metered billing: metric catalog (catalog.manage), usage ingestion and period history (services.manage, API keys work too), client view. |
routes/health.rs | Health check routes (/health, readiness) mounted at the root without the API prefix. |
routes/helpdesk/content.rs | Knowledge base and announcements: public reads (published only) and the staff editor (content.manage). Bodies are plain text / Markdown; the frontend renders them as text, never as raw HTML. |
routes/helpdesk/downloads.rs | Downloads area: staff upload (downloads.manage, raw body, ≤ 25 MiB, allow-listed types by magic bytes); customers download what their active services entitle them to. Files are always served as attachments. |
routes/helpdesk/live_chat.rs | Live chat: public widget endpoints (bearer token per session) and the staff inbox. Both sides poll ?after=<last id>. |
routes/helpdesk/live_chat_admin.rs | Staff side of live chat: list, claim and answer chats. Child of live_chat. |
routes/helpdesk/live_chat_ws.rs | WebSockets accept secrets only in the first frame, never a URL or protocol. Durable writes remain REST operations with the existing CSRF protections. |
routes/helpdesk/mod.rs | Support HTTP routes: tickets (statuses, SLA, macros, attachments, AI), live chat, network status, downloads, knowledge content and projects. |
routes/helpdesk/network_status.rs | Network / service status issues: public status page and staff editor (status.manage). Every status change is recorded as a timeline update. |
routes/helpdesk/projects.rs | Project management (WHMCS Project Management addon). |
routes/helpdesk/support.rs | Support desk extras (tickets.manage): canned replies, tags, merge/split, escalation rules, SLA metrics, staff list; client ratings. |
routes/helpdesk/support_ext.rs | Support extensions: department piping/auto-reply settings, spam rules, ticket time tracking, KB tags, announcements RSS and the contact form. |
routes/helpdesk/ticket_ai.rs | Opt-in, staff-requested drafts. No message, mail or job is ever created here. |
routes/helpdesk/ticket_attachments.rs | Ticket attachment upload/download. Type is decided by magic bytes (never by the client's name or Content-Type alone); the declared type must agree with the sniffed one. Files are only ever served as downloads with nosniff and a sandbox CSP. |
routes/helpdesk/ticket_macros.rs | Ticket macros: manage them, list the ones offered on a ticket (with the reply already filled in), and apply one. |
routes/helpdesk/ticket_sla.rs | Ticket SLA policies (department × priority), live SLA state, the at-risk list and the warning / breach scan. |
routes/helpdesk/ticket_statuses.rs | Custom ticket statuses: everyone signed in can read them (for labels), staff with tickets.manage manage them. |
routes/helpdesk/tickets.rs | Support tickets: client area (own tickets only, no internal notes) and staff desk (tickets.manage). |
routes/hosting/mod.rs | Hosting HTTP routes: provisioning, server modules, service upgrades/downgrades and SSL. |
routes/hosting/modules_ext.rs | Module extras: server health, admin custom module buttons, the client module panel, the module log, the failed-provisioning queue and the public licensing verify endpoint. |
routes/hosting/provisioning.rs | Provisioning admin API: modules, panel servers (keys write-only), product module binding and per-service module actions / status. |
routes/hosting/service_changes.rs | Upgrade/downgrade and cancellation requests (client + admin). |
routes/hosting/ssl.rs | SSL certificate status for client domains: admin overview, on-demand recheck, and the client's own view. |
routes/identity/admin_security.rs | Admin account security: step-up re-authentication ("sudo mode") and an authenticated password change (needed once a password has expired). The enforcement itself lives in RequirePermission (see extract.rs). |
routes/identity/api_keys.rs | Personal API keys. Creating, listing and revoking keys requires an interactive session (keys cannot manage keys). The secret is shown once. |
routes/identity/auth.rs | Login, logout, register and session routes for clients and staff. |
routes/identity/mfa.rs | TOTP two-factor authentication: enrolment, login challenge, backup codes. |
routes/identity/mod.rs | Identity HTTP routes: login/register, MFA, passkeys, SSO, API keys, staff and security questions. |
routes/identity/passkeys.rs | Passkeys (WebAuthn, webauthn-rs): enrolment, passwordless login and step-up re-auth. Recovery when a passkey is lost is the normal password (+ TOTP / backup code) login; staff can revoke a user's passkeys. |
routes/identity/security_questions.rs | Security questions: staff manage the list, users pick one and store a hashed answer, staff verify a caller against it (answer never shown). |
routes/identity/sso.rs | Client SSO into the provisioned panel via a signed one-time token. POST /client/services/{id}/sso returns the redirect URL; POST /sso/consume lets the panel burn the token exactly once. |
routes/identity/staff.rs | Staff roles/permissions editor, staff list with role assignment and the staff 2FA policy (users.manage). |
routes/messaging/campaigns.rs | Mass mail campaigns (campaigns.manage), the client's marketing opt-out and the public, scanner-safe unsubscribe endpoint. |
routes/messaging/email_log.rs | WHMCS "Email Message Log" (staff, all mail with body and resend) and the client area "Email History" (own mail only). |
routes/messaging/email_templates.rs | Admin editing of email templates. Overrides are stored per (template, locale); deleting one reverts to the locale-file default. |
routes/messaging/link_tracking.rs | Link tracking (WHMCS Products > Link Tracking): admin CRUD + public redirect. |
routes/messaging/mod.rs | Messaging HTTP routes: email templates and log, SMTP, campaigns, link tracking, webhook endpoints and inbound webhooks. |
routes/messaging/smtp.rs | Admin SMTP settings. Stored in system_settings under mail.smtp; the password is sealed with the app SecretBox (AES-256-GCM) and never returned. When enabled these settings replace PELTY_SMTP_URL. |
routes/messaging/webhook_endpoints.rs | Admin: outgoing webhook endpoints, their delivery log and redelivery (webhooks.manage). See crate::webhooks_out for the delivery rules. |
routes/messaging/webhooks.rs | Inbound payment webhooks: verify → dedupe → apply → mark processed. |
routes/mod.rs | HTTP API router. Route modules are grouped by domain (finance, commerce, hosting, registry, clients, identity, helpdesk, messaging, extensibility, config, ops) and re-exported here so crate::routes::<module> keeps working. api_router merges every domain router. Covered by the integration suite and the pelty-docs route inventory tests. |
routes/openapi.rs | OpenAPI document (utoipa) listing documented handlers; served at /api/openapi.json. |
routes/ops/admin.rs | Admin dashboard routes: overview stats and admin landing data. |
routes/ops/admin_ops.rs | Admin ops: dashboard prefs + quick links, login history, staff online, calendar, per-client email log with resend, DB backups. |
routes/ops/admin_tools.rs | Admin productivity: global search (command palette), System Health, personal "My Notes" and staff notification rules (Slack/Discord/Teams/webhook). |
routes/ops/bulk.rs | Bulk invoice actions, client mass-pay (from account credit), pre-due reminder settings, and the order approval queue + rules. |
routes/ops/csv_import.rs | CSV import (clients, services, invoices): analyze → map columns → dry-run → import. |
routes/ops/exports.rs | Tax report (JSON or CSV) and invoice / payment CSV exports. |
routes/ops/mass.rs | Admin list mass actions (WHMCS "With selected…") for clients, services, tickets and domains. Invoices and orders use bulk.rs. Each id is handled on its own and reported back, so one bad row never blocks the rest. |
routes/ops/mod.rs | Admin operations HTTP routes: dashboard/admin, admin tools, reports, exports, CSV import, bulk and mass actions. |
routes/ops/reports.rs | Admin financial reports: revenue, refunds, MRR and churn by month. |
routes/registry/domain_pricing.rs | Registrar TLD price sync + margin rules, premium-name settings and per-TLD additional order fields. |
routes/registry/domains.rs | Domains: client search/order/manage, admin TLD pricing and domain admin (services.manage). Registrar work runs in the domains.* jobs. |
routes/registry/mod.rs | Domain HTTP routes: domain registration/management and TLD pricing. |
shared.rs | Optional Redis (PELTY_REDIS_URL) shared by every instance: rate-limit counters and the scheduler leader lock. Without it (or while it is unreachable) everything stays local: in-memory limits, and every instance with PELTY_SCHEDULER=true schedules (jobs are deduplicated in Postgres). Cross-instance invalidation and the instance list live in crate::cluster. |
#pelty-auth
Authentication: Argon2id passwords, session tokens, rate limiting.
| Module | What it does |
|---|---|
crypto.rs | Application-level encryption for small secrets at rest (TOTP seeds). AES-256-GCM with a random 96-bit nonce; key from PELTY_ENCRYPTION_KEY (base64, 32 bytes). There is no built-in default key. |
lib.rs | Authentication: Argon2id passwords, session tokens, rate limiting. |
password.rs | Argon2 password hashing and verification. |
policy.rs | Admin-configurable security policy (security.policy system setting): password rules, session lifetimes and the login rate limit. Read through a short in-process cache; invalidate after an update. |
rate_limit.rs | In-memory fixed-window rate limiter (per key, e.g. IP). Single-node only. |
service.rs | Business logic for register/login/logout. HTTP-agnostic. |
token.rs | Random tokens and their SHA-256 hashes for sessions and links. |
totp.rs | RFC 6238 TOTP (SHA-1, 6 digits, 30 s) plus backup codes. |
#pelty-billing
Pure billing domain logic: billing cycles, invoice math, service lifecycle. No I/O here so every rule is unit-testable; SQL lives in pelty-database.
| Module | What it does |
|---|---|
cycle.rs | Billing cycles (monthly, annually, ...) and date arithmetic for renewals. |
lib.rs | Pure billing domain logic: billing cycles, invoice math, service lifecycle. No I/O here so every rule is unit-testable; SQL lives in pelty-database. |
lifecycle.rs | Service lifecycle state machine. Mirrored by the services_lifecycle_guard trigger so illegal transitions fail even if app code is bypassed. |
math.rs | Exact invoice math with rust_decimal. Rounding: half away from zero (commercial rounding) to the currency exponent, per line, then summed, //! so the printed lines always add up to the printed total. |
proration.rs | Day-based proration for mid-period plan changes. Exact decimals only. |
tax.rs | Tax engine: rules per country/region, inclusive or exclusive prices, compound taxes and EU VAT reverse charge. Exact decimal; every tax amount is rounded to the currency exponent per line, so lines always add up. |
vat_format.rs | Offline VAT number format validation (EU + UK), run before VIES. Checksums are verified for RO, DE, GB, IT, BE, NL, PL, ES-free formats get only a length/charset check. This does NOT prove the number is registered; VIES remains the authority. |
#pelty-cli
pelty-cli, developer tooling for PeltyCMS addons.
| Module | What it does |
|---|---|
main.rs | pelty-cli, developer tooling for PeltyCMS addons. |
wasm_scaffold.rs | pelty-cli addon wasm-scaffold: a WASM addon skeleton (Rust tested; C and TinyGo are templates only, not built in CI). |
#pelty-core
Core domain primitives shared by all PeltyCMS crates.
| Module | What it does |
|---|---|
config.rs | Environment-based configuration, validated at startup. |
error.rs | Typed application errors. Every error has a stable message code that is translated via locale files; internal details are logged, never returned. |
i18n.rs | Translations from flat JSON locale files (locales/<lang>.json). en is the base; missing keys fall back to en, then to the key itself. |
lib.rs | Core domain primitives shared by all PeltyCMS crates. |
money.rs | Exact money type. Never use floats for money. |
#pelty-database
PostgreSQL pool, migrations and repositories. All SQL lives here.
| Module | What it does |
|---|---|
auth/api_keys.rs | Personal API keys (hashed, scoped, revocable, optional expiry). |
auth/mfa.rs | Storage for TOTP 2FA: sealed secrets, hashed backup codes, login challenges. |
auth/mod.rs | Identity repositories: users, staff, sessions, MFA, passkeys, API keys, OAuth, SAML/SSO and security settings. |
auth/oauth_provider.rs | Storage for PeltyCMS acting as an OAuth 2.0 / OIDC provider. Codes and tokens are passed in already hashed; nothing here sees a raw secret. |
auth/passkeys.rs | Passkey storage and single-use WebAuthn ceremony state. The crypto lives in pelty-api (webauthn-rs); this module stores opaque JSON. |
auth/saml.rs | SAML 2.0 SP storage (migration 0289): IdPs, pending requests, replay cache and IdP-session links for single logout. |
auth/security.rs | Security / accounts suite storage (migration 0240): captcha nonces, OAuth states + linked identities, IP rules, impersonation sessions, WHMCS-compatible API credentials, versioned ToS, client close/merge. |
auth/security_questions.rs | Security questions (WHMCS Clients > Security Questions). Answers are stored as password hashes of a normalised form and never returned. |
auth/sessions.rs | Session repository: create, look up and revoke login sessions. |
auth/sso.rs | One-time SSO nonces (see pelty_provisioning::sso). |
auth/staff.rs | Staff roles/permissions editor, role assignment and the staff 2FA policy. |
auth/user_tokens.rs | One-time user tokens (password reset, email verification). Only the SHA-256 of the token is stored; consuming is atomic and single-use. |
auth/users.rs | User repository: accounts for clients and staff. |
billing/add_funds.rs | Add funds: a client-requested invoice whose payment is credited to the account balance (see migration 0272 trigger). Limits live in settings. |
billing/autopay.rs | Saved payment methods and auto-charge of due invoices. Attempts are unique per (invoice, attempt index), so a run is idempotent and two workers can never charge the same attempt twice. |
billing/billable.rs | Billable items: one-off charges (held, added to the client's next renewal invoice, or invoiced immediately) and recurring charges invoiced by the daily billing job. |
billing/card_expiry.rs | Saved-card expiry notices (WHMCS --CreditCardExpiryNotices). |
billing/coupons.rs | Coupons / promo codes: percent or fixed (per eligible item), first invoice only or recurring, global and per-customer limits, validity window and product restrictions. Redemption happens inside the order transaction with the coupon row locked, so limits hold under concurrency. |
billing/credit.rs | Customer credit: an append-only ledger per currency. Staff adjust it; credit is spent by applying it to an unpaid invoice, which records a credit gateway payment through the normal (exactly-once) payment path. |
billing/currencies.rs | Currency administration: exchange rates against the default currency, and converting base-currency product prices into other currencies. |
billing/exchange_rates.rs | Automatic exchange-rate updates: feed parsing (ECB XML or a JSON {"base": "EUR", "rates": {...}} document) and applying the rates, with an optional markup, relative to the default currency. Fetching lives in the API crate behind the mockable HTTP transport. |
billing/gateway_admin.rs | Gateway administration: config upserts, custom gateways, webhook delivery log, payment lookups for return-time completion. |
billing/gateway_rules.rs | Per-gateway fees, min/max amounts and currency restrictions. All money is Decimal; limits and fixed fees are per currency (no FX conversion). |
billing/gift_cards.rs | Gift cards / prepaid credit codes. Codes are shown once at creation and stored as SHA-256; redeeming moves the full balance to account credit. |
billing/invoice_ops.rs | Invoice operations that WHMCS staff use daily: merge, split, duplicate, notes. Finalized invoices are immutable, so merge/split create new finalized invoices holding *copies* of the lines (copied_from) and void the sources (merged_into / split_from keep the trail). Copies do not re-claim a service period, so renewals stay idempotent. |
billing/invoice_tools.rs | Bulk invoice helpers and pre-due invoice reminder settings/run. |
billing/invoices.rs | Invoices, items, finalization (gapless numbering), credit notes and idempotent payment application. Finalized invoices are immutable; the DB triggers in 0004 enforce it even if this code had a bug. |
billing/invoices_service.rs | InvoiceService: Invoice reads and pool-level invoice actions (void, credit/debit notes, payments). |
billing/legal_entities.rs | Legal entities (selling companies) with per-year invoice numbering. |
billing/mod.rs | Billing repositories: invoices, payments, credit, coupons, tax, currencies and gateways. |
billing/overdue.rs | Overdue invoice automation: reminders, a late fee as a separate invoice, suspension of linked services, and unsuspension once paid. Every action is recorded in overdue_actions (unique per invoice + action), so a run is idempotent and safe to repeat. |
billing/quotes.rs | Quotes / proposals: draft → sent → accepted (becomes a finalized invoice) or declined. Line math reuses the invoice rounding rules. |
billing/refunds.rs | Refunds against payments. Two phases so a gateway call never runs inside a DB transaction: reserve locks the payment and records a pending refund (capacity is checked under the lock, so concurrent refunds can never exceed the payment), then complete / fail settle it. |
billing/tax.rs | Tax rules, tax settings and applying the tax engine to a draft invoice right before it is finalized. The result (rates, breakdown, customer snapshot) is frozen with the invoice by the triggers in 0096. |
billing/transactions.rs | Admin transactions list (all gateway payments) with filters and totals. |
billing/usage.rs | Metered (usage) billing. Records land in the service's open period; when the period ends (the service's billing cycle) it is invoiced once: per metric max(0, sum - included) × unit_price, rounded to the currency. |
clients/affiliate_extras.rs | Affiliate extras: per-product commission rates, referral-count tiers and promotional materials. Accrual itself stays in the affiliate_accrue trigger. |
clients/affiliates.rs | Affiliates: referral codes, signup attribution, commissions (accrued by a DB trigger when a referred customer's invoice is paid) and payouts. |
clients/avatars.rs | Profile pictures (already validated and re-encoded by the API layer). |
clients/banned_emails.rs | Banned e-mail domains (WHMCS "Banned Emails"). |
clients/client_extras.rs | Staff notes on clients, custom client fields (with per-client values) and the admin to-do list. |
clients/client_group_rules.rs | Automatic client-group assignment rules (first match by priority wins). |
clients/client_groups.rs | Client groups. A customer belongs to at most one group. |
clients/customer_workspace.rs | Permission-filtered, allowlisted customer workspace projections. |
clients/customers.rs | Customers: billing profile owned by a user account (or staff-created). |
clients/customers_service.rs | ClientService: Client (customer) records and their contacts. |
clients/fraud.rs | Fraud screening settings, rule inputs and stored results. |
clients/gdpr.rs | GDPR data export and erasure. |
clients/inactive_clients.rs | Retention-based erasure of inactive clients (WHMCS Data Retention "delete inactive clients"). Clients are anonymised with the same routine as a GDPR erasure (invoices stay for tax law), never hard deleted. Safeguards: off by default, at least 365 days, never staff, never anyone with live services/domains, unpaid invoices, open tickets or a pending GDPR request, at most max_per_run per run, and every erasure leaves a completed GDPR request as the audit trail. |
clients/kyc.rs | Know-your-customer: document uploads, staff review and the derived customer status used to gate ordering (configurable, off by default). |
clients/mod.rs | Client repositories: customers, workspaces, groups, KYC, GDPR, fraud checks and affiliates. |
commerce/bundles.rs | Bundles and upsell / cross-sell recommendations. |
commerce/catalog.rs | Product catalog: groups, products, per-cycle/currency prices, config options. Listing is done in a fixed number of queries (no N+1). |
commerce/mod.rs | Commerce repositories: products, bundles, order forms, the public storefront and orders (placing and approval). |
commerce/order_approval.rs | Order approval rules and the pending-order approval queue. |
commerce/order_forms.rs | Order form templates (WHMCS "order form templates"): which products or groups a form sells, its step layout, extra fields and the post-order redirect. Groups can pin a form; the client order page renders it. |
commerce/orders.rs | Orders: cart validation → order + finalized invoice in one transaction; approval creates services in one transaction. |
commerce/orders_service.rs | OrderService: Orders: placing, listing and changing order state. |
commerce/storefront.rs | Public storefront: persisted carts with a read-only price/tax preview, abandoned-cart lookup, customer contacts (sub-accounts), email preferences, login history and admin order notes. |
config/automation_settings.rs | Per-task automation settings: enable flag, legacy start hour and an optional cron expression (company time zone). |
config/branding.rs | Invoice branding shown on PDF invoices. |
config/content.rs | Knowledge base and announcements. Public reads only ever return published rows; locale NULL matches every language. |
config/general_settings.rs | WHMCS "General Settings": general, system URLs, maintenance mode, localisation, ordering (security lives with auth settings, social links with the website footer), plus admin-only custom CSS/JS. Stored as JSON in settings; every section has serde defaults so older rows keep loading after new fields are added. |
config/mod.rs | Settings repositories: key/value settings, typed general settings, automation, branding, site content, translations and the setup wizard. |
config/settings.rs | Key/value settings repository used by every typed settings module. |
config/setup_wizard.rs | First-run setup wizard (WHMCS Setup Wizard / "Getting started"): a checklist computed from live configuration, plus a dismiss flag. |
config/site.rs | Public website CMS pages. |
config/translations.rs | Translation editor overrides. |
extensibility/addon_kv.rs | Storage for the WASM addon key/value host functions. |
extensibility/addon_registry.rs | Installed-addon registry (see make docs). |
extensibility/addons.rs | Product addons and custom order fields. |
extensibility/extensions.rs | Plugin state, gateway config, webhook dedup, payments. |
extensibility/mod.rs | Extension repositories: installed addons, addon key/value storage, the addon registry and vendor data. |
extensibility/vendor.rs | MarketConnect-style vendor resale: a vendor server's catalog is synced here, staff import items as normal products (module + server + price = cost + markup), and orders run through the normal provisioning lifecycle. |
helpdesk/downloads.rs | Downloads area. Bytes live in the database; access requires an active service of a linked product (or no linked products at all). |
helpdesk/live_chat.rs | Live chat sessions and messages (polling; ids are monotonic so clients fetch after the last id they have). |
helpdesk/live_chat_ext.rs | Settings, assignment and atomic transcript conversion for live chat. |
helpdesk/mod.rs | Support repositories: tickets and their statuses/SLA/macros/attachments, live chat, satisfaction, network status, announcements, downloads and projects. |
helpdesk/network_status.rs | Network / service status issues and their timeline updates. |
helpdesk/noticeboard.rs | Staff noticeboard: notices visible to every staff member. |
helpdesk/projects.rs | Project management: projects for a client with tasks, time tracking and links to tickets and invoices; billable time is invoiced as lines. |
helpdesk/satisfaction.rs | Support satisfaction (CSAT) report from ticket ratings. |
helpdesk/support.rs | Support desk extras on top of tickets: canned replies, tags, client ratings, merge/split, escalation rules, SLA metrics and e-mail piping log. |
helpdesk/support_ext.rs | Support extensions: department auto-reply + mailbox settings, spam rules, time tracking, KB tags and contact form messages. |
helpdesk/ticket_attachments.rs | Ticket attachments: pending uploads are owned by the uploader and linked to a message atomically inside the reply transaction. |
helpdesk/ticket_macros.rs | Ticket macros: a canned reply or note plus status, priority, assignee, department and tag changes applied in one step. |
helpdesk/ticket_sla.rs | Ticket SLA policies (per department and priority), live SLA state, and the warning / breach scan with escalation. |
helpdesk/ticket_statuses.rs | Admin-defined ticket statuses (built-ins are seeded by the migration). |
helpdesk/tickets.rs | Support tickets. Client queries always filter by customer_id in SQL; internal notes are only returned when include_internal is set (staff). |
helpdesk/tickets_service.rs | TicketService: Tickets, their messages and support departments. |
hosting/mod.rs | Service repositories: active services, upgrades/downgrades, provisioning state, server import and SSL checks. |
hosting/module_ext.rs | Server health, module log, the failed-provisioning queue and licensing lookups. |
hosting/provisioning.rs | Provisioning persistence: panel servers (API keys sealed at rest), the per-service remote state, and enqueueing module actions as durable jobs. |
hosting/server_import.rs | Import accounts that already exist on a provisioning server as services (WHMCS "Server Sync / Import"). Accounts come from the module's list_accounts; this module only validates and writes. |
hosting/service_changes.rs | Plan changes (upgrade / downgrade) and cancellation requests. |
hosting/services.rs | Services (provisioned products) with lifecycle and renewal billing. |
hosting/services_service.rs | HostingService: Active customer services (hosting accounts, products) and their state. |
hosting/ssl_checks.rs | Stored results of TLS certificate probes for client domains. |
lib.rs | PostgreSQL pool, migrations and repositories. All SQL lives here. |
messaging/campaigns.rs | Mass mail campaigns: segment selection, recipient snapshot, batched sending state and unsubscribe. Opted-out customers are excluded when the campaign is queued and re-checked right before each send. |
messaging/email_log.rs | Sent-mail log (WHMCS "Email Message Log" / client "Email History"). |
messaging/email_templates.rs | Operator overrides for email templates. Defaults live in locale files (email.<name>.subject / email.<name>.body). |
messaging/event_mail.rs | Lookups behind event-driven customer emails (pelty_api::event_mail). |
messaging/link_tracking.rs | Link tracking: short /go/{slug} links that redirect and count clicks. |
messaging/mod.rs | Messaging repositories: email templates and log, event mail, campaigns, link tracking and outgoing webhooks. |
messaging/plugin_webhooks.rs | Plugin webhook endpoints (secret + URL override) and the delivery log. |
messaging/webhook_endpoints.rs | Outgoing webhook endpoints (admin-managed) and their delivery log. |
ops/admin_ops.rs | Admin ops: dashboard widget/quick-link prefs, login history, staff online, calendar, per-client email log (from the mail job queue), DB backups. |
ops/admin_tools.rs | Admin tools: global search, system health, My Notes, notification rules. |
ops/audit.rs | Audit log repository: record and list admin/client actions. |
ops/csv_import.rs | CSV import of clients, services and invoices with column mapping, preview and a real dry-run (the whole import runs in a transaction that is rolled back). A live run commits only when every row is valid. |
ops/dashboard.rs | Dashboard aggregates: each figure is one indexed aggregate query, never a per-row loop. |
ops/exports.rs | Tax report and accounting exports. All money stays Decimal; credit notes count negative so a period nets out correctly. |
ops/housekeeping.rs | System cleanup tasks from the WHMCS cron: prune old ticket attachments and keep customer active/inactive status in sync with what they own. |
ops/job_stats.rs | Read-only aggregates over the job queue for the automation dashboard. |
ops/jobs.rs | Postgres job queue: FOR UPDATE SKIP LOCKED claiming, exponential backoff retries, idempotency keys and stuck-job recovery. |
ops/mass.rs | Row updates behind admin list mass actions (customers, domains). |
ops/mod.rs | Admin operations repositories: audit log, dashboard, reports, exports/imports, mass actions, jobs and housekeeping. |
ops/report_library.rs | WHMCS-style report library. Every report is a fixed SQL query over a [from, to) time window returning text cells (money stays exact: NUMERIC is rendered by Postgres, never through floats). |
ops/reports.rs | Monthly financial reports. Every figure is computed in SQL with NUMERIC (exact decimals); months are UTC calendar months. |
registry/domain_defaults.rs | Default nameservers and DNS template for new domain orders (WHMCS "Default Nameservers" and DNS templates). |
registry/domain_pricing.rs | Registrar TLD cost sync with margin rules, premium-name pricing and per-TLD additional order fields. All money is exact Decimal. |
registry/domains.rs | Domains: TLD price list, orders (register/transfer), renewals and expiry reminders. Registrar calls happen in the API worker; this module only holds state. Prices are exact decimals. |
registry/domains_service.rs | DomainService: Registered domains and their lifecycle. |
registry/mod.rs | Domain repositories: registered domains, TLD pricing, defaults and registrant verification. |
registry/registrant_verify.rs | ICANN registrant e-mail verification (WHOIS accuracy). |
#pelty-docs
Documentation generator for PeltyCMS. Everything it writes is derived from code: the route inventory and utoipa schema, the event registry, the WASM runtime's capability/hook types, the WIT world, the UI schema, the config loader, the migrations directory and the extensions/examples/addon-guide sources. Guide prose lives in templates/.
| Module | What it does |
|---|---|
addons.rs | One page per bundled addon, generated from its addon.json plus the setting/field declarations found in its Rust source, and a catalog page. |
coverage.rs | Machine-checked documentation coverage. Each category lists the items the code defines and checks that the page documenting them mentions every one. tests::nothing_is_missing fails when an item is missing. |
doc.rs | Tiny document model rendered to HTML and Markdown, plus a parser for the Markdown subset used by templates/ (headings, paragraphs, - lists, fenced code, tables via directives). |
extract.rs | Source extractors: struct fields with doc comments, trait/fn source, marked snippets, env vars and migrations. |
highlight.rs | Syntax highlighting at generation time (syntect with the extra grammars from two-face). Output uses hl-<scope atom> classes; the colours (GitHub dark) live in templates/style.css, so pages need no JavaScript to look right. |
lib.rs | Documentation generator for PeltyCMS. Everything it writes is derived from code: the route inventory and utoipa schema, the event registry, the WASM runtime's capability/hook types, the WIT world, the UI schema, the config loader, the migrations directory and the extensions/examples/addon-guide sources. Guide prose lives in templates/. |
main.rs | pelty-docs [OUT_DIR], writes the developer docs (HTML, Markdown, JSON) to OUT_DIR (default target/docs). Run by cargo xtask docs (or make docs). |
pages.rs | Builds every page. Reference pages are assembled from code; guide pages come from templates/*.md with directives that pull code in. |
platform.rs | Platform reference pages built from structured sources: system settings keys, general settings, email templates and scheduled tasks. |
reference.rs | Events index, "cancel and modify" reference, widgets/slots index and hook-points index. Everything here is derived from the event registry, the emit sites in the source, the router and the frontend. |
routes.rs | Route inventory parsed from crates/pelty-api/src: every .route("…", …) call outside #[cfg(test)], with its methods, handlers and mount prefix. full_spec merges it with the utoipa document so every registered route appears in the API reference, documented or not. |
slots.rs | Addon UI injection points discovered from the frontend source: every page under the admin and client layouts (frontend/src/App.tsx), its route key and the slot names the Shell renders for it, plus the named slots placed by hand (<PluginSlot slot="…">, <PluginWidgets slot="…">). |
userdocs.rs | The general documentation set at /docs/: a landing page and the Administrator and Client guides. Prose lives in templates/user/*.md; tables are pulled from code with directives (see expand). |
#pelty-extensions
Themes and plugins: manifest loading/validation, hook bus, registry.
| Module | What it does |
|---|---|
addon_pkg.rs | Addon packages (.zip): pack, inspect and safely extract. |
addon_signing.rs | Detached Ed25519 release signatures. Trust comes only from operator keys. |
events.rs | Domain events published by core modules and consumed by plugins and addons. REGISTRY is the single source of truth: the generated docs (make docs) render it, and a test fails when the code emits an event (or a payload key) that is not registered here. |
filters.rs | Filter points: values the host passes through addon filters before using them (WordPress-style apply_filters). Each listener gets {filter, value, context} and replies {value}; the host keeps the JSON schema of the value (see same_schema), applies the money rules and always fails open (a failing filter leaves the value unchanged). |
functions.rs | Core functions addons can wrap with mixins (capabilities.mixins with target fn <name>). A before/around mixin may rewrite the function's input, an after/around mixin its output; both must keep the JSON schema (see same_schema) and never change money values. Identity values (who, which record) are passed in a read-only context. Mixins fail open: a failing or invalid reply leaves the value unchanged. |
lib.rs | Themes and plugins: manifest loading/validation, hook bus, registry. |
plugins.rs | Plugin model. Built-in plugins implement Plugin and are compiled in. External plugins are declared by extensions/plugins/<id>/plugin.json and run out-of-process (signed HTTP webhooks, see make docs). No native dynamic library loading, ever. |
themes.rs | Themes: extensions/themes/<id>/theme.json with whitelisted design tokens and optional static assets. No JS. Token values are validated against a strict character set so they cannot break out of a CSS declaration. |
ui_schema.rs | Declarative plugin UI: plugins describe pages and slot contributions as a JSON node tree that the frontend renders natively with shadcn components and the active theme. No plugin JavaScript ever runs in the app; embed (a sandboxed iframe) is a documented last resort behind the ui.embed capability. See make docs for the node reference. |
#pelty-import
WHMCS / Blesta / Paymenter -> PeltyCMS importer.
| Module | What it does |
|---|---|
blesta.rs | Blesta -> PeltyCMS. Reads a JSON export whose top-level keys are Blesta table names (clients, contacts, packages, pricings, ...) holding arrays of rows with Blesta's column names, and converts it to the WHMCS-shaped model consumed by crate::import::run_source. |
foreign.rs | Shared helpers for converting other billing systems (Blesta, Paymenter) into the WHMCS-shaped WhmcsData model, so a single, tested writer (import::run_source) does all the inserts. |
import.rs | Writes a WhmcsData snapshot into PeltyCMS. |
import_more.rs | WHMCS servers, contacts, promotions and tax rules (same transaction and import_map idempotency as the rest of crate::import). |
lib.rs | WHMCS / Blesta / Paymenter -> PeltyCMS importer. |
map.rs | Pure WHMCS -> PeltyCMS mapping rules. |
paymenter.rs | Paymenter (v1, Laravel) -> PeltyCMS. Reads a JSON export whose top-level keys are Paymenter table names (users, categories, products, plans, prices, services, invoices, invoice_items, invoice_transactions, gateways, tickets, ticket_messages, credits) and converts it to the WHMCS-shaped model consumed by crate::import::run_source. |
sqldump.rs | Reads a WHMCS database from a plain SQL export (mysqldump whmcs > whmcs.sql, phpMyAdmin "Export > SQL", or a hosting panel backup), so an import needs no running MySQL. Only CREATE TABLE (for column order) and INSERT|REPLACE [IGNORE] INTO ... VALUES (...), (...) statements are read; everything else (SET, LOCK TABLES, comments, indexes) is skipped. Values keep MySQL's text form; NULL is None. --hex-blob values (0x...) are decoded to text. |
whmcs.rs | Row structs for the subset of the WHMCS schema the importer reads. Column names follow the WHMCS database schema (tblclients, tblcurrencies, tblproductgroups, tblproducts, tblpricing, tblhosting, tblinvoices, tblinvoiceitems, tblaccounts). Money columns are decimal(16,2) in WHMCS and are carried as exact Decimal, never floats. |
whmcs_crypt.rs | WHMCS secrets. |
#pelty-notifications
Outbound email: a tiny template renderer, the Mailer trait and its SMTP / log / in-memory implementations. Delivery runs through the job queue (see pelty-api::worker), never inline in a request.
| Module | What it does |
|---|---|
lib.rs | Outbound email: a tiny template renderer, the Mailer trait and its SMTP / log / in-memory implementations. Delivery runs through the job queue (see pelty-api::worker), never inline in a request. |
mailer.rs | SMTP mailer built on lettre: builds and sends multipart emails. |
template.rs | {{var}} substitution. Deliberately logic-less: operators edit templates in the admin UI, so there is nothing to execute. |
#pelty-payments
Payment gateway abstraction. Gateways are drop-in modules implementing PaymentGateway and registered in GatewayRegistry. All provider HTTP goes through http::HttpTransport so it can be mocked.
| Module | What it does |
|---|---|
http.rs | HTTP transport used by every gateway. Gateways build HttpRequestSpecs and send them through an HttpTransport, so request logic is testable without network (in-memory MockTransport) or against a local mock HTTP server through ReqwestTransport plus the gateway's api_base override. |
lib.rs | Payment gateway abstraction. Gateways are drop-in modules implementing PaymentGateway and registered in GatewayRegistry. All provider HTTP goes through http::HttpTransport so it can be mocked. |
wire.rs | JSON wire format between the host and WASM gateway addons (pelty:[email protected] world, kind gateway). Money travels as exact decimal strings, never floats. |
#pelty-provisioning
Provisioning and registrar contracts: the module traits, registries, HTTP transports and shared helpers. No panel code lives here: every module (Pterodactyl, cPanel, Proxmox, ...) is its own addon crate under extensions/addons/prov-*, loaded as WASM. Scheduling, retries and persistence live in the job queue (pelty-api::worker). Every module describes its server and product settings with a declarative field schema, so the admin UI renders them natively without module code.
| Module | What it does |
|---|---|
http.rs | Small JSON HTTP helper shared by modules: bearer auth, timeouts, error classification (4xx = rejected, 5xx/network = transient). Never logs keys. |
lib.rs | Provisioning and registrar contracts: the module traits, registries, HTTP transports and shared helpers. No panel code lives here: every module (Pterodactyl, cPanel, Proxmox, ...) is its own addon crate under extensions/addons/prov-*, loaded as WASM. Scheduling, retries and persistence live in the job queue (pelty-api::worker). Every module describes its server and product settings with a declarative field schema, so the admin UI renders them natively without module code. |
licensing.rs | Software licensing primitives (the licensing addon is the module) (WHMCS Licensing Addon style). No remote panel: create mints a license key, lifecycle actions are reflected by the service status, and the public verify endpoint (POST /api/v1/licensing/verify) answers with a response signed with HMAC-SHA256 under the assigned server's API key (the "secret"). The first check binds the license to the caller's domain / IP / directory (if the product allows binding); reissue clears the binding. |
registrar.rs | Domain registrar modules. Real registrars implement RegistrarModule; MockRegistrar is an in-memory implementation for tests and demos and never touches the network. |
registrars.rs | Registrar host plumbing: the HTTP transports registrar addons send through, and the RDAP lookup used by the domain search. The registrars themselves (Namecheap, ResellerClub, Enom, OpenSRS, GoDaddy, CentralNic, generic JSON) live in extensions/addons/reg-*. |
sso.rs | Client single sign-on into a provisioned panel. |
template.rs | Tiny {{name}} template renderer used by the webhook and agent modules. No logic, no loops: unknown placeholders render empty, so a template can never reach data it was not given. Values are escaped for their target (JSON string content, URL path segment or a shell-free plain string). |
util.rs | Shared helpers for the panel / cloud modules. |
wire.rs | JSON wire format between the host and WASM addons of kind provisioning and registrar (pelty:[email protected]). Shared by the guest SDK and the host adapters so both sides agree byte for byte. |
#pelty-saml
SAML 2.0 Service Provider primitives, pure Rust, no unsafe, no C.
| Module | What it does |
|---|---|
c14n.rs | Exclusive XML Canonicalization 1.0 (without comments), <https://www.w3.org/TR/xml-exc-c14n/>, applied to an element subtree. |
dsig.rs | XML-DSig verification for enveloped signatures, restricted to a safe profile: one Reference to the parent element by ID, Exclusive C14N 1.0, SHA-256 digest, RSA-SHA256 or ECDSA-P256-SHA256. The key always comes from the configured IdP certificate; KeyInfo in the message is ignored. |
keys.rs | Signing keys and self-signed certificates (SP request signing, and the simulated IdP used by tests). |
lib.rs | SAML 2.0 Service Provider primitives, pure Rust, no unsafe, no C. |
sp.rs | SAML 2.0 Web Browser SSO profile, Service Provider side. |
testing.rs | A simulated Identity Provider for tests and the admin "test" button fixtures: builds and signs SAML Responses with locally generated keys. Not used on any production code path. |
xml.rs | Minimal namespace-aware XML tree built on quick-xml. |
#pelty-server
PeltyCMS server binary.
| Module | What it does |
|---|---|
bootstrap/mod.rs | First-run bootstrap (Minecraft-server style): when pelty-server starts in a folder it writes a commented .env (with a freshly generated encryption key), creates the folders the server writes to and the default locale files. Idempotent: existing files are never overwritten; later starts only create what is missing. |
console.rs | Interactive server console (Minecraft-server style): a line reader on stdin next to the HTTP server. On a terminal it uses a line editor (history, editing) whose external printer carries the log lines, so logs never garble the prompt; with --console on a pipe it reads plain lines. Commands reuse the same service functions as the admin API / CLI. |
embedded.rs | Files compiled into the binary by the embed-frontend feature (see build.rs): the web UI and the default themes, plus the addon zips only with the opt-in embed-addons feature (off by default and in releases). The UI is served straight from memory; themes and addon zips are written to disk because the server (and the admin, for themes) works with folders. |
eula.rs | eula.txt gate (Minecraft-server style). The first start writes eula.txt with eula=false; serve refuses to start until it says eula=true or the environment sets PELTY_EULA=true (Docker / CI). |
logging.rs | Tracing setup. Log lines go through Sink: straight to stdout, or, //! while the interactive console runs, through the line editor's external printer so they never garble the prompt. The filter sits behind a reload handle so log level <filter> can change it at runtime. |
main.rs | PeltyCMS server binary. |
setup/ai.rs | Optional provider configuration; secrets are collected without echoing. |
setup/mod.rs | Interactive first-run setup wizard (pelty-server setup, or automatically when serve starts in a terminal while .env says PELTY_SETUP=pending). |
setup/term.rs | Terminal prompts (dialoguer: hidden input works on Windows and Unix) and the live database / SMTP checks used by the wizard. |
setup/tests.rs | Tests for the interactive first-run setup with scripted answers. |
update.rs | pelty-server update [--check] [--version X] [--yes] [--no-backup] and the console update: install a release over the running binary. |
whmcs_import.rs | import whmcs for the CLI and the console: read a WHMCS SQL export (mysqldump / phpMyAdmin, no MySQL server needed) or a live MySQL DSN, decrypt server passwords with the WHMCS cc_encryption_hash, seal them with PELTY_ENCRYPTION_KEY and run the idempotent importer. |
#pelty-wasm
Sandboxed WebAssembly addons (Component Model / WIT).
| Module | What it does |
|---|---|
gateway.rs | Host adapter: a WASM addon of kind gateway exposed as a PaymentGateway. |
lib.rs | Sandboxed WebAssembly addons (Component Model / WIT). |
provisioning.rs | Host adapters: WASM addons of kind provisioning / registrar exposed as ProvisioningModule / RegistrarModule. |
runtime.rs | Generic addon runtime for WIT world pelty:addon/[email protected]. |