Procisely

PSI-owned URL shortener and asset link management platform. Provides persistent, branded short URLs that resolve to customer-facing destinations. Primary physical interface is a QR code sticker affixed to each shipped machine.


Overview

Procisely.com is a two-component platform:

  1. Redirect Engine — A public-facing Node.js service at procisely.com that resolves short URLs to destinations via 302 redirects. Customers scan QR code stickers on machines and are routed to the appropriate portal, documentation, or support page.

  2. Admin Interface — Integrated into the PSI Portal at portal.progressivesurface.com/procisely/. Provides redirect management, pattern rules, templates, QR code generation, bulk import, and analytics.

ResourceURL
Productionhttps://procisely.com
Admin UIhttps://portal.progressivesurface.com/procisely
Redirect Engine RepoProgressiveSurface/procisely-redirect
Admin CodePart of ProgressiveSurface/psi-portal
PRDC:\Users\AMD\OneDrive - Progressive Surface\Projects\URL Redirect\Procisely-PRD-V1.md

How It Works

Redirect Flow

Customer scans QR sticker on machine
  → procisely.com/S9820
  → Redirect engine looks up slug "s9820"
  → Match: SPN pattern rule (^S\d{4}$)
  → 302 → portal.progressivesurface.com/assets/s9820
  → Click event logged (slug, timestamp, user-agent, IP hash)

Resolution Precedence

  1. Exact slug match (Redirects table) — highest priority, allows per-slug overrides
  2. Pattern rules (PatternRules table) — regex-based, evaluated in priority order
  3. Default redirecthttps://www.progressivesurface.com

Rule Types

TypeWhen It RunsRequires DB Record?Example
Exact redirectRedirect timeYessupport → progressivesurface.com/support
Pattern ruleRedirect timeNo — matches via regex^S\d{4}$ → portal…/assets/{slug}
Rule templateCreation time onlyProduces recordsAdmin shortcut for batch creation

Architecture

Isolation Model

The redirect engine and admin interface are fully isolated. A compromise of the public service cannot reach internal resources.

LayerRedirect EngineAdmin (Portal)
ComputeDedicated App Service PlanExisting Portal App Service
NetworkPublic, no VNetPrivate endpoint
IdentityOwn managed identityPortal’s managed identity
SQL Roleprocisely_redirector (SELECT + INSERT only)procisely_admin (full CRUD)

Technology Stack

ComponentTechnology
Redirect EngineNode.js 22 LTS + TypeScript + Hono
Admin UIReact 19 + TypeScript + Vite + TailwindCSS (in Portal)
Admin APINode.js + Express (Portal backend routes)
DatabaseAzure SQL (Procisely on procserv-proddata)
QR Generationqrcode + sharp + archiver (server-side)
AuthEntra ID / MSAL (admin only)
HostingAzure App Service (Linux)

Infrastructure

Azure Resources

ResourceNameResource GroupDetails
App Service Planasp-procisely-redirectPS-WEBAPPSB1 Linux, dedicated (compute isolation)
App Serviceprocisely-redirectPS-WEBAPPSNode 22 LTS, Always On, public
Azure SQL DatabaseProciselyProcServices-Prod-DataBasic (5 DTU) on procserv-proddata
DNS Zoneprocisely.comPS-RG-01Azure DNS
SSL Certificateprocisely.comPS-WEBAPPSAzure-managed (GeoTrust), expires Oct 2026
Policy Exemptionprocisely-redirect-public-accessPS-WEBAPPSExempts redirect engine from “Deny App Service Public Network Access” policy
Application Insightspsi-webapps-insightsPS-WEBAPPSShared with other PSI web apps

App Settings (Redirect Engine)

SettingValue
SQL_SERVERprocserv-proddata.database.windows.net
SQL_DATABASEProcisely
SQL_AUTH_TYPEazure-active-directory-default
WEBSITES_PORT8080
NODE_ENVproduction
APPLICATIONINSIGHTS_CONNECTION_STRING(from psi-webapps-insights)

DNS Records (procisely.com)

RecordTypeValue
@A52.162.107.11 (App Service IP)
wwwCNAMEprocisely-redirect.azurewebsites.net
asuidTXTDomain verification hash

Domain registered at Network Solutions, nameservers delegated to Azure DNS (ns1-05.azure-dns.com through ns4-05.azure-dns.info).


Database Schema

Database: Procisely on procserv-proddata.database.windows.net

Tables

TablePurposeKey Columns
RedirectsSlug → destination mappingSlug (PK), DestinationUrl, RedirectType, Category, IsActive, HttpStatusCode
ClickEventsPer-click telemetryId (identity), Slug, ClickedAt, UserAgent, RemoteIpHash
RuleTemplatesCreation-time helpersTemplateId (PK), SlugPattern, DestinationPattern
PatternRulesRuntime regex rulesPatternRuleId (identity), Pattern, DestinationTemplate, Priority (unique)

SQL Roles

RolePermissionsUsed By
procisely_redirectorSELECT Redirects + PatternRules, INSERT ClickEventsRedirect engine managed identity
procisely_adminFull CRUD on all tablesPortal managed identity

