Security & Verification

Security & Verification

How Vault Platform enforces security at every layer — from Entra ID authentication and Managed Identity through item-level access control, document integrity verification, and deep-link safety in VaultLifecycle.

This page explains how Vault Platform security works in practice — the specific mechanisms, enforcement order, and what is checked at each boundary. For compliance posture, sub-processor lists, and pen-test scoping, see the Trust Center.


The No-Egress Principle

Vault Platform is built on a single foundational rule: your document data never leaves your Azure environment.

Unlike a conventional PDF SaaS API where you upload data to a vendor's cloud, every render in Vault Platform happens inside your own Azure subscription. The rendering engine runs in your Dispatcher Function App. Templates are retrieved from your SharePoint. Generated PDFs are stored in your SharePoint or your Azure Blob Storage. At no point does a document payload, a template, or a generated file transit outside your tenant boundary.

Tenant-Native Rendering

The PDF engine runs inside your Azure Function App. Document data is processed in-memory within your subscription and never sent to VaultPDF servers.

Customer-Controlled Storage

All outputs, templates, audit logs, and workflow state are stored in storage you control — SharePoint or Azure Blob Storage — using Managed Identity access only.

Vendor Access Limited to Licensing

VaultPDF's external systems receive only your licenseKey and tenantId for license validation. No document content, payload data, or user information is ever transmitted.


Security Architecture Overview

flowchart TB
  subgraph External["Entry Points"]
    SPFx["SharePoint / SPFx<br/>VaultLifecycle UI"]
    D365["Dynamics 365 / Power Automate<br/>Power Platform Connector"]
    Portal["Vault eSign Portal<br/>(External Signers)"]
  end

  subgraph CustomerTenant["Your Azure Environment"]
    Entra["Microsoft Entra ID<br/>Authentication & JWT Issuance"]
    Disp["Vault Dispatcher Function App<br/>JWT validation · Feature gates · Render engine"]
    SB["Azure Service Bus<br/>Priority Queues (MSI-connected)"]
    Proc["Processor Function Apps<br/>VaultWorkflow · VaultESign · VaultDelivery · VaultAudit"]
    KV["Azure Key Vault<br/>All secrets — vendor staff have no standing access"]
    SP["SharePoint<br/>Templates · Generated Docs · Activity List"]
    Blob["Azure Blob Storage<br/>Audit JSONL · Dispatch payloads · Archives"]
    Entra --> Disp
    Disp --> SB
    Disp --> KV
    Disp --> SP
    Disp --> Blob
    SB --> Proc
    Proc --> KV
    Proc --> SP
    Proc --> Blob
  end

  subgraph VaultShared["Vault Platform Shared Services"]
    Lic["Licensing API<br/>licenseKey + tenantId only"]
    Notify["VaultNotification<br/>Metadata only — no document content"]
  end

  SPFx -->|"Entra ID Bearer JWT + Function Key"| Disp
  D365 -->|"OAuth 2.0 Bearer JWT"| Disp
  Portal -.->|"HMAC portal token · HTTPS"| Disp
  Disp -.->|"licenseKey + tenantId"| Lic
  Proc -.->|"Event metadata only"| Notify

What Crosses to Vault Shared Services

This reference answers the question that matters most for data residency and compliance reviews: exactly which data transits Vault Shared Services infrastructure, per product.

Document content never crosses — for any product or configuration

Document source data (JSON payloads), rendered PDF bytes, templates, file attachments, form field values, and generated files never transit Vault Shared Services under any product or configuration. This is a hard architectural boundary, not a policy choice.

Data transit reference by product

