# SFMagic Security Policies

**Last updated:** May 14, 2026
**Owner:** Tim Cox, principal (tim@timcox.co)
**Scope:** All systems supporting the SFMagic service at sfmagic.co, including the application, database, marketplace agent, and supporting infrastructure.

SFMagic is a sole-proprietor operation. These policies are written to match that scale — concrete commitments, no aspirational fiction. As the team grows, the policies evolve and each section names the trigger for that evolution.

This document is the canonical reference for security commitments. Where it conflicts with marketing or sales material, this document governs.

---

## 1. Information Security Risk Management

**Commitment.** Risks to confidentiality, integrity, and availability of customer data are identified, ranked, and tracked on an ongoing basis.

**Process.**

- **Identification.** New risks are surfaced through (a) automated dependency scanning (GitHub Dependabot), (b) Vercel and Neon platform advisories, (c) upstream advisories from Microsoft, Salesforce, Anthropic, Stripe, and Resend, (d) usage telemetry anomalies surfaced in `/app/usage` and the weekly review digest, and (e) incidents and near-misses.
- **Ranking.** Each finding is scored using CVSS v3 where the upstream advisory provides one, otherwise a local impact × likelihood judgment. Weighting is increased when the affected component handles Microsoft customer data, Salesforce credentials, or payment data.
- **Tracking.** Findings are logged as GitHub Issues on the sfmagic repo with a `security` label. Status is reviewed weekly when the Monday digest is processed.
- **Acceptance.** A risk may be accepted only by the principal, with reasoning recorded on the issue.

**Cadence.** Continuous. Weekly review checkpoint every Monday.

**Trigger to formalize further.** First non-principal employee or contractor with production access.

---

## 2. Data Retention and Disposal

**Commitment.** Customer data is retained only as long as needed to operate the service, and is deleted on a defined schedule when no longer needed.

**Retention by data type.**

| Data | Location | Retention |
| --- | --- | --- |
| Account record (email, hashed password, org details) | Neon Postgres | Lifetime of the account |
| Salesforce OAuth refresh tokens (encrypted) | Neon Postgres | Until revoked by the customer or the account is deleted |
| Salesforce object/field metadata snapshots | Neon Postgres | Lifetime of the tenant link |
| Microsoft 365 tenant link + Entra ID identity claims | Neon Postgres | Lifetime of the tenant link |
| Usage events (tool name, latency, error, timestamp) | Neon Postgres | 13 months rolling, then aggregated |
| Feedback submissions | Neon Postgres | Lifetime of the tenant unless deletion requested |
| Stripe customer / subscription IDs | Neon Postgres + Stripe | Per tax retention requirements (7 years for invoice records) |
| Sentry error events | Sentry | 90 days per Sentry default |
| Vercel access / function logs | Vercel | 1–30 days per Vercel plan retention |

**Disposal.**

