Gevell Security & Trust White Paper
Version 1.0 Β· September 2026
This document is layered. Part IβIX is the external white paper β suitable to share with prospective customers, procurement offices, and security reviewers. Part X (Internal Appendix) is candid current-state tracking for the engineering team and is not intended for external distribution; remove it before sending the file to a customer, or export Parts IβIX only.
Part I β Executive Summary
Gevell is a SaaS platform that converts and audits documents for accessibility β turning PDFs, Office files, web pages, and forms into WCAG 2.1 AA and PDF/UA-1 conforming outputs. Because our customers are frequently public universities, K-12 districts, and government agencies preparing for the ADA Title II compliance deadlines (April 2027 / April 2028), the documents they entrust to us often contain sensitive records governed by FERPA.
Security is therefore a product requirement, not an afterthought. This paper describes how Gevell protects customer data across its lifecycle: encryption in transit and at rest, least-privilege access, a US-only processing footprint, a short and disclosed subprocessor chain, and β because AI is central to our product β a dedicated program for AI data protection and responsible AI.
Security posture at a glance:
| Area | Posture |
|---|---|
| Data residency | United States only (no offshore processing) |
| Encryption | TLS 1.2+ in transit; AES-256 at rest on all stores |
| AI data handling | Zero Data Retention (ZDR) via AWS Bedrock β no model-provider retention, no training on customer data; we do not view customer documents |
| Authentication | Name/password, email magic link, and OTP; SSO (SAML) available; passwords hashed by the auth provider |
| Access control | Row-level security, role-gated admin, MFA on all provider accounts |
| Secure SDLC | 100% pull-request-reviewed, CI-gated (tests, accessibility, dependency audit) |
| Compliance | FERPA service-provider ready; HECVAT answer set maintained; SOC 2 not certified (compensating controls below) |
| Accessibility | WCAG 2.1 AA / PDF/UA-1 β the product itself is accessibility-audited in CI |
Gevell is a small, heavily automated team. We describe our posture plainly β including what we have not yet certified β because accuracy is the foundation of trust.
Part II β Company & Product Overview
- Product: Gevell β a family of document accessibility tools (Gevell PDF, Gevell Web, Gevell Audit, Gevell Report Card, Gevell Forms, and related apps) that convert and remediate documents to WCAG 2.1 AA and PDF/UA-1.
- Hosting model: Cloud-hosted SaaS (AWS, Cloudflare, Supabase) with one vendor-managed processing node for large chunked conversions.
- Customers: Higher education, K-12, state and local government, and enterprises with document accessibility obligations.
- Tagline: Every document deserves a twin.
Part III β Data Protection
III.1 Data we handle
| Class | Examples | Where it lives |
|---|---|---|
| Customer documents | Uploaded PDF/DOCX/PPTX/HTML and converted accessible outputs | Cloudflare R2 (primary store), AWS S3 (processing shim + malware-scan staging), processing host (transient) |
| Account data | Email, name, organization, auth identifiers | Supabase (PostgreSQL, AWS us-east-2) |
| Billing data | Payment method, invoices | Stripe (we store only Stripe customer/charge IDs) |
| Operational metadata | Job status, page counts, cost records, structured logs | Supabase; Loki logs (30-day retention) |
Customer documents are the sensitive class and may contain FERPA-covered student records. We do not solicit and do not knowingly process PHI; HIPAA is contractually out of scope and no BAA is executed.
III.2 Encryption
- In transit: TLS 1.2+ on every hop β browserβCloudflare, CloudflareβAWS, serviceβSupabase, and serviceβBedrock.
- At rest: Cloudflare R2, AWS S3, and Supabase all encrypt at rest with AES-256 using provider-managed keys.
III.3 Data flow
Browser (TLS 1.2+) β upload βΌCloudflare (Pages frontends, R2 object storage β SSE at rest) β signed transfer βΌUpload malware scan (AWS S3 staging + GuardDuty Malware Protection) β clean files admitted to primary store [primary PDF upload path] βΌAPI: AWS API Gateway β Lambda (us-east-1) ββ small / synchronous jobs Node processing host (Docker, private LAN, ββ large / chunked jobs outbound-only via Cloudflare Tunnel) β inference (document images / extracted text) βΌAWS Bedrock β Anthropic Claude (us-east-1, Zero Data Retention; no training on inputs, no provider retention of prompts/outputs) β results βΌAccessible output written back to R2 β customer download (TLS)Supporting paths carry pointers, not content: SQS queues carry job IDs and R2 keys; structured logs carry request IDs, user IDs, and durations β never document content. Admin alerting (Telegram/email) carries operational text only.
III.4 Upload malware scanning
On the primary document upload path, files are uploaded to an isolated AWS S3 staging bucket and scanned by Amazon GuardDuty Malware Protection before any conversion begins. Only files that return a clean result are copied to the primary object store and made available for processing; infected or unscannable files are rejected (fail-closed). The primary store is Cloudflare R2, which GuardDuty cannot scan directly, so the native-S3 staging bucket is where scanning happens by design. Staging objects are lifecycle-expired after one day.
This scan-on-upload path is live for the primary PDF conversion product and is being extended across the remaining product upload surfaces.
III.5 Data residency
All storage and processing is in the United States β AWS us-east-1/us-east-2, Cloudflare US-region R2, and Supabase us-east-2. There is no offshore processing.
III.6 Retention & deletion
- Documents: retained until the customer deletes the file or the account.
- Operational logs: 30 days.
- Backups: operational data 30 days (rolling); database backups provider-managed (daily).
- Deletion: account deletion cascades to Supabase rows and R2 objects, with an audited deletion trail. Customers can delete individual files at any time; deletion removes the stored original and its outputs.
Part IV β Access Control & Application Security
- Authentication: Supabase Auth supporting name/password credentials, email magic link, and 6-digit email OTP. Passwords are hashed by the auth provider β we never see plaintext. Because some university mail systems aggressively filter automated email and make magic-link/OTP delivery unreliable, password sign-in ensures dependable access where email delivery cannot be counted on. API access uses hashed API keys (SHA-256) with active/expiry enforcement.
- Single sign-on (SSO): SAML / institutional IdP sign-in is available for institutions that require it.
- Authorization: Row-level security (RLS) on customer tables in PostgreSQL; role-gated admin surfaces; API routes enforce per-user/tenant scoping at the boundary.
- Session management: Supabase JWT sessions with expiry and refresh.
- Input validation: All input validated at system boundaries; parameterized queries only β no string-concatenated SQL.
- Administrative access: Production access is limited to the operator, with MFA enforced on GitHub, AWS, Cloudflare, Supabase, and Stripe. No offshore staff and no contractors with production access.
Part V β Infrastructure & Operational Security
V.1 Infrastructure
- AWS us-east-1 β Lambda (API compute), SQS (job queues), S3 (processing + scan staging), Bedrock (AI inference).
- Cloudflare β Pages frontends, global CDN, US-region R2 object storage, and Cloudflare Tunnel for the processing host.
- Supabase us-east-2 β managed PostgreSQL and authentication.
- Processing node β one vendor-managed Docker host for large chunked conversions. It sits on a private network reachable only via an outbound-only Cloudflare Tunnel (no inbound ports), is disk-encrypted, and holds documents only transiently during processing.
Physical and lower-layer security for cloud infrastructure is inherited from AWS and Cloudflare, whose SOC 2 / ISO 27001 attestations are available from those providers.
V.2 Secure SDLC & change management
- Every production change ships as a reviewed GitHub pull request with CI gating merge β automated tests, an accessibility (WCAG) audit, and a dependency vulnerability audit must pass.
- Production deploys occur only from the
mainbranch. - Database schema changes are versioned migrations applied deliberately and monitored for drift against production; rollback is redeploy of the prior commit.
V.3 Monitoring, logging & alerting
- Structured logging (JSON) with request/user IDs, durations, and metadata β never document content β aggregated in Loki (30-day retention).
- Grafana alert rules for elevated error rate, fatal errors, and missing heartbeat; Uptime Kuma on production endpoints; spend-anomaly alerting.
- Alerts route to email and Telegram with a cooldown to prevent alert storms.
V.4 Vulnerability management
- Dependabot runs weekly across repositories;
npm auditruns in CI and in a nightly cron with emailed reports. - Critical/high findings are fixed or explicitly documented with justification β never silently ignored.
V.5 Business continuity & disaster recovery
- Database: provider daily backups.
- Object storage: R2 durability plus S3 copies during processing.
- Ops host: nightly encrypted backups to Backblaze B2 (30-day retention), with restores tested quarterly.
Part VI β AI Security & Responsible AI
AI is core to Gevell: Claude models (via AWS Bedrock) generate alt text, analyze document structure, grade WCAG conformance, and drive remediation. Because those models process customer document content, we run a dedicated AI security and responsible-AI program. This section reflects the outcome of a formal enterprise security assessment completed in September 2026.
VI.1 Zero Data Retention (ZDR)
All customer-document inference runs on AWS Bedrock under Zero Data Retention. Under ZDR, prompts and outputs are not retained by the model provider and are never used to train models. Inference is region-pinned to the United States (us-east-1).
ZDR is enforced in code through a single AI client factory that all services route through. When Bedrock credentials are unavailable, the factory logs a distinct fallback warning rather than silently degrading β making a misconfiguration observable rather than invisible. Following the September 2026 assessment, we closed a gap in which the Audit and Report Card processing paths were not passing Bedrock credentials, and a gap in which the API Lambda host was not forwarding its temporary AWS session token β both would have caused inference to fall back off the ZDR path. Coverage was then confirmed with a live production smoke test (a successful Bedrock call with no fallback warning). ZDR is now active across the PDF, Audit, and Report Card products.
VI.2 Responsible AI governance (NIST AI RMF)
Our AI program is mapped to the NIST AI Risk Management Framework across its four functions:
- GOVERN β a written AI Development Policy governs approved tools, permitted data, human review of AI-assisted development changes, traceability, and rollback for every production AI feature.
- MAP β an AI risk register identifies each AI feature, its data flow, and its foreseeable failure modes.
- MEASURE β bias and quality evaluations (below) and a prompt-injection red-team measure real behavior, not assumptions.
- MANAGE β a documented re-measurement cadence, monitoring, and the kill switch (below) keep risks controlled over time.
VI.3 Human oversight & kill switch
We do not view customer documents or their AI outputs. Results are generated and delivered directly to the customer, who reviews their own document; Gevell staff do not read customer content as part of normal operation. This is a deliberate privacy posture, not an oversight gap.
Human oversight instead applies to how AI features are built and shipped, not to individual customer outputs: AI-assisted code is reviewed like any other change, AI tooling cannot independently deploy to production, and every production AI feature is released only with a documented owner, evaluation, monitoring, and rollback path.
Operationally, every AI provider path has a kill switch: an admin control (backed by a persisted flag recording who disabled it, when, and why) and a provider-level environment master shutoff that can disable AI inference independently of the application database. A runbook documents the disable/resume procedure.
Customers can also opt out of AI processing entirely, at two scopes. Each
user has a disable_ai_services flag, and a tenant/institution admin (org owner
or admin) can set the same flag for the whole tenant, disabling AI for every
user in the institution in one place. The gate is enforced server-side: an
AI-dependent route is denied (HTTP 409 AI_DISABLED_BY_USER) when either the
tenant or the user has AI disabled β a tenant that disables AI cannot be
re-enabled upward by an individual user. When AI is off, image/PDF extraction is
unavailable: it does not silently degrade β the customer must build the chart
through the deterministic structured-import path (CSV/spreadsheet) or manual
wizard entry, neither of which sends any content to a model. (Note: AWS Textract
is not offered as an βAI-disabledβ fallback β it is still ML processing of
customer content and would undermine the flagβs promise.)
VI.4 Bias evaluation
We ran a structured, live bias evaluation of our AI features against a balanced image set (race Γ gender). The initial evaluation found that vision-generated alt text occasionally volunteered skin-tone or ethnicity descriptors in a skewed way. We remediated at the root (neutrality instructions in the prompts) with a backstop filter that strips skin-tone/ethnicity language from final alt text (carefully audited to avoid false positives such as βblack hairβ or βwhite backgroundβ), then re-ran the same evaluation and confirmed the skew dropped to zero. The WCAG pre-grader and multilingual (including right-to-left) paths were evaluated and showed no theme- or language-driven bias in scoring.
VI.5 Prompt-injection defense
Because we process untrusted document content, we treat prompt injection as a first-class threat. AI features that ingest customer text wrap it in explicit untrusted-content delimiters with input sanitization, and AI agents used internally are confined to read-only tools with path restrictions and argument-vector execution (no shell string interpolation). We conducted a code-grounded red-team of every AI feature; the one residual gap identified (a WCAG pre-grader path missing the delimiter wrapper) is tracked for remediation and is mitigated in the interim by the advisory-only nature of that output β it surfaces suggestions the customer reviews, not automated changes.
VI.6 PII handling
Gevell does not filter PII or PHI out of AI prompts, and does not offer a setting that claims to. A configurable text-scrubbing filter (AWS Comprehend) existed through 2026-09; it was withdrawn in #3463 and the customer-facing setting was removed with it.
It was withdrawn because its scope never matched its name. Presented in the UI as an account-level βAI data protectionβ level, it was wired into three of the productβs AI call paths:
| Path | Effect |
|---|---|
| PDFβHTML conversion cascade (the reflow lane) | Ineffective. This lane prompts the model with the page itself β PDF bytes, or a PNG rendered from it. The extracted text the filter cleaned is used for routing and coverage checks, not as the prompt. Redacting it left the page pixels, which is what the model reads. |
Text-only PDF structuring (unpdf-claude-converter) | Effective. Text-only prompt. |
| ACR / WCAG pre-grader | Effective. Text-only prompt built from data extracted off the rendered page. |
It was never wired into the preserve (tag-in-place) lane, nor into alt-text
suggestion, HTML remediation, or org-chart extraction β all of which receive the
same customer content. In production it was set to off for every user profile
and for the tenant, so no customer was relying on it.
Removing it gives up genuine redaction on the two text-only paths. We are recording that as an accepted loss rather than describing the change as costless. The judgment was that a control covering three paths out of the product, while presenting itself as an account-wide protection level, misinformed customers about their own exposure β and that correcting the scope claim was worth more than retaining redaction on two paths that no customer had enabled.
Customer content protection rests on the controls that hold across every path: zero data retention on the inference path, no training on customer content, tenant isolation, and the Disable AI services switch (settable per user and per tenant), which is the control that actually keeps content away from a model β some routes degrade to deterministic processing, others decline the operation outright.
Full analysis of what the filter covered:
docs/admin/ai/pii-filter-coverage.md.
Part VII β Compliance & Privacy
VII.1 FERPA
For documents containing student records, Gevell acts as a school official / service provider under the institutionβs direction: data is used only to provide the service, never for advertising, and never sold; deletion is honored on request; and subprocessors are bound accordingly. FERPA rider language is acceptable.
VII.2 HIPAA
Out of scope. The service is not offered for PHI, no BAA is executed, and contracts exclude PHI uploads.
VII.3 Higher-education & government assessments
- HECVAT β we maintain a complete, consistent HECVAT answer set and a data flow / subprocessor disclosure, available to any institution on request.
- TX-RAMP β not yet certified; the intended path is provisional certification sponsored by the contracting institution.
VII.4 Certifications & roadmap
- SOC 2 / ISO 27001 β not currently certified. Compensating evidence includes automated nightly security audits, CI dependency scanning, WCAG CI gates, and this documented control set.
- Penetration testing β a scoped external test of the customer-facing applications is planned and tracked; it can be prioritized at contract time.
- SSO (SAML / institutional IdP) β available today (see Β§IV).
We represent these accurately. Reviewers score honesty well, and we would rather disclose a roadmap item than overstate our posture.
Part VIII β Subprocessors
| Subprocessor | Purpose | Customer data received | Retention posture |
|---|---|---|---|
| Amazon Web Services | API compute, queues, S3, Bedrock inference, malware scanning | Documents (processing + inference) | Bedrock: ZDR; S3 lifecycle-managed |
| Cloudflare | Frontend hosting, CDN, R2 object storage, tunnel | Documents (storage), traffic metadata | Stored until customer deletes; SSE at rest |
| Supabase | PostgreSQL, authentication | Account data, job/document metadata | Daily backups; deleted on account deletion |
| Anthropic (via AWS Bedrock) | AI document analysis | Document page images / text during inference | ZDR β not retained, not used for training |
| Mathpix | OCR of math / scientific notation | Page images routed to math OCR only | Per Mathpix terms; only pages needing math OCR |
| Stripe | Payments | Billing data (card data never touches our systems) | Stripe-managed |
| Resend | Transactional email | Email address, message content (no documents) | Provider-managed |
| Twilio | Support line / voice OTP | Phone numbers, voicemail audio | Provider-managed |
| Backblaze B2 | Encrypted server backups (ops data β not customer documents) | None (operational data only) | 30-day rolling |
All storage and inference subprocessors operate in US regions. Legacy Google Gemini paths have been retired from customer-document processing in favor of Bedrock ZDR.
Part IX β Incident Response & Contact
- Detection: Grafana alerting (error rate, fatal errors, heartbeat), Uptime Kuma endpoint monitoring, and spend-anomaly alerts.
- Response: On a confirmed security incident we contain the affected system, preserve evidence, remediate, and notify affected customers. Our target customer-notification window for a confirmed data breach is 72 hours.
- AI incidents follow the same process, with the kill switch (Β§VI.3) available to immediately disable an affected AI feature or provider path.
- Reporting a concern: [email protected]
Part X β Internal Appendix (candid current state β remove before external distribution)
This section tracks known gaps honestly for the engineering team. It restates the
[GAP] items from hecvat-draft.md and the open items from the September 2026
security epic (#3022). Do not send Part X to a customer.
X.1 Known gaps (from HECVAT draft)
- Formal InfoSec policy PDF β controls are documented in-repo but not yet a standalone formal policy document. Generate before first formal submission.
- RTO/RPO figures β not yet written into
disaster-recovery.md; HECVAT asks for numbers. - Formal IR runbook β roles, severity levels, and notification timelines need to be formalized (the 72-hour figure in Β§IX is our stated target, not yet a tested runbook).
- SOC 2 / ISO 27001 β not certified; no roadmap letter β compensating controls only.
- Penetration test β none yet; scoped external test of the customer-facing apps is the cheapest satisfying evidence. Tracked: issue #3096.
- Processing node β the one non-cloud host is the item reviewers probe hardest; never represent the platform as βall cloud.β Migration to cloud compute is on the roadmap.
- Cyber-liability insurance certificate β have ready to attach.
- Confirm MFA actually enabled on every provider account before submitting.
X.2 Security epic #3022 β status (2026-09-14)
Closed: #3013 (Bedrock ZDR routing, live-verified), #3014 (full-monorepo ZDR audit), #3016 (bias eval), #3019 (upload malware scanning, live), #3021 (AI risk register), #3023 (AI kill switch), #3083 (Lambda session-token ZDR fix), plus #3066/#3068/#3080/#3086/#3087.
Open / follow-ups:
- #3015 β PII scrubber wiring. Closed as withdrawn (#3463): the control
was removed rather than completed, for the reason given in Β§VI.6. Remaining
cleanup (dropping the
ai_pii_filtercolumns and the Comprehend IAM grants and SDK dependencies) is tracked on #3463. - #3052 β opus-page-converter Files-API non-ZDR exception (accepted, admin-only, gated).
- #3088 β WCAG pre-grader (
wcag-ai-quality-checker.ts) inlines untrusted headings/body with no<untrusted_*>delimiter wrapper (unlike alt-text-suggester and ai-fix). Medium residual; mitigated by the advisory-only output (customer reviews suggestions; no automated changes). Fix = mirror thesanitizeUntrusted/delimiter pattern + add an injection test. This is the residual gap referenced in Β§VI.5. - #3090 β
tools/segment-clisends document content to direct, non-ZDR Anthropic (own SDK dep, no factory access). Internal CLI tool, not a customer-facing path, but should be moved onto the shared ZDR factory. - #3091 β permanent CDK enable of upload malware scanning (was live via manual Lambda env override; CDK flip ends drift).
- #3092 / #3093 / #3094 β #3019 hardening: server-side double-convert guard; GuardDuty per-GB scan cost β cost ledger; audit other appsβ upload surfaces (audit/remediate/forms/pro).
X.3 Loose finding (not yet filed)
quality-gate.ts:84logspreview="${textContent.slice(0,80)}β¦"β customer document text to stdout. Logging-exposure (out of the #3015 AI-ingestion scope) but worth closing: structured logs are supposed to carry metadata only, and Β§III.3 states logs never carry document content.
X.4 Source documents
docs/admin/security/data-flow-subprocessors.mddocs/admin/security/hecvat-draft.mddocs/admin/security/ferpa-subprocessor-compliance.mddocs/admin/security/data-privacy-implementation.mddocs/admin/ai/ai-development-policy.mddocs/admin/ai/nist-ai-rmf-alignment.mddocs/admin/ai/ai-risk-register.mddocs/admin/ai/bias-evaluation.mddocs/admin/ai/prompt-injection-redteam-2026-09-14.mddocs/admin/runbooks/ai-kill-switch.mddocs/admin/runbooks/malware-scanning-s3.md