DataYour subscription onlyTransits Vault Shared ServicesDetail
All products
Document source data, payloads, templatesYesNeverRendering runs in your Dispatcher
Generated PDF bytesYesNeverStored in your Blob Storage or SharePoint
licenseKey + tenantIdYes — Licensing APINo document content; HTTPS only
VaultESign
Document (signer views it)YesNeverServed via your Dispatcher proxy; portal renders UI only
Signer invitation email + portal linkYes — notification metadataNo document content; covered under Refract Logic DPA
Signature PNG (drawn in browser)Yes — stored at restTransits in-memoryPortal POSTs HMAC callback containing PNG to your Dispatcher; not stored on portal — see note below
Initials, date, text, checkbox fieldsYesNeverSubmitted to your Dispatcher; stored in your Table Storage
Evidence certificateYesNeverGenerated in your Processor; stored in your Blob
VaultDelivery
PDF bytes (recipient download)YesNeverSAS URL → browser → your Blob; portal serves UI metadata only — see note below
Recipient invitation email + portal linkYes — notification metadataEmail address + link + document name; no document content
Delivery session state, audit eventsYesNeverWritten to your Table Storage and audit JSONL
VaultWorkflow
Form field data (all types)YesNeverBrowser → your Dispatcher → your Table Storage
File attachmentsYesNeverBrowser → Dispatcher pre-sign → directly to your Blob Storage; portal server never in upload path — see note below
Participant invitation email + portal linkYes — notification metadataEmail + link; no form data or document content
Workflow state, decisions, approvalsYesNeverStored in your Table Storage + audit JSONL
Sealed PDF + Evidence AppendixYesNeverGenerated and stored in your subscription
Notifications (all products)
Email addressYes — vault-shared modeFor ACS delivery; covered under Refract Logic DPA. Use customer-acs mode to keep this in your tenant entirely.
Portal access linkYes — vault-shared modeTime-limited token; no document content
Document nameYes — vault-shared modeDisplay only in email subject/body; no document content
Document bytes, file content, form dataNeverNeverNot included in any notification under any mode

Notes on in-memory transit and byte paths

Signature PNG (VaultESign): The signer draws their signature in the browser on the portal UI. When they submit, the portal server constructs an HMAC-signed callback body — which includes the signature PNG — and POSTs it to your Dispatcher. The PNG transits portal servers in-memory during this callback. It is not stored on portal servers and the callback is HMAC-verified by your Dispatcher before use.

File attachments (VaultWorkflow): Attachment uploads use a pre-signed Azure Blob SAS URL issued by your Dispatcher. The browser uploads the file bytes directly to your Azure Blob Storage container — the portal server is never in the upload path and never receives the file content.

Document download (VaultDelivery): The delivery portal (portal.vaultpdf.io) serves session metadata only (document name, expiry, state). When the recipient downloads, their browser calls your Dispatcher's SAS endpoint, which issues a short-lived Azure Blob SAS URL. The document bytes stream directly from your Azure Blob Storage to the recipient's browser — portal servers are not in the byte path at any stage.

Notification emails: In vault-shared mode, the notification payload (email address, portal link, document name, notification type) transits the VaultPDF notification service. In customer-acs mode, notifications are sent directly from your own Azure Communication Services instance and Vault Shared Services is not involved for delivery or workflow notifications. See Email Provider Configuration for the current VaultESign caveat.


Layer 1 — Microsoft Entra ID Authentication

Every request to Vault Platform begins at Entra ID. This is not optional and cannot be bypassed.

SharePoint / SPFx callers

VaultLifecycle is a SharePoint Framework (SPFx) web part and command set deployed inside your SharePoint environment. Before the SPFx components load:

  1. The user must authenticate to your SharePoint site with a valid Entra ID session.
  2. SharePoint enforces site-level permissions. A user without access to the VaultPDF SharePoint site cannot reach the page.
  3. Only after a valid SharePoint session is established does the SPFx runtime load and the VaultLifecycle workspace become visible.

There is no way to access VaultLifecycle content by guessing or crafting a URL. Authentication to SharePoint is a hard prerequisite.

Power Platform / Dynamics 365 callers

The Vault Platform Power Platform Connector uses OAuth 2.0 with Entra ID as the identity provider. Every API call carries a Bearer JWT. The Dispatcher Function validates the token on every request — there is no session or cookie that persists across calls.

Direct API callers

Direct calls to the Dispatcher Function API require:

  • A valid Azure AD Bearer JWT (validated on every hop)
  • A Function host key passed as ?code= in the query string

Both must be present. The function key is stored in your SPFx property bag (encrypted at rest by SharePoint) and is never embedded in client-side source code.


Layer 2 — VaultLifecycle Access Control

VaultLifecycle enforces a four-layer access control model. All four layers apply identically whether the workspace is opened manually (by clicking the command button) or via a deep link.

Layer 2a — SharePoint site authentication

Covered above. Unauthenticated users cannot reach the page.

Layer 2b — SharePoint list permissions (server-enforced)

All data in VaultLifecycle is read from the VaultPDF_Activity SharePoint list via SharePoint REST API. SharePoint enforces list-level read permissions server-side on every request. A user who does not have Read access to the VaultPDF_Activity list receives an HTTP 403 — the SPFx client receives no data regardless of what filters are set.

This is independent of the SPFx UI. The UI cannot show data that SharePoint refuses to return.

Layer 2c — Admin role resolution (live server-side call on every open)

When the VaultLifecycle workspace opens, it immediately makes two live SharePoint REST calls before displaying any results:

GET /_api/web/currentuser?$select=IsSiteAdmin
GET /_api/web/currentuser/groups?$select=Title