- Account or tenant deletion is executed via `scripts/delete-tenant.ts`, which cascades through all related rows in the database.
- Microsoft tenant unlink removes rows in `m365_tenant_links` and `m365_user_sf_links` immediately.
- Salesforce token revocation (initiated from the customer's Salesforce Setup) is detected server-side and the corresponding token row is deleted.
- Encrypted database backups maintained by Neon age out within the platform's standard retention window (currently 7 days on the free_v3 plan; the upper bound for any plan is 30 days).
- Customers may request immediate deletion of their account by emailing tim@timcox.co.

**Cadence.** Immediate on customer-initiated deletion; passive retention bounds otherwise.

---

## 3. Access Management — Customer Data, Encryption Keys, Secrets

**Commitment.** Access to production systems, customer data, encryption keys, and shared secrets is limited to the minimum number of principals necessary to operate the service.

**Current state.**

- Sole principal (Tim Cox) holds all production access. There are no employees or contractors with production credentials at time of writing.
- All third-party accounts (Vercel, Neon, GitHub, Stripe, Resend, Sentry, Microsoft Entra admin, Salesforce Dev Hub, Anthropic, Namecheap) are protected with multi-factor authentication.
- Production secrets and encryption keys are stored as encrypted environment variables in Vercel, scoped to the sfmagic project. Local copies live only in the principal's developer workstation `.env.local`.
- OAuth refresh tokens for customer Salesforce orgs are encrypted at rest in Postgres using AES-256-GCM with `TOKEN_ENCRYPTION_KEY`.
- Third-party API credentials use scoped or restricted variants where supported: Stripe restricted key (`rk_live_…`), Salesforce External Client App with PKCE, Sentry project-scoped keys.

**Process for adding access (future employees or contractors).**

1. Identify the minimum set of systems required for the role.
2. Provision named accounts on each system (no shared credentials).
3. Require MFA on every account.
4. Record the grant in a separate access register.
5. Review quarterly for need-to-have.
6. Revoke immediately on role change or departure.

**Key rotation.**

- `TOKEN_ENCRYPTION_KEY`, `AUTH_SECRET`, `CRON_SECRET`: rotated on suspected exposure; otherwise annually.
- Third-party API keys: rotated on suspected exposure or when a provider deprecates the key version; otherwise annually.
- Customer OAuth tokens: refreshed automatically by the Salesforce OAuth refresh flow; no manual rotation.

**Trigger to formalize further.** First non-principal access grant.

---

## 4. Encryption

**Commitment.** Customer data is encrypted in transit and at rest.

**In transit.**

- All inbound HTTPS traffic to sfmagic.co terminates at Vercel's edge, which enforces TLS 1.2 and TLS 1.3 (TLS 1.0/1.1 disabled by default).
- Database connections to Neon Postgres require TLS 1.2 or higher (`sslmode=require`).
- All outbound calls to third-party APIs (Microsoft Graph, Salesforce, Anthropic, Stripe, Resend, Sentry) are made over HTTPS with TLS 1.2 or higher.

**At rest.**

- Neon Postgres encrypts all data and backups at rest using AES-256.
- Sensitive application-layer data — specifically customer Salesforce OAuth refresh tokens and per-tenant Salesforce client secrets (`tenants.sfConfig.clientSecretEnc`) — is additionally encrypted with AES-256-GCM at the application layer using `TOKEN_ENCRYPTION_KEY` before being written to the database.
- Vercel environment variables holding production secrets are encrypted at rest by Vercel.
- Sentry events are encrypted at rest per Sentry's standard.

---

## 5. Change Management

**Commitment.** All changes to production are version-controlled, reviewed, tested, and deployable as immutable artifacts with rollback.

**Process.**

1. Changes are authored in branches on the sfmagic repository.
2. All commits are signed by the author and pushed to GitHub.
3. Continuous integration runs the full test suite on every push.
4. Preview deployments are created automatically by Vercel for every commit and validated before merge to `main`.
5. Merge to `main` triggers an immutable production deployment on Vercel.
6. Rollback to any prior deployment is one click in the Vercel dashboard and takes effect within seconds.
7. Deployment history is preserved indefinitely in Vercel and the Git commit log.

**Code review.** The service is currently operated by a single principal, so peer code review is not in place. Compensating controls: CI gating, immutable artifacts, preview validation, runtime error capture (Sentry), and the ability to revert any change instantly. The trigger to introduce peer review is the first non-principal commit author, after which two-person approval will be required for all merges to `main`.

---

## 6. Vulnerability Management

**Commitment.** Vulnerabilities are identified through continuous automated and platform-level scanning, ranked by severity, and patched within defined SLAs.

**Identification.**

- GitHub Dependabot scans application dependencies on every commit and on every newly published advisory.
- Vercel performs platform-level vulnerability scanning on its runtime, edge network, and managed infrastructure.
- Neon performs scanning on the managed Postgres tier.
- Upstream advisories from Microsoft, Salesforce, Anthropic, Stripe, and Resend are monitored via their respective security mailing lists or status pages.

**Ranking.** Findings are ranked using CVSS v3 (Critical 9.0+, High 7.0–8.9, Medium 4.0–6.9, Low 0.1–3.9), with additional weighting where the affected component handles Microsoft customer data or Salesforce credentials.

**Patching SLAs.**

| Severity | Time-to-patch |
| --- | --- |
| Critical (CVSS 9.0+) | Within 48 hours of advisory |
| High (7.0–8.9) | Within 7 days |
| Medium (4.0–6.9) | Within 30 days |
| Low (0.1–3.9) | Next regular release |

**Platform infrastructure.** Vercel runtime, Node.js, and Neon Postgres are patched automatically by the providers within their own SLAs. The principal is responsible for monitoring patch-related provider advisories.

**Scanning cadence.** Continuous, which exceeds a quarterly cadence. A formal third-party penetration test is planned within the first 12 months of broader adoption.

**Audit trail.** Patch application is auditable via the Git commit log (which deploys are linked to which advisories) and the Vercel deployment history.

---

## 7. Disaster Recovery and Backup

**Commitment.** The service can recover from data loss or infrastructure failure within defined objectives.

**Recovery objectives.**

| Metric | Target |
| --- | --- |
| RTO (Recovery Time Objective) | 4 hours |
| RPO (Recovery Point Objective) | 24 hours |

**Backup strategy.**

- Neon Postgres provides automated backups with point-in-time recovery within the platform's retention window.
- Application source is version-controlled in Git, with offsite copies on GitHub.
- Environment variables are mirrored to a secure local developer workstation, enabling re-creation of production configuration if Vercel state is lost.
- Vercel retains all prior deployments as immutable artifacts, enabling rollback to any prior version.

**Restore procedures.**

- **Database corruption or accidental deletion.** Restore from Neon point-in-time recovery to a new branch, validate, then promote.
- **Application regression.** Roll back to the prior immutable deployment in Vercel.
- **Full Vercel project loss.** Re-link the GitHub repository to a new Vercel project, restore environment variables from the local copy, redeploy from `main`.
- **Database provider loss.** Provision a new Neon project, restore from the most recent automated backup or downstream replica, update `DATABASE_URL`, redeploy.

**Testing cadence.** Vercel rollback is exercised on the rare production regression. Full disaster simulation is planned annually starting Q4 2026.

---

## 8. Security Incident Response

**Commitment.** Security incidents are detected, contained, investigated, and communicated on a defined timeline, including notification to supervisory authorities and affected individuals within 72 hours of detection of a personal-data breach.

**Definition.** A security incident is any event that compromises, or threatens to compromise, the confidentiality, integrity, or availability of customer data, the service, or supporting infrastructure.

**Detection sources.**

- Sentry alerts on runtime errors and anomalies.
- Vercel deployment failure and platform alerts.
- Stripe and Resend bounce or failure notifications.
- Weekly review digest surfacing usage anomalies.
- Customer reports to tim@timcox.co.
- Third-party security disclosures.

**Severity ladder.**

| Severity | Description | Initial response |
| --- | --- | --- |
| SEV-1 | Customer data exposure, full service outage, or compromised credential | Within 1 hour |
| SEV-2 | Partial outage, degraded performance, or near-miss exposure | Within 4 hours |
| SEV-3 | Minor degradation, isolated errors, advisory follow-up | Within 1 business day |

**Response process.**

1. **Detect** — initial signal received and validated.
2. **Contain** — stop the bleeding. Revoke compromised credentials, roll back to the last-good deployment, take affected endpoints offline if necessary.
3. **Assess** — determine scope. What data, how many customers, what time window?
4. **Notify** — at SEV-1, customer notification is initiated within the 72-hour breach-notification window where personal data of EU or UK residents is involved (GDPR Article 33), or as required by applicable US state laws. Microsoft is notified through Partner Center if the incident affects M365 customer data.
5. **Investigate** — root cause analysis.
6. **Remediate** — apply permanent fix.
7. **Document** — post-incident report filed in `docs/security/incidents/YYYY-MM-DD-slug.md`.

The detailed operational steps live in `docs/security/incident-response-runbook.md`.

**72-hour breach notification.**

- For breaches involving personal data of EU/UK residents, supervisory authorities and affected individuals are notified within 72 hours of detection per GDPR Article 33.
- For breaches involving Microsoft 365 customer data, Microsoft is notified through Partner Center within the same window.
- For breaches involving California residents, notification follows California Civil Code §1798.82.

**Trigger to formalize further.** First SEV-2 or above incident.

---

## 9. Logging and Monitoring

**Commitment.** All system components supporting the service generate event logs, which are reviewed regularly for security-relevant events.

**Logging coverage.**

| Component | Log source | Captured |
| --- | --- | --- |
| Application compute | Vercel function logs | Request, response, function invocation, errors |
| Application errors | Sentry | Stack traces, request context, user-agent |
| Edge / DDoS | Vercel platform logs | Inbound IPs, blocked requests, anomalies |
| Database | Neon logs | Connection events, slow queries |
| Tool dispatch | In-app `usage_events` table | Tool name, tenant, user session, latency, error, records returned |
| Authentication | NextAuth + application logs | Sign-in, sign-out, token issue |
| OAuth flows | Application logs | Authorization, callback, revoke |
| Email delivery | Resend dashboard | Send, bounce, complaint |
| Billing | Stripe dashboard | Subscription events, invoice events |

**Alerting.** Sentry sends real-time alerts to tim@timcox.co for new error fingerprints. Vercel sends deployment-failure alerts. Resend surfaces delivery failures. Stripe surfaces payment failures.

**Review cadence.**

- Push-based alerts are triaged at receipt.
- A weekly automated digest runs every Monday at 09:00 ET via Vercel Cron, processed by an LLM agent that reviews `usage_events` for anomalies (retry bursts, zero-result spikes, error-rate jumps) and emails a summary to the principal.
- Customer-visible usage analytics at `/app/usage` are available to every tenant admin.

---

## 10. Sub-processors and Third-Party Data Sharing

**Commitment.** Customer data is shared only with infrastructure sub-processors necessary to operate the service, each governed by a Data Processing Agreement.

**Current sub-processors handling customer data.**

| Sub-processor | Purpose | Location | DPA |
| --- | --- | --- | --- |
| Vercel Inc. | Application hosting, edge, logs | AWS us-east-1 (US) | vercel.com/legal/dpa |
| Neon | Postgres database hosting + backups | AWS us-east-1 (US) | neon.tech/dpa |
| Sentry | Error telemetry | US | sentry.io/legal/dpa |
| Resend | Transactional email (outbound notifications, feedback, digest) | US | resend.com/legal/dpa |
| Stripe | Billing | US | stripe.com/legal/dpa |
| ImprovMX | Inbound email forwarding for the @sfmagic.co apex domain | US | improvmx.com/terms |
| Anthropic | LLM inference for the onboarding agent and weekly digest | US | anthropic.com/legal/commercial-terms |
| Microsoft (Entra ID, Partner Center) | Identity for M365 users, marketplace operations | US | microsoft.com/licensing/docs/customeragreement |
| Salesforce | The customer's own Salesforce org (data origin and destination) | Per customer | salesforce.com/company/legal/agreements/data-processing-addendum/ |

Microsoft customer data (Entra ID identity claims and tenant identifiers) flows only to Vercel, Neon, and Sentry. The other sub-processors above handle other categories of data and do not receive Microsoft-specific identity information unless the customer explicitly submits it (for example, by including an email address in a feedback message).

**Onward transfer.** Customer data is not sold, used for advertising, or shared with any party outside the sub-processor set listed above.

**Notification.** New sub-processors are added only when needed to operate the service, and the change is reflected in this document and on the public `/security` page.

---

## 11. Secure Development

**Commitment.** Secure coding practices address common vulnerability classes including the OWASP Top 10 (2021).

| OWASP category | How we address it |
| --- | --- |
| A01 — Broken Access Control | Bearer-token authentication on every MCP call; tenant scoping enforced on every query; per-user Salesforce identity on every dispatch |
| A02 — Cryptographic Failures | TLS 1.2+ everywhere; AES-256-GCM for tokens at rest; bcrypt for password hashing; no rolled-our-own crypto |
| A03 — Injection | Parameterized queries via the Drizzle ORM; no raw string concatenation into SQL; structured SOQL parameter binding for Salesforce |
| A04 — Insecure Design | Read-only Salesforce OAuth scopes; minimal attack surface; least-privilege scoped API keys |
| A05 — Security Misconfiguration | Vercel and Neon platform defaults; secrets only in encrypted env vars; no admin endpoints exposed without authentication |
| A06 — Vulnerable Components | GitHub Dependabot continuous scanning; patching SLAs in §6 |
| A07 — Authentication and Identification Failures | NextAuth with bcrypt password hashing; PKCE on all OAuth flows; MFA on all administrative accounts |
| A08 — Software and Data Integrity Failures | Immutable Vercel deployments; signed Stripe webhooks; verified Entra ID bearer tokens via JWKS |
| A09 — Security Logging and Monitoring Failures | See §9 |
| A10 — Server-Side Request Forgery | No user-controlled outbound URL fetches; outbound calls limited to a fixed set of providers |

**Dependency management.** Application dependencies are pinned in `package-lock.json` and upgraded on advisory or routine cadence.

---

## 12. Employee Lifecycle

**Commitment.** When the service has employees or contractors, a documented joiner / mover / leaver process governs access provisioning, modification, and removal.

**Current state.** The service is operated by a single principal with no employees, so this process is not yet in active use.

**Process for future employees.**

- **Joiner.** Provision named accounts on each system required for the role, with the minimum scope needed. Require MFA. Record the grant in the access register. Brief the new joiner on these policies.
- **Mover.** When a role changes, review and adjust access within 7 days. Remove access no longer needed.
- **Leaver.** Revoke all access within 24 hours of departure. Rotate any shared secrets the leaver had access to. Confirm with a follow-up audit.

**Trigger to activate.** First non-principal employee or contractor with any production access.

---

## 13. Anti-Malware and Application Controls

**Commitment.** Code execution on the service is constrained by application controls rather than by traditional anti-malware agents, which do not apply to the serverless architecture.

**Controls in place.**

- Vercel Fluid Compute functions run as ephemeral, isolated instances with no persistent filesystem.
- Code execution is restricted to immutable deployments built from version-controlled source.
- The application accepts no user file uploads.
- Dependency vulnerabilities are monitored continuously by GitHub Dependabot.
- Vercel performs infrastructure-level threat detection on its runtime and edge network.

---

## 14. Network Boundary

**Commitment.** The service's external network boundary is protected by intrusion detection and prevention controls.

**Controls in place.**

- The Vercel edge provides automatic DDoS mitigation.
- The Vercel Web Application Firewall applies managed rulesets and supports custom rules where needed.
- Vercel BotID filters malicious bot traffic.
- Rate limiting is applied at the edge before traffic reaches application functions.
- The Neon Postgres database is reached only via authenticated TLS connections initiated from Vercel Functions and is not directly exposed to the public internet.

---

## 15. Certifications and Attestations

**Current state.** SFMagic does not hold SOC 1, SOC 2, ISO 27001, or PCI DSS attestations. The service is too small and too young for those audits to be cost-justified.

**What we rely on.** The platforms below hold the relevant attestations and are the basis on which the service is built:

| Platform | Attestations |
| --- | --- |
| Vercel | SOC 2 Type II, ISO 27001, GDPR, CCPA |
| Neon | SOC 2 Type II, GDPR, HIPAA |
| Stripe | PCI DSS Level 1, SOC 1 Type II, SOC 2 Type II |
| Sentry | SOC 2 Type II, GDPR |
| Anthropic | SOC 2 Type II |
| Microsoft (Entra, Azure) | SOC 1/2/3, ISO 27001, FedRAMP, multiple |
| Salesforce | SOC 1/2/3, ISO 27001, PCI DSS |

**Trigger to pursue our own attestations.** Enterprise customers with contractual requirements, or annualized revenue justifying the audit cost.

---

## 16. Policy Review

This document is reviewed at minimum annually, and additionally whenever:

- A new sub-processor is added.
- A new component is added to the architecture.
- A security incident at SEV-2 or above occurs.
- A new employee or contractor is onboarded.
- A regulatory change affects an existing commitment.

Each review is recorded with a dated entry below.

| Date | Reviewer | Changes |
| --- | --- | --- |
| 2026-05-14 | Tim Cox | Initial publication |

---

## Contact

**Security disclosures:** tim@timcox.co
**General inquiries:** tim@timcox.co
**Customer-facing summary:** sfmagic.co/security
**Privacy policy:** sfmagic.co/privacy
