Skip to main content

PMS Sync is currently in a pilot programme; capabilities described here are live in pilot deployments.

Cloud Services & Operations

Cloud Services & Operations

Last updated Owner: AlterspectiveFor: Alterspective operators & platform admins

The operator's reference for the hosted side of PMS Sync — what runs where, how it deploys, how to check it is healthy, and which environment variables configure it. The hosted Portal and Proxy are multi-tenant: one deployment serves every client, with each tenant isolated by its org config and token claims. All secrets are environment variables resolved from Azure Key Vault — never hard-coded and never shown here.

1. Services, ports & deployment

ServicePortWhere it runsDeploy
Import PortalAderantImportPortal3060pms-sync.alterspective.com.au · staging.pms-sync.alterspective.com.auCoolify — develop to staging, main to production
API ProxyShareDoAderantAPIProxy3050aderant-proxy.alterspective.com.auCoolify — main to production
SQL API agentAderantSQLAPITypeScript4102On-premise · via Azure Relay / ngrokWindows MSI on the client host (not Coolify)
Embed widgetfoundry-widgets/pms-sync-embedSharedo IDEFoundry CLI → /_ideFiles/Alterspective/PmsSync/Embed
Deploy model. The Portal and Proxy are containerised (running as a non-root appuser) and deploy via Coolify: develop feeds the staging portal at staging.pms-sync.alterspective.com.au, while main feeds production. The SQL API agent is installed at the client as a Windows service (see the Deployment Guide). The embed widget is published to the Sharedo IDE with the Foundry CLI — not through Coolify.

2. Health & version endpoints

