The reference implementation is correct end-to-end but optimized for clarity over production rigor. Work through this list before promoting beyond a dev PDI.
- Use a dedicated PDI / sub-prod for staging, then move to prod
with the same config. Take notes; the
02-servicenow-setup.mdchecklist is designed to be re-run. - Promote via Update Set, not by re-clicking through the UI.
Capture the role, user, custom column, Scripted REST API + both
resources, both
sys_properties, and the Business Rule into a single update set so the prod move is one import. - Restrict Scripted REST role grants narrowly. Only the bridge
service account should hold
x_intranet_bridge_caller. Don't re-use the role for human users. - Rotate the
intranet.bridgepassword on a schedule. The bridge needs a single env-var update; no code change. - Use a
password2-typedsys_propertyforintranet_bridge.outbound_webhook_secretso it isn't visible in casual UI browsing. - Audit the BR script — anyone with
business_rule_admincan modify it. Treat the Business Rule and Scripted REST scripts as production code under change control.
-
Persist
BridgeSessionoutside the process. The reference_sessionsdict is in-memory: a worker restart loses every in-flight chat. Move to Redis or a small relational table keyed bybridge_session_id. State to persist: -state(BOT/QUEUED/LIVE/CLOSED) -interaction_sys_id,interaction_number-conversation_sys_id,sn_user_sys_id-user_email,user_display_name,rep_name*Status:* the bridge runs on Azure Container Apps as `ca-cps-bridge` pinned to `min=max=1` exactly because of this. Externalising state is the prerequisite to scaling out and to zero-downtime deploys. -
Constant-time secret comparison. Replace
secret == SN_WEBHOOK_SECRETwithhmac.compare_digest(...). Same forAGENT_API_SECRET. -
HTTPS only. Terminate TLS at your ingress; reject plain HTTP.
-
Rate-limit the public endpoints, especially
/api/servicenow/escalate(cheap to call, expensive on the SN side: each call creates an interaction + queues a work item). -
Authentication for
/api/servicenow/escalate(browser-facing). Today, anyone with abridge_session_idcan escalate. Either: - Validate the session id against an authenticated user (e.g. SSO session cookie), or - Remove the browser-facing escalate path entirely and only allow Copilot Studio's/agent/escalate(withX-Agent-Secret). -
Bind the consumer identity to the authenticated user. Replace
SN_DEFAULT_USER_SYS_IDwith a real lookup (e.g. SSO claim →sys_userlookup by email). -
Drop
agent_api_secretfrom URLs. The reference accepts it as either a header or a query string. For prod, remove the query string fallback. -
Centralize logging. Forward bridge logs to your APM / observability stack so you can correlate
bridge_session_idacross user-message, webhook, and Direct Line activity. -
Add health/readiness endpoints (
/healthz,/readyz) and gate them behind your platform's health checks.
- Move secrets out of the Topic editor. The HTTP action's
X-Agent-Secretheader value is visible to anyone with edit access to the agent. Use Copilot Studio's Connectors with a stored credential, or front the bridge with an API gateway that injects the secret based on caller identity. - Add a fallback message when the HTTP action fails — show the user something like "Sorry, I couldn't reach a live agent right now. Please email support@yourco.com." rather than dying silently.
- Don't trust the
bridge_session_idfrom query strings orlocalStorage. It's allocated by the server on page load (/api/servicenow/init-session); always use that result, never a cached value from a previous session. - Render rep messages with text-only escaping. Don't innerHTML
the
textfield — it comes from a chat message that could contain<script>-like content. The reference snippets usetextContent. - Handle session expiry. Decide what to do when the bridge
returns 404 on poll (e.g. session GC'd because user left the page
open for hours). Reset to
botmode and re-init.
- Synthetic monitoring. Run an end-to-end probe (the sequence
in
06-end-to-end-test.md) on a schedule against your prod bridge from outside your network. Alert on failure. - Capacity planning. Each escalation creates a SN
sys_cs_conversation,interaction,sys_cs_session,sys_cs_session_binding,awa_work_item, plus Nsys_cs_messagerows. SN PDIs have very low rate limits; check with your SN admin for prod limits. - Disaster recovery. If the bridge goes down:
- In-flight chats: agents in SOW can still see and reply to the
chat, but consumer messages won't reach them and agent replies
won't reach consumers.
- New chats: Copilot Studio HTTP action fails → fallback message.
Have a documented "the bridge is down" playbook (e.g. expose
support@yourco.comand a status page).
These are reasonable extensions but not done in the reference:
- Multi-region failover for the bridge.
- File / image attachments in either direction.
- Typing indicators ("Alex is typing…") — would require subscribing to
additional
sys_cs_*events or polling the conversation. - Read receipts.
- Transcript persistence outside ServiceNow.
- Internationalization of the auto-greeting / status messages.