Cross-cutting · Realtime updates (Pusher)
A websocket channel used for two things: streaming a customer’s captured signature into the open customer form, and delivering AI-generated proposal images when they are ready.
| Area | Cross-cutting |
| Routes | crm.users.edit · cms.proposals.new |
| Centre modules | always available |
| Staff levels | as per the host screen |
| Models | proposal · user |
| UI label | error.signature.not_exist |
| Coverage | 3 use cases · 2 happy · 3 failure |
Known issues (1)
How it works
pusher.connectToChannel(id, callback) subscribes per record and disconnectToChannel(id) is called in willDestroyElement, so subscriptions are scoped to the open form. In the customer form the callback simply writes model.signatureUrl, which is what makes a signature captured on a paired tablet appear without a reload. In the proposal editor the same mechanism carries the result of an AI image generation, which is inherently slow. There is no reconnection or fallback polling: if the socket drops, the update silently never arrives and the user must reload.
Use cases
Why someone opens this (3)
- A customer signing a GDPR consent on a tablet while the operator watches it appear on the record.
- Waiting for an AI-generated proposal image without polling or reloading.
- Keeping a long-lived form in step with an out-of-band action.
Path map
flowchart LR F(["Realtime updates Pusher"]):::feat F --> H1["Signature appears live"]:::ok F --> H2["AI image delivered"]:::ok F -.-> X1["Socket connection lost"]:::bad F -.-> X2["Signature not captured"]:::bad F -.-> X3["Subscription leak"]:::bad classDef feat fill:#8c5a3c,stroke:#8c5a3c,color:#ffffff,font-weight:bold classDef ok fill:#e3f1ea,stroke:#0d6b42,color:#0d4a2e classDef bad fill:#f7e6e2,stroke:#9a2d1c,color:#6e1f13
Happy paths
Signature appears live
- Operator opens an existing customer; the form subscribes to that user’s channel.
- The customer signs on a paired device and the signature is stored.
- The pushed URL is written to
model.signatureUrland renders immediately.- Leaving the form unsubscribes.
AI image delivered
- User requests an AI image on a proposal.
- Generation runs asynchronously; the result arrives over the channel.
- The image is offered for review and attachment.
Failure paths
Socket connection lost
Cause — Network interruption or provider issue.
What happens — No reconnect or polling fallback — the update never arrives and nothing tells the user. The form looks simply as if nothing happened.
Signature not captured
Cause — The customer never signs, or the device fails.
What happens — Downstream features report
error.signature.not_exist(‘The user does not have signature’) — for example when generating a communication confirmation PDF.
Subscription leak
Cause — The component is destroyed without
willDestroyElementrunning.What happens — Guarded by the explicit disconnect, but only when
this.modelis present.
QA checklist
Tick these off while regression-testing this feature. The boxes are plain Markdown, so progress is visible in git diffs.
- ✅ Signature appears live
- ✅ AI image delivered
- ⛔ Socket connection lost
- ⛔ Signature not captured
- ⛔ Subscription leak
Implementation
app/services/pusher.jsapp/components/form-user.jsapp/controllers/cms/proposals/new.jsapp/routes/application.js
Translation keys (1)
Key English error.signature.not_existThe user does not have signature
Related
- Same area — CSV import engine · Data export engine (email delivery) · Filter & segment builder component · File upload, gallery & image modal · Multi-language content authoring · Role & module permission layer · Error presentation & API error mapping · Product analytics & error monitoring
- Shares data with — Activity campaigns (programme grouping) · Proposal list & publication workflow · Proposal editor (content, coupon, push, AI images) · Push notification editor (scheduling, geofencing, deep links) · Customer list & filtering · Customer create & edit · Customer deletion with unsubscribe notice · Customer CSV export with column picker
Generated from doc/feature-inventory.json · id xc-realtime · commit 276788ca6