Skip to content

Customer Password Recovery Events

Responsibility and flow

CustomerForgotPassword
  → EventBus: CustomerPasswordResetRequestedRecord + EV_RECORD_ADD
  → WorkflowManager: conditions and logical delivery route
  → EventBus: CustomerPasswordResetRecord + EV_RECORD_ADD
  → Router: explicit JSON field list
  → Moleculer: customer.password_reset.delivery_requested
  → external module: route filtering, channel, template and delivery

Server owns token generation, expiry and password reset. Workflow does not know mailer templates or templateId. The server does not call MailerSendEmail in this flow. Modules are trusted plugin-like participants. Delivery acknowledgement is a later stage.

Internal input

CustomerPasswordResetRequestedRecord contains request_id, customer_id, brand, language, country, first_name, last_name, email, phone, reset_url, requested_at and expires_at. These are a customer snapshot: no extra customer lookup is required. The internal EventBus name and workflow trigger are customer.password_reset_requested. Router does not export this input record.

Workflow direction

Scope: CRM. Conditions: brand, customer.country, customer.language, customer.email, customer.phone. Contact presence can be tested with != "". Only one action is allowed for this trigger:

[
  {
    "type":"customer.password_reset.request_delivery",
    "params":{"delivery_route":"customer-recovery-email"}
  }
]

delivery_route must be a nonempty string. It is a logical route, not a template, provider or arbitrary event name. Configure active rules per brand, with higher-priority specific rules and a lower-priority fallback. The first successful matching rule ends processing regardless of stop_processing. A request can claim delivery only once. No matching rule means no outbound request, with a server diagnostic.

These definitions are exposed through MngGetWorkflowTriggers, MngGetWorkflowActionsByTrigger and MngGetWorkflowConditionsByTrigger. Validation is available through MngValidateWorkflowRule; rules use the existing CRUD API. Workflow history stores request_id, not reset_url/token.

External output

C++ payload: CustomerPasswordResetRecord, with the input fields plus delivery_route. Internal name: customer.password_reset; accepted code: EV_RECORD_ADD. Explicit specialised external mapping: customer.password_reset.delivery_requested.

The current implementation emits a flat JSON payload, not the proposed generic event envelope with data/schema_version/event_id:

{
  "request_id":"<opaque correlation identifier>",
  "customer_id":140,
  "brand":"default",
  "language":"en",
  "country":"CY",
  "first_name":"John",
  "last_name":"Smith",
  "email":"[email protected]",
  "phone":"+35700000000",
  "delivery_route":"customer-recovery-email",
  "reset_url":"https://terminal.example.com/en/sign/recovery/<64-character token>",
  "requested_at":1789459200,
  "expires_at":1789461000
}

customer_id is integer; timestamps are Unix seconds; other fields are strings. The module subscribes using normal Moleculer event handling and processes only its delivery_route. This field is consumer-side routing, not a NATS permission or targeted broker subscription: multiple matching subscribers may receive the event. Avoid multiple independent delivery consumers for the same route unless they coordinate.

The module maps route/purpose + brand + language to its own templates and delivery configuration. Email is one possible channel; other modules may handle SMS or another delivery system without changes to the server's template logic.

Secrets and delivery semantics

reset_url intentionally contains the recovery secret and is available to trusted subscribers. Do not log it, persist it in ordinary workflow history, expose it in analytics or rewrite it into click-tracking links. It may grant password-reset access, but does not grant login access or disable OTP.

No acknowledgement, retry, replay or durable delivery guarantee is implemented. Workflow success means the delivery-request event was emitted, not that a module received it or sent a message. request_id can be used for consumer deduplication. Server reset state is memory-only and survives neither restart nor process failover. Tokens expire after 30 minutes. The token in the link is distinct from request_id; the retained manager state contains only its hash, not the link.

See CustomerForgotPassword and CustomerResetPassword.