These calls resolve the user's actual admin status from the server at open time. The isAdmin value derived from these calls controls:

  • Whether the user sees all items or only items they are permitted to see
  • Whether the Configuration panel and admin-only actions are available

There is no client-side override for admin status. A URL parameter, a manipulated prop, or a cached value cannot elevate a user's permissions — the live server response is authoritative.

A user is treated as admin if either:

  • They are a SharePoint Site Collection Administrator, or
  • They are a member of the VaultPDF.Admin SharePoint group

Layer 2d — Item-level access control (VPDFRestrictionMap)

After SharePoint returns the list of activity items, each item passes through a client-side visibility check before being shown. Items where VPDFExcludeFromSearch=true never return from SharePoint at all (pre-filtered at the OData query level). For all other items, the following rules apply:

ConditionResult
User is VaultPDF AdminItem visible at admin level (full metadata)
Item has no VPDFRestrictionMapItem visible at operational level (open access)
User's email matches VPDFInitiatedBy or VPDFSignerEmailItem visible at operational level (creator/participant)
User's SharePoint group matches a VPDFRestrictionMap entryVisible at the level granted in that entry
No matchItem silently excluded from results

VPDFRestrictionMap is a pipe-delimited string stored on each activity item. An example value:

Finance.Approvers=admin|HR.Managers=operational

This means members of the Finance.Approvers SP group see the item at admin level; members of HR.Managers see it at operational level; everyone else sees nothing.

When an item is visible but at operational level (not admin), sensitive fields such as PdfHash, internal metadata, and document integrity controls are redacted — the item is still findable and openable, but privileged information is withheld.

Restriction Map Precedence

If a user matches multiple group entries in VPDFRestrictionMap, they receive the highest matching visibility level. Creator/participant status (operational) is checked before group membership and serves as a shortcut — no group lookup is required for the item's own initiator or signers.


Layer 3 — API Authentication (Dispatcher Function)

Calls from VaultLifecycle to the Dispatcher Function for extended data (audit events, signing state, delivery state, workflow state) use AadHttpClient — the SharePoint Framework's AAD-integrated HTTP client.

Every such request:

  1. Automatically attaches a Bearer JWT scoped to the Dispatcher Function's AAD application registration (API_RESOURCE_ID)
  2. Includes the Function host key as ?code= (stored encrypted in the SPFx property bag)
  3. Is validated by the Dispatcher on receipt — both the token audience and the function key must be valid

Neither of these values is readable from the browser's URL bar, local storage, or network responses in plaintext. The AAD token is issued by Entra ID with a short TTL and is automatically refreshed by the SPFx AAD client.


Layer 4 — Managed Identity for Azure Services

Inside the Dispatcher and Processor Function Apps, all access to Azure services uses Managed Identity (MSI). No passwords, connection strings with credentials, or client secrets are stored in application code or environment variables for Azure resource access.

ResourceAccess method
SharePoint (templates, activity list, generated docs)MSI via Microsoft Graph — Sites.ReadWrite.All
Azure Blob Storage (payloads, archives, audit JSONL)MSI — Storage Blob Data Contributor
Azure Service Bus (dispatch queues)MSI — Azure Service Bus Data Sender/Receiver
Azure Table Storage (batch dispatch state)MSI — Storage Table Data Contributor
Azure Key Vault (all secrets)MSI — Key Vault Secrets User

VaultPDF vendor staff have no standing access to your Key Vault. The secrets your deployment uses (JWT signing keys, encryption keys, ACS keys) are provisioned by your team and accessible only by your Function App's MSI.


Licensing Security

License entitlements are cryptographically signed using JWS ES256 (ECDSA P-256). VaultPDF holds the private signing key. Your Dispatcher holds only the public verification key — it can verify entitlements but cannot forge them.

The runtime uses a 4-tier cascade:

Tier 1 — In-memory cache (24-hour TTL)

The verified entitlement is held in memory. No external call. Tier 2+ is only reached on cache miss or startup.

Tier 2 — SharePoint license.vpdf

The Dispatcher reads the signed entitlement file from your SharePoint. Any modification to this file causes JWS signature verification to fail — the file is discarded and Tier 3 is attempted.

Tier 3 — Licensing API

A direct HTTPS call to license.vaultpdf.io carrying only licenseKey and tenantId. The response includes a fresh signed license.vpdf bound to your tenant ID. If the tid claim in the response does not match your configured tenant, the response is rejected.

Tier 4 — 48-hour grace period

