The controls in place today: how the service is reached, how accounts and payments are handled, what we keep, and how a change gets to production.
Frameworks
PolicyChanges is compliant with HIPAA, PCI DSS and NIST CSF. These three standards set the bar for the work described on this page, and each one maps to the controls listed below.
HIPAA
The Security Rule’s technical safeguards (access control, transmission security, audit controls) are the model the application is built against. The data set is scoped deliberately: PolicyChanges runs on payer policy documents and the provider roster records you supply, which keeps patient records out of the system entirely.
PCI DSS
Card data is handled end to end by Stripe, a PCI DSS Level 1 service provider. Payment details are entered on Stripe’s own hosted page, which keeps our servers outside card scope altogether.
NIST CSF
The five functions organize the operational side: an inventory of what runs and what it stores (Identify), the network and access controls below (Protect), automated alarms that page a human on failure (Detect and Respond), and nightly restorable database backups (Recover).
Hosting and network
The whole service runs inside a single United States region. Our application servers are reachable only through our content delivery layer; there is no direct public route to them.
Edge and TLS
Every connection is encrypted. The edge terminates TLS, redirects every plain HTTP request to HTTPS, and negotiates a minimum of TLS 1.2. Certificates are issued and rotated automatically, so renewal is a property of the platform rather than a calendar reminder somebody has to honour.
Origin isolation
The application servers accept exactly one inbound port, and only from the published address ranges of our content delivery layer. Traffic that has not come through the edge has no path to the application, so the protections applied at the edge cannot be stepped around by addressing the origin directly.
Administrative access
Remote login ports are closed to the internet. Operators reach a server through a brokered session service that authenticates each person against our central access controls and records the session, so administrative access is individually attributed rather than shared. Credential material available to the server itself is reachable only by an authenticated, session-token request, which closes the credential-theft path that unauthenticated metadata access leaves open.
Response headers
Every response carries HSTS (max-age=31536000; includeSubDomains), X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and a Permissions-Policy that switches off camera and microphone.
Edge logs
Request-level access logging is on at the edge and delivered to dedicated, private, versioned storage, so there is a durable record of what reached the service and when.
Accounts and sessions
Identity provider
Customer authentication is handled by a dedicated managed identity provider. Sign-up, sign-in, password change and password reset all happen there. Your password is passed straight through to it and never lands in our database. There is no password column in any table and no hashing code in the application, because there is nothing for us to hash.
Sessions
A session is a signed token issued by that identity provider, valid for one hour. Every request through the application’s middleware re-verifies the token signature against the provider’s published signing keys and checks both issuer and audience before the request is allowed to continue.
Cookies
Session cookies are set httpOnly (unreadable from JavaScript), secure in production (HTTPS only), and sameSite=lax to blunt cross-site request forgery.
Payments
Card handling
Checkout is Stripe-hosted. Clicking a plan sends you to a Stripe Checkout session on Stripe’s domain, where card details are entered. Those details are never posted to, processed by, or stored on our systems. The codebase contains no card-number field at all. Subscription management runs through the Stripe Customer Portal on the same basis.
Webhook integrity
Every Stripe webhook is verified against the endpoint signing secret before it is acted on, and each event id is recorded so a replayed or duplicated event is processed once.
What we store
The record we keep about you is deliberately thin: account identity, organization and team membership, notification preferences, saved searches and filters, which policy changes you have read or saved, and the subscription record that backs billing. It is encrypted in transit and at rest with industry-standard algorithms.
Scope
The monitored source material is payer policy documentation: public and provider-facing bulletins, coverage policies and billing updates. Patient records have no place in that workflow and no field in the schema.
Roster uploads
CSV uploads are parsed into roster records for screening. The original upload file is not retained as a separate document. Optional SSN and EIN values are encrypted individually, never used for matching, and never returned in full by the API. Responses include only masked last-four digits and presence flags.
Backups
The database is dumped nightly, compressed, and shipped to private object storage with server-side encryption and versioning on by default and public access blocked at every level. A lifecycle rule expires each daily backup after 90 days.
Roster data and OIG screening
Exclusion screening compares a roster you provide against selected exclusion sources. The available sources include the HHS OIG List of Excluded Individuals and Entities (the public LEIE file), SAM.gov, and supported state lists. Each downloaded source is size-capped and hashed with SHA-256, so the exact snapshot a result was produced from is identifiable after the fact.
Optional identifiers
SSN and EIN are optional. When one is supplied it is encrypted at rest with industry-standard authenticated encryption, under a unique random initialization vector per value, so two identical numbers never produce the same stored ciphertext. Only the last four digits are retained in readable form, for display as ••••1234.
They stay put
The API never returns a full stored SSN or EIN. Its responses carry masked last-four digits and a flag saying whether a value is on file, and nothing more. The screening code paths emit no log output whatsoever, so there is no application log for an identifier to appear in. Free-text review notes reject anything shaped like an SSN or EIN on the way in, which keeps them out of the fields that were never meant to hold them.
Not used for matching
Matching runs on NPI, name, business name, state and date of birth. The encrypted identifiers are held for your own verification work and take no part in producing a match.
Deletion
Stored identifiers can be cleared at any time, individually or as part of resolving a record, and doing so writes an audit event. The encrypted value and the last-four display value are both removed in the same operation.
Email authentication
Sending domain
Outbound mail is cryptographically signed and domain-authenticated. It leaves from a verified policychanges.app domain identity on a reputation-monitored sending path, with bounces and complaints suppressed automatically.
DKIM, SPF, DMARC
DKIM signing is active on 2048-bit keys, with the signing records published in DNS. A dedicated envelope-sender subdomain carries an SPF record so the envelope sender aligns. A DMARC record is published with an aggregate reporting address, so authentication results come back to us for review.
How changes reach production
No long-lived keys
Releases are automated, and the automation holds nothing worth stealing. The pipeline exchanges a short-lived workload identity token for temporary cloud credentials that are scoped to this one repository and expire on their own. There is no standing access key sitting in the build system to leak or rotate.
Reviewed, then scripted
Every change is run through an automated code review gate before it can land, and a release then executes a checked-in script rather than hand-typed commands: fetch, install, build, migrate, restart, health check. The pipeline confirms the public health endpoint is answering before it reports success. Production deploys are triggered deliberately rather than firing on every commit.
Monitoring and backups
Infrastructure and application health are monitored continuously, with alerting on anomalies.
Uptime
An external health check polls /api/health over HTTPS from multiple geographic regions. That endpoint runs a live query against the database, so it reports on the data path and not merely on whether a process is listening.
Alarms
Nine alarms watch the service: site down, worker down, disk filling, memory and swap pressure, host auto-reboot and auto-recovery, email delivery stalling, and policy data going stale. They page out to SMS and to a staffed chat channel, so a failure reaches a person rather than a dashboard nobody is looking at.
Restore
Backups are taken nightly and retained for 90 days, with a checked-in restore script and an alert that fires if a backup job fails.
Reporting a security issue
Found something, or need detail for a vendor review? Write to security@policychanges.app. Reports reach a maintainer directly and get a reply. If you are reporting a vulnerability, please include the steps to reproduce it and give us a chance to ship a fix before publishing.