Data Flow Diagrams β Gevell PDF
1. Data classification
| ID | Class | Examples | Sensitivity | Primary store |
|---|---|---|---|---|
| D1 | Customer documents | PDFs and Office files uploaded for conversion | High β may contain FERPA-covered records | Cloudflare R2 |
| D3 | Account & identity data | Email, name, organization, auth identifiers, tenant/team membership | Moderate | Supabase PostgreSQL |
| D4 | Billing & usage data | Entitlements, usage records, invoice references | Moderate | Supabase PostgreSQL |
| D5 | Derived analysis | Conformance results (PDF/UA, WCAG) and accessibility reports | Moderate (derived from D1) | Supabase + R2 |
| D6 | Operational metadata | Job status, page counts, cost records, structured logs | Low | Supabase, Amazon CloudWatch Logs |
The platform holds no payment instrument β institutional accounts are billed by invoice against recorded usage.
2. Trust boundaries
| # | Boundary | Crossing controls |
|---|---|---|
| TB-1 | Public internet β Cloudflare edge | TLS 1.2+, DDoS protection, and the Cloudflare Web Application Firewall (managed rule sets plus rate limiting) in front of the web applications and the primary API |
| TB-2 | Browser β object storage (direct upload/download) | Short-lived presigned URL, issued only after an authorization check, scoped to one object key and method |
| TB-3 | Edge β API (AWS) | TLS, origin authentication, request-scoped JWT or hashed API key. The serverless API (api-pdf.theaccessible.org) is reached directly at AWS API Gateway rather than through Cloudflare; it is protected by API Gateway request throttling and application-level rate limiting |
| TB-4 | API β data stores | Least-privilege credentials; PostgreSQL row-level security; parameterized queries only |
| TB-5 | API β processing tier | The processing host is one always-on AWS EC2 instance in us-east-1 (an Auto Scaling group of one across two Availability Zones) whose security group allows no inbound traffic; requests reach it only through an outbound-initiated Cloudflare Tunnel. It is administered only through AWS Systems Manager (no SSH, no key pair), requires IMDSv2, uses encrypted EBS disks, and loads its secrets from AWS SSM Parameter Store (KMS-encrypted SecureStrings) into memory at start |
| TB-6 | Queue β processing tier | Messages carry job IDs and object keys only β never document bytes |
| TB-7 | Platform β AI inference | TLS to AWS Bedrock in-region under Zero Data Retention; fails closed if a ZDR path is unavailable |
| TB-9 | Platform β subprocessors (email provider, customer storage integrations) | Scoped credentials; minimum necessary payload; disclosed in the subprocessor list |
| TB-10 | Operator β production | Multi-factor authentication is required on every administrative account for our infrastructure and service providers (AWS, Cloudflare, Supabase, GitHub, Google Workspace), with a move to phishing-resistant passkeys completing by Sep 30, 2026; access-gated admin surfaces; no contractor or offshore access; the processing host is administered only through AWS Systems Manager; AWS CloudTrail records account activity and AWS GuardDuty threat detection alerts the CTO |
3. Level 0 β Context diagram
flowchart LR accTitle: Context diagram for Gevell PDF accDescr: Customers submit documents and receive accessible outputs and conformance reports, while the platform exchanges data with inference, identity and email services. U["Customer user<br/>(institution staff)"] ADM["Gevell operator"] SYS["Gevell PDF"] AI["AWS Bedrock β Anthropic Claude<br/>(Zero Data Retention)"] MAIL["Resend (transactional email)"] IDP["Institutional IdP<br/>(SAML SSO / LTI)"]
U -->|"D1 documents Β· D3 account data"| SYS SYS -->|"accessible outputs Β· D5 conformance reports"| U SYS <-->|"D1 page images + text (inference only)"| AI SYS -->|"D3 addresses, notification text"| MAIL SYS <-->|"D3 assertions"| IDP ADM -->|"operational queries (D6)"| SYSDescription: customer users submit documents and account data, and receive accessible outputs and conformance reports. The platform exchanges page images and extracted text with AWS Bedrock for inference only, sends notification email through Resend, and federates identity with institutional identity providers. Operators see operational metadata.
4. Level 1 β Shared decomposition
flowchart TB accTitle: Level 1 decomposition of the shared platform accDescr: The edge serves the application shell, the API authenticates callers and creates jobs, queues feed the processing hosts, and results are written back to object storage and the database. U["Customer user"]
subgraph TB1["TB-1/TB-2 Β· Cloudflare edge (US)"] P1["P1 Β· Serve application shell<br/>pdf.gevell.com"] DS1[("DS1 Β· R2<br/>D1 documents Β· outputs")] DS2[("DS2 Β· KV<br/>sessions, file metadata, share tokens")] end
subgraph TB3["TB-3/TB-4 Β· Stateless API (AWS us-east-1)"] P2["P2 Β· Authenticate & authorize"] P3["P3 Β· Manage files & jobs"] P4["P4 Β· Meter usage"] DS3[("DS3 Β· PostgreSQL<br/>D3 Β· D4 Β· D5 Β· D6")] Q[("DS4 Β· Job queues<br/>pointers only")] end
subgraph TB5["TB-5/TB-6 Β· Processing tier (AWS EC2 us-east-1, no inbound access)"] P5["P5 Β· Render, extract & analyze<br/>PDF toolchain"] P6["P6 Β· Validate<br/>veraPDF Β· WCAG rule engine"] end
AI["AWS Bedrock (ZDR)"] IDP["Institutional IdP"]
U --> P1 --> P2 P2 <--> IDP P2 --> DS3 P2 --> DS2 U -->|"D1 direct upload via presigned URL"| DS1 P3 -->|mint presigned URL| U P3 --> DS3 P3 --> Q --> P5 P5 -->|read original| DS1 P5 -->|"D1 page images + text"| AI AI -->|proposals| P5 P5 --> P6 P6 -->|"outputs"| DS1 P6 -->|"D5 conformance results"| DS3 P4 --> DS3 DS1 -->|"outputs via presigned URL"| UDescription: the edge serves the application shell. The API authenticates users, records files and jobs in PostgreSQL, mints short-lived presigned URLs so document bytes move directly between the browser and object storage, and places job pointers on a queue. The processing tier renders and extracts content from uploaded documents, obtains proposals from Bedrock, validates deterministically, then writes outputs to object storage and conformance results to the database. Usage is metered from job records and invoiced from those records.
5. Level 2 β Gevell PDF (document conversion)
sequenceDiagram accTitle: Document conversion sequence accDescr: The browser requests a presigned URL and uploads bytes directly to a scan-staging bucket; only on a clean malware verdict is the file admitted, converted on a processing host, and its outputs written back to storage. autonumber participant B as Browser participant API as API participant S3 as S3 scan staging participant GD as GuardDuty Malware Protection participant R2 as R2 object store participant DB as PostgreSQL participant Q as Pipeline queue participant W as Processing host (EC2) participant AI as Bedrock (ZDR) participant V as veraPDF
B->>API: POST /api/files/upload (authenticated) API->>DB: create file record (metadata only) API-->>B: presigned PUT URL (single object, short TTL) B->>S3: upload document bytes directly (TLS) S3->>GD: scan on upload GD-->>S3: verdict Note over S3,R2: clean β admitted to primary store<br/>infected or unscannable β rejected (fail closed)<br/>staging objects lifecycle-expired after 1 day S3->>R2: admit clean object B->>API: POST /api/convert/{fileId}/estimate API-->>B: page count + cost estimate B->>API: POST /api/convert/{fileId} API->>DB: check entitlement and credit balance API->>Q: enqueue {jobId, objectKey} Q->>W: deliver job pointer W->>R2: GET original bytes W->>AI: page images + extracted text AI-->>W: reading order, structure, alt-text proposals W->>V: validate candidate tagged PDF (PDF/UA-1) V-->>W: conformance result W->>R2: PUT accessible HTML + tagged PDF + report W->>DB: job complete, page count, cost ledger entry B->>API: GET /api/files/{fileId}/status β complete API-->>B: presigned GET URLs for outputs B->>R2: download outputs (TLS)Description: the browser requests a presigned upload URL and uploads bytes directly to a scan-staging bucket; the file is admitted to the primary store only after a clean malware verdict. Conversion is requested separately, priced, checked against entitlements, and enqueued as a pointer. A processing host reads the original, obtains structural proposals from Bedrock, validates the candidate tagged PDF against PDF/UA-1 with veraPDF, writes outputs back to object storage, and records completion and cost. Outputs are retrieved through short-lived presigned download URLs.
What crosses each boundary:
| Hop | Payload | Class |
|---|---|---|
| Browser β staging bucket | Full document bytes | D1 |
| Staging β primary store | Full document bytes (clean only) | D1 |
| API β queue | Job ID, object key, user ID | D6 |
| Processing host β Bedrock | Page images, extracted text, system prompt | D1 |
| Processing host β PostgreSQL | Status, page count, cost, error text | D6 |
| Processing host β object store | Accessible HTML, tagged PDF, report | D1 / D5 |
| Logs & alerts (all hops) | Request ID, user ID, duration, status | D6 β never document content |
6. Authentication and session flow (both products)
flowchart TB accTitle: Authentication and session flow accDescr: Password, emailed link, one-time code and institutional identity provider paths all converge on an expiring JWT session scoped to a single user and tenant. U["User"] --> C{"Sign-in method"} C -->|password| A1["Auth provider verifies hash<br/>(plaintext never seen by Gevell)"] C -->|magic link / email OTP| A2["One-time link or code via Resend"] C -->|SAML SSO / LTI 1.3| A3["Institutional IdP assertion"] A1 --> S["Session: 15-minute access token<br/>ends after 1 h idle, 12 h maximum"] A2 --> S A3 --> S S --> RLS["Per-request tenant/user scoping at the API boundary<br/>+ PostgreSQL row-level security"] RLS --> DATA[("Only rows and objects owned by that user/tenant")] MK["Machine clients"] -->|"API key β SHA-256 hashed, expiry enforced"| RLSDescription: users authenticate by password, emailed link or one-time code, or an institutional identity provider; all paths converge on an expiring JWT session. Every request is scoped to the callerβs user and tenant at the API boundary and again by database row-level security. Machine clients use hashed, expiring API keys through the same authorization path. Access tokens last 15 minutes; a session ends after 1 hour of inactivity and expires 12 hours after sign-in regardless of activity. With SSO, the institutionβs identity-provider policies also apply.
7. Usage metering and invoicing flow
flowchart LR accTitle: Usage metering and invoicing flow accDescr: Every billable operation writes a cost-ledger record and decrements the account allowance; institutional accounts are invoiced against recorded usage rather than charged to a stored payment instrument. JOB["Completed conversion or parse"] --> LEDGER[("Cost ledger<br/>operation type, resource, cost, timestamp")] JOB --> ENT["Entitlement / allowance decrement"] ENT --> DB[("PostgreSQL")] LEDGER --> DB DB --> INV["Usage reports and invoices<br/>(billed to the institution on terms)"] LEDGER --> MON["Spend monitors & kill-switches"]Description: every billable operation writes a cost-ledger record and decrements the accountβs entitlement or allowance. Institutional accounts are invoiced against those recorded usage figures on agreed terms; the platform itself holds no payment instrument and performs no payment processing. The cost ledger also drives spend monitoring and automatic kill-switches.
8. Deletion flow
flowchart TB accTitle: Deletion flow accDescr: Deleting a file removes the original, every derived output, and the associated metadata and share tokens; account deletion cascades the same way. D1["Per-file delete"] --> R2X["Remove original and outputs from object storage"] D1 --> KVX["Remove file metadata and share tokens"] D2["Refund within refund window"] --> R2X D3["Account deletion request"] --> SOFT["Soft delete β sign-in disabled,<br/>30-day grace window, restore link emailed"] SOFT --> SWEEP["Scheduled hard-delete sweep"] SWEEP --> R2X SWEEP --> ANON["Anonymize account records"] R2X --> BK["No separate document backup;<br/>database backups roll off after 7 days"]Description: deleting a file removes the original, every derived output, and associated metadata and share tokens. Account deletion soft-deletes first β sign-in disabled, restore link issued, 30-day grace window β after which a scheduled sweep hard-deletes the accountβs stored objects and anonymizes its records. Documents have no separate backup copy; database backups are retained for 7 days and then age out.
9. Retention summary
| Data | Location | Retention |
|---|---|---|
| Uploaded originals and derived outputs | Object store | Until the customer deletes the file or account β no time-based auto-expiry |
| Scan-staging copies | S3 staging bucket | 1 day (lifecycle) |
| File metadata | KV | Lives with the file |
| Share-link tokens | KV | Until link TTL expiry |
| Sessions | KV | Ends after 1 hour of inactivity; expires 12 hours after sign-in regardless of activity |
| Job metadata | PostgreSQL | 13 months |
| Conformance results and reports | PostgreSQL | With the account (customer-deletable) |
| Request / usage logs | PostgreSQL (90 days) Β· Amazon CloudWatch Logs | Rolling |
| AI prompt & response records | PostgreSQL | 30 days |
| Billing and usage records | PostgreSQL | 7 years (statutory) |
| Database backups | Supabase-managed, encrypted | Daily; retained 7 days |
| Document backups | None kept separately | Cloudflare R2 is replicated for durability and encrypted at rest |
10. Flows that are explicitly not present
Stating the negatives is often what a reviewer actually needs:
- No document or page content in queues, logs, alerts, or analytics. These carry identifiers and metadata only.
- No model training on customer data. Inference runs under Zero Data Retention; where ZDR is unavailable the operation fails rather than falling back.
- No human review of customer documents by Gevell staff in the normal course of processing.
- No offshore processing or storage. All flows terminate in US regions.
- No payment processing in the platform. Invoiced accounts are billed from recorded usage; the platform holds no payment instrument.
- No inbound network path to the processing host. Its security group allows no inbound traffic; public traffic reaches it only through an outbound-initiated tunnel, and administration is only through AWS Systems Manager, with no SSH.
- No customer data on company premises. All processing and storage run in cloud services in US regions.
- No cross-tenant data path. Object keys are user-scoped and every read is mediated by an authorization check plus row-level security.