Schema source: procisely-redirect/sql/schema.sql


Security

Redirect Engine Hardening

  • One route: GET /{slug} plus GET /health. No admin routes, no Swagger.
  • Slug sanitization: 5-step pipeline — URL decode, null byte rejection, CRLF rejection, alphanumeric+hyphen allowlist (max 128 chars), lowercase normalization.
  • Parameterized SQL queries only — slug never interpolated into query strings.
  • No user input in responses — returns only 302 + Location header. No HTML body, no error details.
  • Security headers on all responses: HSTS, CSP (default-src ‘none’), X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy no-referrer.
  • Rate limiting — in-memory per-IP rate limiter.
  • Click event IP privacy — SHA-256 hash only, full IP not retained.
  • Fire-and-forget click logging — click recording never blocks redirect response. Only logs clicks for actual matches (exact or pattern) — default fallback redirects (bot probes, unknown slugs) are not logged.

Pattern Rule Safety

  • Regex patterns are admin-authored only (never from public input).
  • Slug input bounded to 128 chars (limits ReDoS surface).
  • Invalid regex patterns are silently skipped at runtime.
  • Regex validation at creation time in the admin API.

Admin Features (Portal Integration)

All admin features are at portal.progressivesurface.com/procisely/*, behind Entra ID auth and private endpoint.

Pages

PageRoutePurpose
Dashboard/prociselyStats, default behavior config, active pattern rules, recent activity
Redirect List/procisely/redirectsFilterable table, inline toggle, bulk ops, CSV export
Redirect Editor/procisely/redirects/new or /:slug/editCreate/edit with template or custom mode
Bulk Import/procisely/bulk-importCSV upload, template import, combined onboard + QR flow
QR Generator/procisely/qrSingle/batch QR generation with logo overlay
Template Manager/procisely/templatesCRUD for creation-time templates
Pattern Rules/procisely/patternsRegex rule management with live tester
Analytics/procisely/analyticsClick trends, top redirects, category breakdown

API Endpoints

All endpoints at /api/procisely/*, authenticated via Entra ID bearer token.

MethodPathPurpose
GET/healthHealth check (no auth)
GET/POST/PUT/DELETE/redirects/*Redirect CRUD + bulk + from-template
GET/POST/PUT/DELETE/templates/*Template CRUD
GET/POST/PUT/DELETE/patterns/*Pattern rule CRUD + test + reorder
GET/analytics/*Click analytics + top redirects
GET/redirects/:slug/qrSingle QR generation
POST/redirects/batch-qrBatch QR ZIP download
POST/redirects/bulk-onboardTemplate import + QR download in one flow

Seed Data

Default Templates

TemplateSlug PatternDestinationCategory
Asset Customer Portal{serial}portal.progressivesurface.com/assets/{serial}asset
Recalibration Requestrecal-{serial}portal.progressivesurface.com/recalibration?asset={serial}support
Documentation Librarydocs-{serial}docs.progressivesurface.com/machines/{serial}asset
Campaign Landing Page{auto}(user-specified)campaign
Internal Tool Link{slug}(user-specified)internal

Default Pattern Rule

NamePatternDestinationPriority
SPN Asset Portal^S\d{4}$portal.progressivesurface.com/assets/{slug}10

This rule means every PSI serial number (S + 4 digits) automatically redirects to the asset portal without creating individual redirect records.


CI/CD

Redirect Engine

SettingValue
TriggerPush to main
Runnerpsi-internal (ps-cicd-runner, Ubuntu)
Authaz login --identity (managed identity)
Deployaz webapp deployment source config-zip
Tests70 unit + integration tests (Vitest)

Portal (Admin UI + API)

Deployed as part of the standard Portal CI/CD pipeline. Push to master triggers build + deploy.

Additional tests: 30 API route tests (Vitest + Supertest) via npm run test:api.


Testing

SuiteCountFrameworkCommand
Redirect engine unit tests62Vitestcd procisely-redirect && npm test
Redirect engine integration8Vitest + Hono app.request()Same
Portal API route tests30Vitest + Supertestcd psi-portal && npm run test:api
Total100

QR Code Specifications

SettingValue
Contenthttps://procisely.com/{slug}
FormatsPNG (raster) and SVG (vector)
Sizes128px to 2048px (PNG), scalable (SVG)
Error correctionLevel M (15%) default, Level H (30%) with logo
Logo overlayPSI logo centered at 20% of QR width
Print quality300 DPI minimum for 1” stickers
Batch exportZIP archive with filenames matching slugs

Future Roadmap

FeaturePriorityTrigger
Business Central integrationHighBC go-live — auto-create asset links from shipped machines
Geolocation analyticsMediumWhen click volume justifies GeoIP cost
Dynamic customer routingMediumPortal queries customer from serial
Bot detectionLowClick analytics reliability
Link expirationLowCampaign use cases grow
CPQ integrationMediumAuto-generate links at order time
Per-redirect 301 optionLowSEO benefit for permanent redirects (schema field exists)