TheAccessibleOrgChart β Enterprise (working name): Zero-Knowledge Migration Design
Status: Draft for review
Author: (fill in)
Date: 2026-07-06
Related product: apps/org-chart (TheAccessibleOrgChart, orgchart.theaccessible.org)
Audience: Engineering + founders
1. Summary
We want a variant of the org chart product that can be sold into the federal government β DoD in particular β where the core selling point is that we never see, transit, or retain the customerβs data. The AI vision call moves to Amazon Bedrock in AWS GovCloud with a zero-data-retention (ZDR) posture, and everything else that touches customer PII (org chart image, extracted names/titles/emails/phones, rendered output) moves into the browser or into customer-controlled storage.
The expensive part of this work β a zero-knowledge AI path β is not org-chart-specific. It is the capability that unlocks all of the TheAccessible suite for DoD/gov. This doc therefore specifies it as a reusable platform capability (@accessible-org/zk-ai) with OrgChart-Enterprise as the first adopter, not as a one-off.
The headline finding from the code review: the Bedrock swap itself is small (a day or two in vision-extractor.ts). The real work is the persistence redesign β today the product writes full customer PII into Supabase and R2 in five different places. βNo access to their dataβ is primarily a data-storage problem, and only secondarily an AI-vendor problem.
2. Goals and non-goals
Goals
- Zero-knowledge posture: in the Enterprise edition, the customerβs org chart image and extracted PII never persist on Anglin AI infrastructure and, ideally, never transit it.
- Bedrock + ZDR + GovCloud: AI vision inference runs on Bedrock in AWS GovCloud (FedRAMP High / DoD IL-aligned) with no prompt/response retention.
- Reusable: the zero-knowledge AI path is a shared package the whole suite can adopt.
- Preserve the product experience: upload β extract β edit β choose template β export accessible HTML, with WCAG 2.1 AA output unchanged.
- Sellable compliance story: produce artifacts (data-flow attestation, architecture diagram) a federal 508 coordinator / ISSO can put in an ATO package.
Non-goals
- Not re-architecting the consumer/SaaS edition β it keeps its current server-side flow and hosted features.
- Not pursuing our own FedRAMP authorization in v1 β we inherit Bedrock GovCloudβs authorization boundary and keep our own footprint out of the data path.
- Not building customer-side SSO/CAC integration in v1 (flagged as a fast-follow).
3. Current architecture (where the data actually goes)
The live source is the main API worker, not the stale workers/org-chart-api/dist tree:
- Routes:
workers/api/src/routes/org-chart/* - Services:
workers/api/src/services/org-chart/* - Templates:
workers/api/src/templates/* - Shared types:
@org-chart/shared(packages/org-chart-shared) - Frontend:
apps/org-chartβ a static Next.js export (apps/org-chart/out/) that calls the worker viaNEXT_PUBLIC_API_URLwith a Supabase bearer token.
Current flow (consumer edition)
- Upload β browser posts the image; worker stores it in R2 as
source_image_r2_keyand records mime type onorg_charts. - Extract (
routes/org-chart/extract.ts) β worker fetches the image from R2, base64-encodes it, converts PDFβPNG if needed via the Cloudflare browser binding (storage.browser), then callsextractOrgChart()for both Gemini and Claude in parallel, scores them, and picks the better result.- Model calls live in
services/org-chart/vision-extractor.ts:extractWithClaudeβ@anthropic-ai/sdk, modelclaude-sonnet-4-6.extractWithGeminiβ@google/genai, modelgemini-2.0-flash(or Vertex whenUSE_VERTEX_AI=true).
- API keys are injected by
middleware/org-chart-storage-cf.tsviaextractApiKeys(env)(ANTHROPIC_API_KEY,GEMINI_API_KEY_PDF || GEMINI_API_KEY).
- Model calls live in
- Generate (
routes/org-chart/generate.ts) βgetTemplate(id).render(input)produces HTML;validateWCAG()(pure) plusrunAxeAudit(html, storage.browser)(needs the CF headless browser) validate it; output HTML + WCAG report are written to R2 and anorg_chart_outputsrow. - Finalize (
routes/org-chart/finalize.ts) β Stripe Checkout,FINALIZE_PRICE_CENTS = 3000($30) per chart; webhook setsfinalized_at+paid_until(1-year hosting window). Hosted sharing/embeds serve the stored output.
Where customer PII lives today (the problem)
| Sink | What lands there | File |
|---|---|---|
| R2 | Source image (the raw org chart) | extract.ts (source_image_r2_key) |
| R2 | Rendered accessible HTML + WCAG report | generate.ts |
Supabase org_chart_people | Full PII, one row per person (name, title, email, phone, employee_id, custom_fields) | extract.ts |
Supabase extraction_quality_metrics.extracted_data | The entire extracted org as JSON β written up to 3Γ (both models + winner) | extract.ts |
Supabase org_chart_versions.snapshot | Full snapshot of every person | extract.ts, versions route |
Supabase org_charts.extraction_raw_json | Raw model output | extract.ts |
Conclusion: today we have complete access to every customerβs org data. A Bedrock swap alone does not change that. The Enterprise edition must remove these sinks.
What is already portable (good news)
- Templates (
workers/api/src/templates/*) are pure functions:render(input: TemplateInput): TemplateOutputβ nofetch, noenv, no storage, no Supabase. They can run unchanged in the browser. - WCAG validator (
services/org-chart/wcag-validator.ts) is a pure function. - axe-core actually gets easier client-side: today it needs
storage.browser; in the browser it runs against the real DOM for free and the CF browser dependency disappears. - Extraction orchestration (dual-model compare/select, Zod schema,
parseAndValidate,validateExtraction,calculateQualityMetrics) is pure TS. - PDFβimage is the only browser-hostile step server-side (
storage.browser); replace withpdf.jsclient-side.
Roughly 70% of the pipeline is already pure code that can be lifted into the client bundle with little change.
4. Target architecture (zero-knowledge)
Core principle: plaintext customer data exists only in the customerβs browser and in the model providerβs ZDR inference boundary. It never lands on Anglin AI infrastructure.
βββββββββββββββββββββββββββββββββββββββββββ β Customer browser (Enterprise edition) β org chart image ββββΊ β β β 1. pdf.js: PDFβPNG (if needed) β β 2. extraction orchestration (pure TS) β β 3. template.render() (pure TS) β β 4. axe-core + WCAG validate (real DOM) β β 5. state in IndexedDB / encrypted exportβ βββββββββββββ¬ββββββββββββββββββββββ¬βββββββββ β (only the image) β (never leaves) short-lived β βΌ STS creds β local edit / export / (Cognito) β customer-owned bucket βΌ βββββββββββββββββββββββββββββββββββββββ β AWS GovCloud β β Bedrock InvokeModel (Claude) β β Zero data retention + guardrail β β (FedRAMP High / DoD IL boundary) β βββββββββββββββββββββββββββββββββββββββ
Anglin AI infrastructure: issues scoped STS creds + non-PII billing counters ONLY. Never receives the image or the extracted PII.4.1 Browser-resident processing
Move steps 1β5 above into the client bundle. The pure code (templates, validators, orchestration, Zod schema, quality metrics) moves into a shared client-safe package so both editions can import it. PDF conversion and axe-core get browser-native implementations.
4.2 Zero-Knowledge AI Gateway (the reusable capability)
Two routing options; the choice defines how strong the claim is.
Option A β Browser β Bedrock direct (true zero-access). Recommended.
- The browser obtains short-lived, tightly scoped STS credentials from an Amazon Cognito Identity Pool, authorized to call only
bedrock:InvokeModelon one model ARN in GovCloud. - The image goes browser β Bedrock GovCloud and never touches our servers.
- We cannot see the data even in transit. This is the only architecture that supports an honest βwe are technically incapable of accessing your dataβ statement to an ISSO.
- Trade-offs: we run a Cognito Identity Pool + IAM scoping; token metering shifts to client-side counters and/or CloudTrail rather than server-side logging.
Option B β Thin stateless proxy (fallback).
- Browser β our Worker β Bedrock, with no logging and no persistence.
- Simpler auth and metering, reuses existing key management β but plaintext transits our infra, so the claim weakens to βwe donβt retain it,β not βwe canβt see it.β Weaker for a federal buyer; keep as a fallback only.
ZDR specifics: Bedrock does not store prompts/outputs or use them for training by default. In GovCloud we additionally (a) pin to a GovCloud region, (b) attach a Bedrock Guardrail configured for no-logging, and (c) disable model-invocation logging. Document this as the ZDR attestation.
Model mapping (verified July 2026): Vision-capable Claude is available in Bedrock GovCloud at FedRAMP High / DoD IL4/5 β this gates the whole project green. Availability, per AWS/Anthropic:
- Initial GovCloud FedRAMP-High / IL4/5 approval (Jun 2025): Claude 3.5 Sonnet v1 and Claude 3 Haiku.
- Claude 3.7 Sonnet added to GovCloud (Jul 2025), same authorization.
- Claude Sonnet 4.5 now live in GovCloud US-West and US-East (default quotas raised to 5M TPM / 1,000 RPM in Feb 2026, matching commercial) β this is the current best target.
All of these are multimodal (image input); Anthropic explicitly markets Claudeβs vision on βcharts, graphs and technical diagramsβ β i.e. exactly org charts. So the Enterprise target model is Claude Sonnet 4.5 on Bedrock GovCloud, not the claude-sonnet-4-6 we use today on the Anthropic direct API (4.6 is not the GovCloud SKU β pin to 4.5 for the gov path and keep 4.6 on the consumer edition).
Bedrock has no Gemini, so the dual-model ensemble becomes either Claude-only or Claude Sonnet 4.5 + Amazon Nova to preserve the compare-and-select logic. Recommend launching Claude-only and adding Nova as the second scorer only if quality regresses.
GovCloud operational notes: (1) exact modelId must be confirmed in-console and will likely be a cross-region inference profile (GovCloud-prefixed) rather than a bare anthropic.claude-... ID; (2) model access in GovCloud is enabled via the associated standard (commercial) AWS account ID linked to the GovCloud account; (3) Guardrails, Agents, Knowledge Bases, and Model Evaluation are all available in GovCloud, so the no-logging ZDR guardrail in Β§4.2 is supported natively.
4.3 Persistence redesign (the real work)
Eliminate every PII sink from Β§3 for the Enterprise edition:
- No source image in R2 β the image stays in the browser; it is sent only to Bedrock.
- No
org_chart_people/extraction_quality_metrics.extracted_data/versions.snapshot/extraction_raw_jsonβ chart state lives in IndexedDB in the browser, with an optional encrypted export (customer holds the key) or write-through to a customer-owned bucket (their S3/GovCloud, their account). - Billing/usage β keep only non-PII counters (chart count, extraction count, timestamps, tenant id). No names, no contents.
- Quality metrics β either drop for Enterprise tenants or reduce to aggregate scores with no
extracted_data.
4.4 Reusable platform package
Create @accessible-org/zk-ai exporting: the Cognito/STS credential broker client, a invokeVisionModel() that targets Bedrock GovCloud, the ZDR/guardrail config, and typed request/response wrappers. OrgChart-Enterprise imports it; PDF/Web/Audit/Slides adopt it later with their own prompts. This is what makes the investment pay off across the suite rather than for one narrow product.
5. Migration plan (phased, file-by-file)
Phase 0 β Bedrock adapter spike (1β2 days)
- Add
extractWithBedrock(imageBase64, mimeType)toservices/org-chart/vision-extractor.tsusing@aws-sdk/client-bedrock-runtimeInvokeModelCommand. Reuse the existingSYSTEM_PROMPTandparseAndValidateverbatim. - Target Claude Sonnet 4.5 in GovCloud US-West/US-East; resolve the exact inference-profile
modelIdin-console (enable model access via the linked commercial account ID first). - Add
'bedrock-claude'to theVisionModeltype in@org-chart/sharedand to theswitchinextractOrgChart(). - Gate on env (
BEDROCK_REGION,BEDROCK_MODEL_ID). Prove parity against a handful ofTestFiles/org charts. - Deliverable: drop-in adapter, still server-side, proving Claude Sonnet 4.5 (Bedrock) output quality matches todayβs
claude-sonnet-4-6(Anthropic direct).
Phase 1 β Client-safe extraction/render/validate package (1β2 weeks)
- Create
packages/org-chart-client(or extend@org-chart/shared) and move, unchanged where possible:templates/*(render,buildTree, color utils) β pure.services/org-chart/wcag-validator.ts,extraction-validator.ts, the Zod schema +parseAndValidate+ quality metrics fromvision-extractor.ts.
- Replace server-only bits:
- PDFβPNG: new
pdf.jsimplementation (waspdf-converter.ts+storage.browser). - axe-core: run against live DOM in the browser (was
axe-validator.ts+storage.browser).
- PDFβPNG: new
- Frontend (
apps/org-chart) calls these locally instead of hitting/extractand/generate.
Phase 2 β Zero-Knowledge AI Gateway (2β3 weeks)
- Stand up Cognito Identity Pool (GovCloud) + IAM role scoped to
bedrock:InvokeModelon the single model ARN. - Build
@accessible-org/zk-ai: credential broker +invokeVisionModel()(Option A). Browser calls Bedrock directly. - Attach Bedrock Guardrail (no-logging) and disable invocation logging; script the ZDR config as IaC (
infra/). - Keep Option B proxy behind a flag for environments where direct calls are blocked.
Phase 3 β Persistence redesign (2β4 weeks, the critical path)
- New Enterprise data layer: IndexedDB store for chart/people/relationships/versions; encrypted export; optional customer-bucket write-through adapter.
- Strip all PII writes for Enterprise tenants: remove
org_chart_people,extracted_data,snapshot,extraction_raw_json, and R2 image/output storage from the Enterprise path. - Reduce Supabase to non-PII billing/usage rows (or a separate minimal schema for Enterprise tenants).
Phase 4 β Feature reconciliation (1β2 weeks)
- Hosted sharing / embeds /
paid_untilhosting window assume server-stored charts β replace with a customer-storage handoff or disable for Enterprise. - Billing: rework the
$30-at-finalizeflow (finalize.ts,FINALIZE_PRICE_CENTS) to a per-tenant/seat or per-chart-count model that reads only non-PII counters. (Federal buyers wonβt use consumer Stripe checkout anyway β see Β§7.) - Admin/analytics dashboards that read PII must be gated off for Enterprise tenants.
Phase 5 β Compliance artifacts (1 week)
- Data-flow diagram + written attestation (βdata never persists on vendor infra; inference in Bedrock GovCloud under ZDRβ).
- VPAT/ACR for the Enterprise UI itself (required to sell β the tool must be accessible).
- Draft answers for common ISSO/ATO questions (data residency, encryption in transit, credential lifetime, logging).
6. What breaks / decisions required
- Gemini is gone (no Bedrock equivalent). Decide: Claude-only vs. Claude + Nova ensemble.
- Hosted sharing/embeds conflict with zero-knowledge. Decide: drop for Enterprise, or customer-bucket hosting in their account.
- Editing/versions move to browser state. Decide: IndexedDB-only vs. encrypted export vs. customer bucket as source of truth.
- Billing model must stop depending on server-side data. Decide the Enterprise pricing unit (seat / tenant / chart volume).
- Auth: consumer uses Supabase auth. Enterprise likely needs the customerβs IdP (SAML/OIDC, eventually CAC/PIV). Decide v1 scope.
7. Effort estimate
| Phase | Scope | Rough effort |
|---|---|---|
| 0 | Bedrock adapter spike | 1β2 days |
| 1 | Client-safe render/validate/extract package | 1β2 weeks |
| 2 | Zero-knowledge AI gateway (Cognito + Bedrock GovCloud) | 2β3 weeks |
| 3 | Persistence redesign (critical path) | 2β4 weeks |
| 4 | Feature reconciliation (sharing/billing/admin) | 1β2 weeks |
| 5 | Compliance artifacts | 1 week |
Total: ~7β12 weeks of focused engineering for a single developer, dominated by Phase 3. The Bedrock swap people assume is the hard part is the smallest line item. Because @accessible-org/zk-ai is reusable, phases 0/2/5 are amortized across the whole suite.
8. Go-to-market (WOSB) and whether itβs worth it
The honest market read
- The mandate has teeth. DOJ oversees federal Section 508 compliance; agencies face civil penalties ($75K first / $150K repeat), active litigation (NFB v. SSA, plus DHS and Dept. of Education matters), and GSA publishes an annual governmentwide 508 assessment that keeps the failures visible. Org charts are a textbook 508 failure and DoD produces them at scale β often with names, titles, and chain-of-command that are sensitive/CUI, which is exactly why the zero-knowledge posture resonates.
- WOSB is a real but modest lever. FY24: WOSBs won ~$26.6B (3.44% of federal dollars), below the 5% statutory goal, and most of that came through full-and-open competition, not set-asides. The sole-source lane exists (up to $4.5M for services / $7M manufacturing) and is useful, but relatively few dollars flow through WOSB set-asides specifically. Treat WOSB as friction reduction and a tie-breaker, not a golden ticket.
- Org-chart-only is too narrow to be the whole business case. Agencies donβt budget for βaccessible org chartsβ; they budget for 508 remediation broadly. Competing accessible chart component libraries (Telerik, AG Charts, amCharts) mean a contractor could DIY. Our moat is specifically legacy-artifact conversion + zero-knowledge data posture + turnkey output.
Verdict
Worth building β but framed as a platform capability, not a standalone org-chart product. The zero-knowledge / Bedrock-GovCloud layer is what unlocks all DoD sales for the suite (PDF, Web, Audit, Slides all need the same βwe canβt see your data / FedRAMP-alignedβ story). Build it once, ship OrgChart-Enterprise as the flagship wedge, and land-and-expand into the higher-budget remediation products. As a standalone whose entire revenue case is federal org-chart sales, the TAM is likely too thin to justify the rebuild; as adopter #1 of a reusable gov-ready capability, the ROI is strong.
Sales motion
- Foundational (do regardless): active SAM.gov registration + UEI; NAICS (541511/541512/541519, 513210); WOSB/EDWOSB certification via SBA; capture SDVOSB/8(a)/HUBZone if any also apply.
- Credential the product: VPAT/ACR for the Enterprise UI (non-negotiable β you canβt sell an accessibility tool that isnβt itself accessible) + the zero-knowledge data-flow attestation.
- Land cheap: price a pilot under the $15K micro-purchase threshold so a contracting officer / 508 coordinator can buy directly. WOSB + micro-purchase is the lowest-friction first dollar.
- Target the champions: agency Section 508 program managers / coordinators (every agency has one) and DoD component CIO / accessibility offices. Respond to sources-sought/RFIs even with no dollar attached β thatβs how requirements get written.
- Vehicle for scale: pursue GSA MAS (~4β6 months) and, for DoD IT, SEWP / NITAAC; or sell through a reseller already on those vehicles initially.
- Consider SBIR/STTR: DoD runs the largest SBIR program in government β non-dilutive funding to build/prove exactly this, with a Phase III sole-source path.
- Expand: once inside on org charts, sell the broader 508 remediation products where the real budget sits.
9. Open questions / risks
Which exact Claude model IDs are available in Bedrock GovCloud, and is vision supported?Resolved (Jul 2026): vision-capable Claude is authorized in GovCloud at FedRAMP High / DoD IL4/5 β Claude 3.5 Sonnet v1, Claude 3 Haiku, Claude 3.7 Sonnet, and now Claude Sonnet 4.5 (US-West + US-East). All support image input. Target Sonnet 4.5; confirm the exact inference-profilemodelIdin-console. Green light for Phase 0.- Is direct browserβBedrock (Option A) acceptable to target agenciesβ browser/network policies, or will some require the Option B proxy inside their boundary?
- Do target agencies require the tool to run inside their own AWS/GovCloud tenancy (fully on-prem-to-them) rather than our Cognito pool? That would push toward a deployable/BYO-cloud packaging.
- CAC/PIV auth timeline β v1 IdP (SAML/OIDC) vs. fast-follow.
- Encrypted-export key management UX β who holds the key, recovery story.
Appendix A β Key files touched
workers/api/src/services/org-chart/vision-extractor.tsβ add Bedrock adapter; source of the model calls and system prompt.workers/api/src/routes/org-chart/extract.tsβ the orchestration + all PII writes to remove for Enterprise.workers/api/src/routes/org-chart/generate.tsβ template render + WCAG/axe + R2/org_chart_outputswrites.workers/api/src/routes/org-chart/finalize.tsβ$30Stripe flow to rework.workers/api/src/templates/*β pure renderers to lift into the client bundle.workers/api/src/services/org-chart/{wcag-validator,extraction-validator,pdf-converter,axe-validator}.tsβ port/replace for browser.packages/org-chart-sharedβVisionModeltype + shared schema.apps/org-chartβ static frontend that hosts the new client-side pipeline.- New:
packages/org-chart-client,@accessible-org/zk-ai,infra/GovCloud + Cognito IaC.