If the Licensing API is unreachable (outage, network issue), the Dispatcher operates on the last known-good entitlement for up to 48 hours. Grace does not apply to genuine license revocations or expirations — those are communicated in the Tier 3 response and take effect immediately.


VaultLifecycle supports deep links — URLs with query parameters such as ?batchId=, ?correlationId=, or ?sourceSystem= that pre-populate the search and auto-open the workspace. This is useful for source systems (Dynamics 365, Business Central) that want to provide a one-click link directly to a specific document's lifecycle view.

Deep links do not bypass any security layer

A deep link pre-populates filter state. It does not modify authentication, admin resolution, SP list permissions, or item-level visibility checks. Every layer described above runs identically whether the workspace opens via button click or deep link.

URLEffect
Home.aspx?correlationId=d8cb1510-8290-40f8-8592-702eaa9838a6Workspace opens with CorrelationId pre-populated in search
Home.aspx?batchId=082ab853-7852-47f0-b078-1927d2d92619Workspace opens with BatchId pre-populated in search
Home.aspx?sourceSystem=D365_FOWorkspace opens with Source System filter set to D365_FO
Home.aspx?q=INV-001&sourceSystem=D365_FOWorkspace opens with text search and source system filter combined
  • Grant access to a user who is not authenticated to SharePoint
  • Elevate a user's admin status
  • Show items the user's SP permissions do not allow
  • Show items the user's VPDFRestrictionMap visibility does not permit

A non-privileged user who follows a deep link with a valid ?correlationId=... will see zero results if the corresponding activity item is restricted — the search executes, returns nothing (because SP enforces permissions and the visibility check excludes the item), and the workspace is empty.

CorrelationId and BatchId are globally unique

CorrelationIds and BatchIds are UUID v4 values generated by Vault Platform at render/dispatch time. They are globally unique by construction — no sourceSystem qualifier is needed to identify a specific record. A source system can safely use:

https://your-sharepoint-site/SitePages/Home.aspx?batchId=082ab853-7852-47f0-b078-1927d2d92619

and it will always resolve to exactly that batch. Adding &sourceSystem=D365_FO is harmless but redundant for GUID-based lookups.

IDs are visible in browser history

CorrelationIds and BatchIds in deep-link URLs appear in the browser's address bar, browser history, and corporate proxy logs. These are internal job identifiers, not credentials — they grant no access on their own. However, if your organisation's policy restricts internal identifiers in URLs, consider opening VaultLifecycle from an authenticated portal rather than sharing deep links externally.


eSign Security

VaultESign uses short-lived HMAC-SHA256 portal tokens to authenticate external signers. These tokens are issued by the Dispatcher and verified by the eSign Portal.

PropertyValue
Token bindingcorrelationId, action, timestamp — a token is valid only for the specific action it was issued for
TTL4 hours from issuance
DerivationHKDF-derived kEnc (AES-GCM) + kMac (HMAC-SHA256) from a root key in your Azure Key Vault
Replay preventionmessageId = {correlationId}-delivery enforced at Service Bus — duplicate messages are discarded
Approver PII protectionApprover email addresses in workflow state are encrypted with AES-256-GCM before storage; the key is in your Azure Key Vault

The eSign Portal is stateless — it does not store document content. Document bytes are streamed from your storage via the Dispatcher at the moment of signing, and the Portal never retains them.


Document Integrity Verification

Every PDF generated by Vault Platform is SHA-256 hashed at render time. The hash is stored in the VaultPDF_Activity list (PdfHash column) and in the audit JSONL.

Verification process

From VaultLifecycle, any document with a stored hash can be verified in one click:

Re-download the PDF

The Dispatcher retrieves the current file from storage (SharePoint or Azure Blob).

Compute current hash

SHA-256 is computed on the downloaded bytes client-side.

Compare against stored hash

The computed hash is compared against the PdfHash value stored at render time in the activity list.

Result

Match = the PDF has not been modified since generation. Mismatch = the file was altered or replaced after the original render. The result is shown in the Integrity panel.

Audit chain integrity

The immutable audit JSONL uses a hash chain: each event includes a previousHash field linking it to the prior event. The verifier API checks chain continuity from the first event to the most recent. A gap or modification in any event breaks the chain and is reported.


Data Encryption

In transit

All communication within Vault Platform uses HTTPS with TLS 1.2+. This includes:

  • SPFx → Dispatcher Function
  • Dispatcher → SharePoint Graph API
  • Dispatcher → Azure Blob Storage
  • Dispatcher → Azure Key Vault
  • Dispatcher → Licensing API
  • Azure Service Bus connections (AMQP over TLS)