Every service exposes health endpoints (exempt from auth and rate limiting) whose bodies report build/version information — version, buildTime, environment, and the normalized environment label such as PRE PROD for staging. Both backends serve their API under /api/v1/* and stamp an X-API-Version header; the legacy /api/* path remains a deprecated alias.

ServiceEndpointMeaning
PortalGET /api/healthLiveness (used by the container healthcheck).
ProxyGET /healthLiveness — always 200 when the process is up.
ProxyGET /health/readyReadiness — checks the upstream on-prem agent.
ProxyGET /health/deepFull upstream diagnostics with latency.
SQL APIGET /api/healthLiveness — always 200; body carries version + schema count.
SQL APIGET /api/health/ready200 only when SQL is reachable and schema discovered (else 503).
SQL APIGET /api/health/checksFull diagnostics in the body (always 200).

3. Security controls & rate limits

  • API-key guard — every service-to-service call carries x-api-key; the agent and proxy fail hard in production when the key is missing or weak.
  • CORS — origins come from ALLOWED_ORIGINS (comma-separated). Unset in production means deny-all; there are no wildcard defaults.
  • Rate limits — global ~300 req/min and search ~60 req/min (tunable); import POST routes are fixed at 20 req/min per IP. Traefik sits in front with trust proxy = 1.
  • Write gate — imports are blocked unless writes are enabled for the org. The per-org Settings value (import_write_enabled) takes precedence; IMPORT_WRITE_ENABLED is the env-level fallback. A blocked import POST returns 501.
  • Embed SSO — the widget's short-lived HS256 JWT is signed with PORTAL_EMBED_SECRET (rejected if shorter than 32 chars).

4. Logging & observability

  • Structured pino logging in the Portal and Proxy; the SQL API writes structured JSONL (logs/app-YYYY-MM.jsonl).
  • A correlation id (x-correlation-id) propagates Portal → Proxy → SQL API so a single import can be traced across all three.
  • Sentry error tracking runs in the Portal and Proxy.
  • Backend AI capabilities are exposed as MCP services at /mcp (Keystone OAuth 2.1) — see Architecture & Dependencies.

5. Environment variable reference

Variable names only — values are configured per environment and resolved from Key Vault. These are the key variables for standing up or operating each service; each service's .env.example is the complete, authoritative list.

Import Portal

  • KEYSTONE_URL · KEYSTONE_APP_IDKeystone OIDC identity + app registration
  • KEYSTONE_HANDOFF_SECRET · KEYSTONE_SERVICE_KEYKeystone handoff + service auth
  • APP_URLPublic base URL — required; the OIDC callback fails without it
  • ENTRA_TENANT_ID · ENTRA_CLIENT_ID · ENTRA_CLIENT_SECRETMicrosoft Entra ID sign-in path (omit to disable the Entra button)
  • SESSION_SECRETSigns the portal session cookie
  • SUPABASE_URL · SUPABASE_SERVICE_ROLE_KEYPer-org config + import history store
  • IMPORT_PROXY_URL · IMPORT_PROXY_API_KEYReaches the API Proxy
  • PORTAL_EMBED_SECRET · PORTAL_AUDIENCEVerifies the Sharedo embed SSO handoff JWT (shared with the Proxy)
  • EMBED_ALLOWED_HOSTSCSP frame-ancestors + postMessage allowlist for the Sharedo origin (defaults to self — embedding is blocked until set)
  • CRON_SECRETValidates scheduled close-sync calls from the Proxy (must match the Proxy value)

API Proxy

  • API_KEYService-to-service guard — fails hard in production if absent
  • ALLOWED_ORIGINSCORS whitelist (comma-separated). Unset in prod = deny all. No wildcards.
  • RATE_LIMIT_GLOBAL_PER_MIN · RATE_LIMIT_SEARCH_PER_MINRate-limit tuning (defaults 300 / 60)
  • DB_PROXY_URL · DB_PROXY_API_KEYReaches the on-prem SQL API agent over the tunnel
  • ADERANT_API_URLUpstream Aderant REST base URL (write-back / health probes)
  • SHAREDO_IDENTITY_URL · SHAREDO_API_URL · SHAREDO_INSTANCEClio Operate / Sharedo write target
  • SHAREDO_CLIENT_ID · SHAREDO_CLIENT_SECRET · SHAREDO_SCOPEOAuth client for the write path
  • IMPORT_WRITE_ENABLEDEnv-level write fallback — the per-org Settings value takes precedence
  • PORTAL_EMBED_SECRET · PORTAL_AUDIENCESigns/validates the widget SSO JWT (secret ≥32 chars)
  • SUPABASE_URL · SUPABASE_SERVICE_ROLE_KEYLoads per-org config for embedded pass-through + Proxy MCP
  • PORTAL_CRON_URL · CRON_SECRETEnables scheduled close-sync; disabled unless both set (portal /api/cron/run validates the secret)
  • ADERANT_AUTH_TYPE · ADERANT_USERNAME · ADERANT_PASSWORD · ADERANT_DOMAINUpstream Aderant REST auth (basic / NTLM)

SQL API agent

  • SQL_SERVER · SQL_PORT · SQL_DATABASE · SQL_USER · SQL_PASSWORDRead-only Aderant connection (see SQL Database Setup)
  • SQL_ENCRYPT · SQL_TRUST_SERVER_CERTIFICATETLS posture
  • PORTListen port — default 4102
  • API_KEYx-api-key guard — refuses to start in prod if missing / <32 chars / placeholder
  • AZURE_RELAY_CONNECTION_STRING · AZURE_RELAY_NAMESPACE · AZURE_RELAY_PATH · AZURE_RELAY_KEY_NAME · AZURE_RELAY_KEYOutbound Azure Relay tunnel — the agent enters Hybrid Connection mode only when AZURE_RELAY_CONNECTION_STRING is set
Never commit secrets. SHAREDO_CLIENT_SECRET, API keys, relay keys, and SQL passwords are environment variables only. IMPORT_WRITE_ENABLED must stay an env var — never hard-coded.

For the component model and dependencies, see Architecture & Dependencies. For the on-prem agent install, see the Deployment Guide. For hosting and data residency, see Security & Data Residency.