The Dispatcher Function App has httpsOnly: true enforced in the Bicep deployment template. HTTP is rejected at the Azure layer.

At rest

DataEncryptionKey ownership
Azure Blob Storage (outputs, audit, archives)AES-256 (Azure Storage Service Encryption)Microsoft-managed by default; customer-managed key (CMK) via Azure Key Vault available
Azure Key Vault secretsAES-256 (HSM-backed)Azure — your tenant
Approver email addresses (workflow state)AES-256-GCM + random IVYour Azure Key Vault (ESIGN_ENCRYPTION_KEY)
Portal tokensHKDF-derived AES-GCM + HMAC-SHA256Your Azure Key Vault
Audit verification reportsAES-256 (Storage SSE) + HMAC-SHA256 companion .sig.jsonStorage SSE + your AUDIT_REPORT_HMAC_KEY
Batch dispatch payloadsAES-256 (Azure Storage SSE)Microsoft-managed (see blob note above)

Key Management

All Vault Platform secrets are stored in your Azure Key Vault. The deployment Bicep template provisions the Key Vault with:

  • enablePurgeProtection: true — irreversible; prevents secret deletion bypassing soft-delete
  • 90-day soft-delete retention
  • No standing access granted to VaultPDF vendor staff

Key rotation is an operator action:

az keyvault secret set \
  --vault-name <your-kv-name> \
  --name esign-encryption-key \
  --value <new-key>

The approver-email ciphertext schema includes a keyId field to support re-encryption on key roll without data loss.

Never store secrets in source code or environment variables

All secrets should be stored in Azure Key Vault and referenced via Key Vault references in your Function App configuration (e.g. @Microsoft.KeyVault(VaultName=kv-name;SecretName=secret-name)). Direct environment variable values for secrets are not recommended for production deployments.


Input Validation and Injection Prevention

Attack vectorControl
OData injection in SharePoint queriesSingle-quote doubling on all user-supplied values; no raw string concatenation in filter expressions
SSRF via external asset fetchDNS resolution mandatory; resolved IP validated against RFC 1918 blocklist; IP pinned for duration of fetch
ZIP slip in .vpdf template extractionassertSafeArchiveEntryName rejects path traversal, absolute paths, UNC paths, drive letters, and control characters before any extraction
Expression injection (conditional styles)Zero eval / Function usage; prototype key blocklist; max expression length 4096; max token count 1024; max eval depth 200
Duplicate seal replayService Bus messageId = {correlationId}-workflow-seal; requiresDuplicateDetection: true on queue
Concurrent approval raceOptimistic ETag concurrency on all intermediate workflow state updates; 412 returned as HTTP 409
Schema substitution mid-workflowSHA-256 of fetched YAML verified against value stored at workflow start; mismatch throws

Security Layer Summary

The following table summarises what is enforced at each boundary for a typical VaultLifecycle open — manual button click or deep link:

LayerEnforced byClient override possible?
Page accessSharePoint / Entra ID authenticationNo — redirect to login if unauthenticated
List data accessSharePoint REST API (server-side)No — 403 if no list permissions
Admin statusLive SP REST calls at open timeNo — server response is authoritative
Item visibilityVPDFRestrictionMap + VPDFExcludeFromSearchNo — filtered at SP query level and post-receive
API calls (audit, signing, delivery)AAD Bearer JWT + Function keyNo — token issued by Entra ID; key stored encrypted
Azure resource accessManaged Identity (MSI)No — no credentials accessible to application code
Secret accessAzure Key Vault (MSI)No — vendor staff have no standing access
Document integritySHA-256 hash stored at render timeNot applicable — verification is on-demand
LicensingJWS ES256 signed entitlementsNo — signature verified locally; cannot be forged

Compliance Summary

StandardStatus
GDPR (EU)Data stays in your Azure region; no document content transits VaultPDF systems; DPA available on request
HIPAA / HITECHCustomer-owned infrastructure model supports BAA with Microsoft; no PHI transits VaultPDF systems
FedRAMP ModerateCustomer-owned deployment into Azure Government regions supported; controls mapping available on request
SOC 2 Type IPlanned
ISO 27001Planned — leveraging SOC 2 control mapping
PDF/UA-1 (Section 508)Structural tagging, MarkInfo, StructTreeRoot, Lang, ViewerPreferences/DisplayDocTitle implemented
WCAG 2.1 AAPDF-side implemented; UI accessibility improvements in backlog

For the full sub-processor list and data processing addendum, see the Trust Center.


Security Questionnaires and Pen-Test Scoping

Contact the Vault Platform security team for security questionnaire responses, architecture review packages, and pen-test scoping documentation.

On this page