Appearance
Heritage Community Hub — Platform Strategy ​
Status: THE single canonical plan. This is the one source of truth for Heritage Community Hub — vision, architecture, scope, decisions, delivery order, and every request/change. There are no side plan documents; all planning lives here and is mirrored as work items in Azure DevOps Boards (Epic → Feature → User Story → Task), linked via
AB#.This is a planning & foundation document. No code, infrastructure, or pipelines are built from this document. All implementation is tracked as ADO work items and executed in later delivery phases — never directly from this file.
Phase 0 (Decide) is complete — the core stack is locked in ADRs 0001-0007 (
docs/internal/adr/). Active changes and things still to discuss are tracked in Open questions / decisions to discuss.Change log (requests captured here):
- 2026-06-22 — Platform-foundation UI view inventory. ~35 canonical views enumerated across desktop/tablet/phone viewports. ADR 0033 (view inventory) authored; ADR 0032 (member-detail) revised to Manage-button + kid-birthday-only model; ADR 0031 responsive values (1024 / sidebar 220px / 860px) ratified. Design doc
platform-ui-view-inventory.mdadded. DesignSync card naming convention locked. Export-to-Excel added to roadmap (Priority 4). Profile cleanup: remove "Bible Study" and "Homeschool Co-op" feature tags fromprofile.html. ADR README index updated through 0033. ADO: one Feature + ~34 User Stories to create under AB#3074 (execution follows approval of this plan).- 2026-06-17 — Revised delivery priority: Platform → iOS app → Sermons/Music Hub → Calendar & Announcements → Messaging → Android app → everything else. See Delivery roadmap.
- 2026-06-17 — Platform scope expanded to own all RBAC, member features, signups, and the family portal. See Platform scope.
- 2026-06-17 — New Sermons & Music Hub (sermons/video/music, inexpensive storage, web + mobile streaming, mobile offline download). Member-posted photo media is a separate, back-burner feature.
- 2026-06-17 — New requests, approach still to discuss: a detailed platform ADR + one ADR per feature; a member-facing roadmap + changelog driven by ADO (in-app after sign-in); no public landing page.
- 2026-06-17 — Ran a repository/docs best-practices research pass; recommended target structure + tooling (pnpm + Turborepo, Diátaxis docs by audience, mockups in
packages/ui+Storybook) captured in Repository structure; decisions 5-10 open.- 2026-06-17 — Mockups to be rebuilt in the decided web stack (React in
packages/ui+ Storybook), replacing the oldmockups/HTML. Tracked in ADO as AB#3160.- 2026-06-17 — Cost constraint (governing): free/cheap until Microsoft nonprofit status, then free/cheap under Azure where possible. See Cloud architecture.
- 2026-06-17 — Documentation model clarified: two buckets — internal repo docs (not public) and member-facing in-app docs (incl. roadmap/changelog), shown in the app after sign-in. No public docs tier (closed community). See Documentation model.
- 2026-06-17 — Structure decisions 5-10 resolved: Turborepo, pnpm (npm fallback), feature-folders- in-app first, two-bucket docs, mockups in
packages/ui.- 2026-06-17 — Moved forward on decided items: added the pnpm + Turborepo skeleton config (
pnpm-workspace.yaml,turbo.json,.npmrc, updatedpackage.json); authored ADR 0008 — Platform composition (AB#3155); removed the stray{{REPO_ROOT}}junk folder.- 2026-06-17 — Docs reconciled to the two-bucket model (decisions 9 & 10):
docs/reorganized intodocs/internal/(Diátaxis:adr,reference,explanation,how-to,tutorials,operations) +docs/member/; ADRs moved todocs/internal/adr/; oldmockups/retired todocs/archive/mockups/(React rebuild = AB#3160). All cross-references updated.- 2026-06-17 — Last four open questions resolved (1–4): MVP = platform-first; roadmap/changelog mechanism is build-time detail (AB#3159 — in-app after sign-in); domain heritageva.app in Cloudflare, DNS wired at deploy time; "Messaging" = one-way broadcasts + notifications, no chat.
- 2026-06-18 — Per-feature ADRs 0009-0020 authored and Accepted: iOS, Sermons & Music Hub, Calendar, Announcements, Messaging & Notifications, Android, Homeschool, Marketplace, Small Groups, and the three Signature features. Plus schema reconciled to ADR 0007, API contracts (
docs/internal/design/api-contracts.md) and security HIGH-item designs (docs/internal/design/security-high-items-design.md) authored. Child credentials decided: stored in the platformUserstable (not Clerk), hashed with Argon2id, verified server-side (ADR 0003).- 2026-06-18 — Admin/portal & portability ADRs 0021-0024 authored and Accepted: ADR 0021 Admin & Ministry Portal, ADR 0022 Family Portal, ADR 0023 Communications authoring & approval workflow (adds 6th RBAC role
comms_author, drafts-only), ADR 0024 Cloud portability & provider abstraction (DB = Postgres; compute = Azure Container Apps). Infrastructure "admin" is Plane-1 RBAC via Azure/Entra/GitHub — no custom page.- 2026-06-18 — Communications subsystem = three layers: 0023 governance (who authors + draft→queue→ approve), 0012 content (the Announcement = the single one-way broadcast type), 0013 transport (delivery channels only; the separate "messaging content" concept is dropped/unified into Announcements).
- 2026-06-18 — Multi-channel delivery + required phone (NEW): member profiles require a phone number (adults) and carry email; every approved announcement/notification fans out across SMS text + app push (if installed) + email. SMS is now in-scope (no longer deferred) → pick an SMS provider (rec: Azure Communication Services); SMS is per-message paid — flagged against the free/cheap constraint (updates security-audit S4). Touches ADR 0013, ADR 0007 (
Users.Phonerequired), and the schema.- 2026-06-18 — Portability posture = portable-by-design: abstract the four lock-in primitives (compute/DB/storage/secrets), containerize, prefer portable building blocks — Azure now, but a move to AWS/GCP/self-host stays an adapter swap. New ADR 0024 (Cloud portability & provider abstraction) to be authored; reopens the ADR 0004 database choice (Azure SQL → consider Postgres for portability).
- 2026-06-18 — Media storage (ADR 0010) = storage abstraction + cheap S3-compatible: a signed-URL
StorageProviderinterface; evaluate Cloudflare R2 (zero egress) / B2 / Cloudflare Stream (video) vs Azure Blob; YouTube/Vimeo only as a managed-video fallback. Member-only gating preserved via the API.- 2026-06-18 — Calendar (ADR 0011) sync: add a tokenized read-only ICS subscription feed (RBAC- filtered; subscribe in iCloud/Google/Outlook) + per-event "add to calendar"
.ics. Two-way sync out of scope.- 2026-06-18 — Build-ready documentation pipeline (governing order): ADRs → design/architecture/build docs → implementation docs → operations guides → then ready to build & test. Each layer gates the next.
- 2026-06-18 — Dev-environment rule: the application is never built on the working VM — builds run in WSL or a separate dev box (keep this VM clean). Planning/docs only on the VM.
- 2026-06-18 — Homeschool portal = two tiers (ADR 0015): (1) an all-ages Resource & Support Library (links, unit studies, convictions, downloadable end-of-year evaluations) and (2) a dedicated High School Program (classes, assignments, class calendar, teacher back-end: collaboration/gradebook/notes). Tier 2 is LMS-like and deferred for deeper design.
- 2026-06-18 — Process — per-feature deep dives are just-in-time: each feature's detailed design happens in its own phase (Layer 2/3 docs, in delivery order), NOT all up front. The ADR layer locks the decision + flags only what the platform/schema must reserve now (foundation-first / no-surprises). Far-off features (signature features, the HS LMS tier) get the ADR-level decision now and the deep design later.
Decisions resolved 2026-06-18: the 6th RBAC role (
comms_author, drafts-only — ADR 0023 Accepted), the SMS provider (Twilio, provider-neutral adapter, not Azure-locked ACS — ADR 0013 Accepted, S4 closed), and the database (Postgres on Azure DB for PostgreSQL Flexible Server, portable — ADR 0024 Accepted, supersedes ADR 0004's Azure SQL + Functions). ADR decision layer now CLOSED — all ADRs 0001-0024 Accepted (owner accepted the remaining feature/portal ADRs 0009-0012, 0014-0022 on 2026-06-18).ADO board reconciled 2026-06-18 (board now tracks everything): updated DB→Postgres (AB#3107/3108), compute→ Container Apps (AB#3103/3105), RBAC five→six roles (AB#3087); added provider-abstraction Feature AB#3162, Admin & Ministry Portal AB#3166, and stories for comms_author (AB#3168), Twilio SMS/SendGrid/A2P-10DLC (AB#3169-3171), Announcements author→approve workflow (AB#3172), Calendar ICS (AB#3173), Homeschool Tier 1/2 (AB#3174-3175); ADR Epic AB#3154 + stories closed.
Foundation documentation pipeline now tracked in ADO with sprints (2026-06-18), per the work-items standard: new Epic AB#3177 "Author build-ready foundation documentation" with a Feature per layer — design AB#3178 (S1), architecture AB#3179 (S2), build AB#3180 (S2), implementation AB#3181 (S3), operations AB#3182 (S4) — and 14 child Stories AB#3183-3196 assigned across sprints 2026-Q3-S1..S4. All items use controlled-vocabulary tags,
\Platform/\Homeschoolarea paths, and ≥3 acceptance criteria; the freeform tags on AB#3162-3176 were corrected. Next: author the docs, sprint by sprint, starting with the S1 design docs (data model, API, auth/RBAC).
- 2026-06-18 — Platform-strategy reconciliation (AB#3200): all stale "Proposed" ADR references updated to Accepted; Decisions locked section updated for ADR 0024 (Postgres + Container Apps supersede ADR 0004 Azure SQL + Functions); RBAC role count corrected to six throughout; S4 security item marked closed (Twilio + SendGrid decided); cloud architecture table corrected; Phase 0 status updated to reflect all 24 ADRs Accepted; landing-site section "TO DISCUSS" label removed (all items resolved); ADR plan section reflects completed/Accepted state.
- 2026-06-18 — Docs folder reorg (reverses the Diátaxis layout; see ADR 0001 update): renamed the
docs/internal/folders from the Diátaxis quadrants (explanation/,reference/,how-to/,tutorials/) to self-evident, doc-type names —design/,architecture/,build/,implementation/,operations/,overview/(plusadr/). 21 docs + the architecture diagram moved viagit mv(history preserved); all cross-references updated. Commit1554ff5.
End-game goal ​
One faith-centered community platform for Heritage Virginia, delivered on three surfaces from one codebase:
- A web application (responsive — desktop + mobile browser).
- A native iOS app (Apple App Store).
- A native Android app (Google Play Store).
All three are clients of one backend. Build a feature once on the platform; it appears on every surface. The work is organized in three conceptual layers: Platform (the core), Mobile apps (iOS + Android), and Features (the capabilities the platform provides).
Web-app-first, progressive feature enablement, and cross-platform delivery ​
These three decisions govern how the platform is built and how features reach users. They are locked in ADRs 0030 and 0031 and apply from the first delivery commit onward.
Web-app-first ​
The web application (apps/web, React + Vite + PWA) at heritageva.app is the primary, verified delivery surface. It is the first usable client and the surface against which features are validated before any mobile release. The web app opens to sign-in / register — it is not a public site. See ADR 0027 and ADR 0031.
PWA as cross-platform path. The same React codebase is installable as a Progressive Web App to iOS and Android home screens, providing a cross-platform experience without a separate native release pipeline. This is the verified cross-platform path during the Platform and early feature phases.
React Native (apps/mobile) is the eventual native App Store / Play Store surface (ADR 0002, 0009, 0014). Its fidelity through the design pipeline is deferred to the iOS delivery phase (AB#3077).
Progressive feature enablement (ADR 0030, AB#3692) ​
Features are dark until onboarded. A feature's navigation entries, icons, routes, and settings panels appear in the UI only after:
- Its API endpoints pass acceptance tests.
- Its UI components are built from
@hch/ui. - Its entry has been added to the feature registry in
packages/shared-configwithenabled: true. - Its ADO story acceptance criteria have been verified.
Before that point, the feature shows nothing — no placeholder, no "coming soon" entry. The core navigation shell (bottom tab bar, primary web nav, account/profile, notifications) is always present and is not registry-gated.
The feature registry is served by the API (GET /config/features) with RBAC role filtering applied server-side. Web and mobile surfaces consume the same endpoint; there are no per-client nav config files. See ADR 0030.
Code-first design, mirrored to Claude Design (ADR 0031) ​
UI components and design tokens are built in packages/ui/src/ first, authored to the canonical spec in docs/internal/design/claude-design.md §4. The Claude Design project (ceb2fb20-8346-4a74-8683-a96e4663b525) receives @dsCard HTML mockups mirrored from real components via /design-sync — it is a communication and validation tool, not the originating source of UI work. Handoff output is treated as scaffold and is reviewed before merging.
The @hch/ui import rule (ADR 0027) is unchanged: every page and component in apps/web and apps/mobile imports from @hch/ui only.
Guiding principles — NO SURPRISES ​
The foundation, organization, and platform are paramount. These gates are non-negotiable:
- Decide before building. Every architectural/tool choice is locked in an ADR before code depends on it. No guessing, no hard-coding an unvetted choice.
- Foundation-first. The platform core (API + auth + Account/Family-Group + RBAC + observability) and infrastructure come before features.
- De-risk on paper, not in code. Integration risks and unknowns are surfaced and resolved in ADRs and design notes during the decide phase — not by writing throwaway proof-of-concept code.
- Phase gates. Each phase has an explicit definition of done; do not advance until it's met.
- Everything as code + documented. Bicep IaC (no click-ops), ADRs as the single source of architectural truth, ADO for work tracking, documented free-tier ceilings + budget alerts, security audited up front.
- Honest trade-offs, early. Risks and unknowns are surfaced explicitly as they appear.
Architecture — API-first / headless platform ​
The make-or-break principle: all business logic, data, auth, and rules live behind a single backend API. Web and mobile contain only presentation + client state. This is what makes web + 2 apps roughly 1.3× effort instead of 3×.
Layer 1 — Platform (the core) ​
- Backend API — single source of truth (REST or GraphQL). All features are API endpoints. (
apps/api) - Web app — React + Vite + TypeScript; installable PWA; hosted at heritageva.app. First usable client, part of Platform Epic AB#3074. (
apps/web) - Shared packages consumed by every surface:
packages/shared-types— domain types / API contracts (one definition, used everywhere).packages/api-client— typed SDK wrapping the API, so web and mobile call the platform identically.packages/shared-utils— validation, formatting, RBAC helpers.packages/shared-config— shared config/constants.packages/ui— design tokens / shared design system.
- Database — relational store; schema drafted in
database/schema.sql(a design doc, not the live DB — the live store will be a managed cloud service). - Auth — token-based (OAuth2/OIDC) so the same identity works across web + both apps.
Layer 2 — Mobile apps (iOS + Android) ​
- Decided: React Native + Expo — one TypeScript codebase ships both iOS and Android and reuses
shared-types+api-client+shared-utils. (apps/mobile) - Mobile-specific needs: push notifications (APNs/FCM), offline cache/sync, App Store + Play Store release pipelines (EAS Build) — the one genuinely separate deploy cadence.
Layer 3 — Features ​
Each feature is a platform capability (API + data + rules) surfaced in web and mobile UIs. See the Feature inventory.
Structure — ONE monorepo, logically decomposed (DECIDED) ​
A monorepo is one Git repo holding many independently bounded workspaces. Separation happens on two axes: Axis 1 — Surfaces (apps/api, apps/web, apps/mobile) and Axis 2 — Features (features/<name>/ vertical slices that repeat inside each surface, stitched by shared types).
heritage-community-hub/ # ONE git repo
├── apps/ # SURFACES — deployable applications
│ ├── api/ src/features/{calendar,messaging,…} # all logic → containerized API (Azure Container Apps)
│ ├── web/ src/features/{calendar,messaging,…} # React + Vite PWA → Azure SWA (heritageva.app)
│ └── mobile/src/features/{calendar,messaging,…} # React Native (Expo) → App Store (AB#3077) / Play Store (AB#3139)
├── packages/ # SHARED CODE — imported by apps, not deployed alone
│ ├── shared-types/ api-client/ shared-utils/ shared-config/ ui/
├── infrastructure/ # IaC (Bicep)
├── database/ # schema, migrations, seeds
└── docs/ # architecture, decisions (adr/), guidesNote:
apps/*andpackages/*are planned, not yet created. Thepackage.jsonworkspace scripts therefore have no targets today. They are scaffolded in Phase 1.
Revisit multi-repo only at 10+ devs / divergent stacks. The one defensible split — mobile's separate release cadence — is handled by a separate pipeline, not a separate repo.
Feature inventory ​
Cross-cutting platform foundation ​
- Authentication & Identity — invitation-code registration, multi-step approval workflow, MFA, token-based auth across web + mobile.
- Role-Based Access Control (RBAC) — Community Leader / Ministry Leader / Small Group Leader / Member / Visitor, with per-feature visibility levels.
- Audit logging — security/compliance trail.
- Notifications service — email + SMS + in-app + mobile push, with priority levels.
Main Community Hub ​
- Sermons & Music Hub (NEW — priority 3) — post weekly sermons (video), videos, and music (audio); inexpensive Blob storage; web streaming; mobile streaming and offline download; member-only via RBAC; all original community content, no DRM. (Distinct from member-posted media.)
- Community Calendar System (PRIMARY engagement driver) — events, RSVP, attendance/check-in, multi-view, recurring, visibility by role/group.
- Communication / Messaging — one-way broadcast announcements + the notifications service (email/SMS/in-app/push).
- Small Groups & Ministries Management.
- Resource Management.
- Member-posted media (BACK BURNER) — members post photos of events, weddings, engagements. Separate from the Sermons & Music Hub; deferred.
Homeschool Education Portal — two tiers ​
- Tier 1 — Homeschool Resource & Support Library (all families, all ages): a resource/support library — recommended-resource links, unit studies, the community's homeschool convictions/philosophy, and downloadable community-specific end-of-year evaluations + required forms. Browse/download; not assignments or grades. Ships earlier (lightweight).
- Tier 2 — High School Program (dedicated): the high-school classes the community offers — homework assignments, class events, class times/calendar — plus a teacher back-end (collaboration, gradebook, notes). LMS-like; needs deeper design as its phase approaches (teacher role, gradebook, enrollment).
- Parent-managed student accounts (COPPA-compliant; no self-registration). See ADR 0015.
Community Marketplace ​
- Member-only classifieds, vendor/business listings, browse/reviews (listings only — no transactions).
Signature / future ​
- Pony Express Delivery Network, Community Ride Share & Travel, Sister Community Integration, Community Learning Platform, Community Wellness & Support.
Account & Family-Group model (closed community) ​
This is a closed, member-only community — "a family, not just a church." Minister/Admin approval gates everything. No public access (a future public marketplace is the only open question).
- Account types: Member (adult), Spouse (adult), Child (sub-account), plus leadership (Minister/Admin/Approver).
- Approval flow: request access → minister verifies & approves → creates member + their Family Group → member adds spouse (separate approval) → member adds children as sub-accounts.
- Children: no email, do not log in via email/social — a parent-managed credential (username + PIN/password). Scoped to homeschool/allowed sections only.
- Schema changes needed:
Users.Email→ nullable (children have no email); extendApprovalWorkflowto gate spouse-add and content; add an Announcements table (one-way broadcast, no replies).
→ ADR: Account & Family-Group Identity + Approval Workflow.
Messaging = one-way broadcast (not chat) ​
An approver authors and approves a message; recipients cannot reply. No user-to-user threads. This collapses content moderation into the existing approval workflow.
Authentication — end users ​
End users sign in with Apple (iCloud) + Google social login. No Entra for end users (Entra stays for infrastructure identity only). The platform keeps its own Users record keyed to the provider sub claim. Sign in with Apple requires an Apple Developer account ($99/yr, needed for the App Store anyway). Provider: Clerk (locked — ADR 0003).
Cloud architecture (free / low-cost Azure to start) ​
Cost constraint (governing — applies to every tech/hosting choice): until Microsoft nonprofit status is granted, use cheap or free solutions (Azure preferred, but cost wins). After nonprofit status, still cheap or free, but under the Azure umbrella where possible. Every new service choice must be checked against its free-tier fit.
Start on free/serverless tiers; scale up once Microsoft Nonprofits Azure credits (~$3,500/yr) are approved. API-first means clients don't care which tier the backend runs on.
| Platform need | Free / low-cost start | Notes |
|---|---|---|
Web app (apps/web) — installable PWA | Azure Static Web Apps (Free) — custom domain heritageva.app | Opens to sign-in/register; no public site; stapp-heritageva-prod-<region> |
| API / compute | Azure Container Apps (containerized Node.js API) | ADR 0024; portable to any container host; ca-heritageva-api-prod-<region> |
| Database | Azure Database for PostgreSQL Flexible Server | ADR 0024; connection-string portable to AWS RDS / GCP / Supabase; psql-heritageva-prod-<region> |
| File / media storage | Blob Storage / Cloudflare R2 | pennies at small scale; zero egress on R2 |
| Secrets | Key Vault (kv-heritageva-prod-<region>) | In HCS tenant; dedicated heritageva-branded KV |
Documentation model (revised 2026-06-17) ​
This is a closed, member-only community — nothing is public. Documentation falls into two buckets:
| Bucket | What | Audience | Where it lives / is served |
|---|---|---|---|
| Internal / repo docs (NOT public) | ADRs, architecture & design, implementation, operational/runbooks, PM | the team only | in the repo: docs/internal/ (+ pmo/); never exposed to members or the public |
| In-app docs (member-facing) | how-to-use / support / about content and the roadmap + changelog | signed-in members | authored in the repo, delivered inside the web + mobile apps (e.g. About/Support menu) after sign-in — not a public site |
- The roadmap and changelog are member-facing, shown in the app after sign-in (their permanent home), not a public web page.
- There is no "public" docs tier. Repo
docs/is internal-only; member content is authored in the repo but served in-app behind auth.
Observability — monitoring, alerting, logging ​
Four layers ("who logged in, where, how long" = layers 1 + 2):
- App audit/activity log — the existing
AuditLogtable; extend to track login→logout for session duration. - App telemetry — Application Insights SDK in web + API + mobile (~5GB/mo free).
- Infra monitoring + alerts — Azure Monitor + Log Analytics + action groups (~5GB/mo free).
- Auth-provider logs — provider dashboard (if chosen).
If the stack goes non-Azure, telemetry shifts to an OSS equivalent (OpenTelemetry + Grafana, Sentry).
Application RBAC — two planes ​
- Plane 1 — Infrastructure access RBAC (operators/devs touching Azure/GitHub/ADO/KV): Azure RBAC
- Entra roles + managed identities, least-privilege. Governed by platform standards. The only place Entra is used.
- Plane 2 — Application authorization RBAC (community members): scoped in
database/schema.sqlanddocs/internal/overview/ministry-leadership-overview.md. Enforced server-side in the API — clients never self-authorize. - Reconcile: schema.sql has 4 permission levels; README lists 5 Main-Hub roles. The ADR settles one canonical model + permission matrix + how a social-login subject maps to an app user + role(s).
Security audit (CAF / WAF) — gaps to close ​
Re-graded for the closed community (no health/financial data, member-only, minister-approves-everything, one-way messaging, kids = parent-managed sub-accounts). Honest verdict: architecturally sound but not yet build-ready until the HIGH items below are designed.
- S1 (HIGH) Data protection & COPPA — data classification, encryption-at-rest statement, TLS everywhere, retention/deletion, verifiable-parental-consent flow.
- S2 (HIGH) Trust & physical safety — Pony Express / Ride Share / in-person events: identity verification, report/block, liability/waiver. (Largely mitigated by closed vetted membership; re-opens if the marketplace goes public.)
- S3 (HIGH) Content moderation — collapses into the approval workflow (no user replies).
- S4 (MED) — CLOSED. Notifications providers decided: Twilio (SMS, provider-neutral adapter) + SendGrid (email). ADR 0013 Accepted; ACS not used.
- S5 (MED) Mobile client secrets — OAuth PKCE + secure storage + backend-for-frontend; clients hold short-lived tokens only.
- S6 (MED) API security baseline (OWASP) — server-side validation, rate limiting, CORS, CSRF, output encoding.
- S7 (MED) Vulnerability management — Snyk (present) + Dependabot + CodeQL + secret scanning.
- S8 (LOW/MED) Privacy & legal — Privacy Policy, ToS, GDPR/CCPA/COPPA rights, app-store data-safety labels.
WAF watch items: reliability (free-tier no/limited SLA → DB backup + PITR + DR runbook + health checks); cost (budget alerts + documented ceilings); operational excellence (environments strategy + Bicep IaC).
Operational foundations (free-tier friendly) ​
- Environments: dev / test / prod — minimal on free tier (decide in Phase 0).
- IaC: Bicep — all Azure resources as code (
infrastructure/currently empty). - Reliability: DB automated backups + point-in-time restore; documented DR/restore runbook; health checks.
- Cost governance: Azure Cost Management budget alerts + documented free-tier ceilings + Nonprofits upgrade path.
- Security baseline: Defender for Cloud free CSPM, Azure Policy guardrails, Key Vault for all secrets, no secrets in repo.
- Notifications provider: Twilio (SMS, provider-neutral adapter) + SendGrid (email). Decided — ADR 0013 Accepted.
Testing & quality ​
Unit + integration + e2e (follow the platform testing.md standard); CI gates (lint + test + build + Snyk + Dependabot + CodeQL / secret scanning); accessibility (WCAG) pass.
Project management — Azure DevOps ​
ADO Boards is the single source of truth for all work items. Code + PRs stay on GitHub (Heritage-Virginia org); work items live in the "Heritage Community Hub" ADO project (dev.azure.com/hybridcloudsolutions), linked via AB#<id> in commits and PR descriptions.
- GitHub Issues are a public intake + visibility mirror only — never authoritative (GitHub→ADO on issue open; ADO→GitHub on status change).
- Hierarchy: Epic → Feature → User Story → Task. Verb-first titles; required Acceptance Criteria (Epic/Feature/Story ≥ 3, Bug ≥ 2); Priority 1–4 (default 3); standard tag vocabulary; iterations
YYYY-Q<n>-S<m>(2-week sprints). - The
pmo/docs are reference/planning docs; the authoritative items are created in ADO. - See the
pmo/ADO guides for theaz boardsCLI workflow.
Delivery roadmap — priority order ​
This is the agreed delivery order (revised 2026-06-17). Each phase is owned by an ADO Epic; the build work lives there as Features → User Stories → Tasks. The platform is first and most important — get it right — and everything else is a client of it. This roadmap is forward-looking vision; no build work happens from this document.
| # | Phase | ADO Epic | Priority |
|---|---|---|---|
| 0 | Decide ✅ COMPLETE (2026-06-18) | Resolve Platform Open Decisions — ADRs 0001-0024 all Accepted | done |
| 1 | Platform — foundation + all identity, RBAC, member features, signups, family portal | Build Platform — AB#3074 | 2 |
| 2 | Apple (iOS) app | Deliver iOS (Apple) App — AB#3077 | 2 |
| 3 | Sermons & Music Hub — sermons/video/music, storage, web + mobile streaming, offline download | Deliver Sermons and Music Hub — AB#3137 | 3 |
| 4 | Community Calendar & Announcements | Deliver Community Calendar and Announcements — AB#3075 | 3 |
| 5 | Messaging & Notifications | Deliver Messaging and Notifications — AB#3138 | 4 |
| 6 | Google (Android) app | Deliver Android (Google) App — AB#3139 | 4 |
| 7 | Additional features — Small Groups/Ministries, Homeschool, Marketplace, member-posted media (back burner) | Deliver Additional Features — AB#3076 | 4 |
| 7 | Signature features — Pony Express, Ride Share, Sister Community | Deliver Signature Features — AB#3078 | 4 |
Cross-cutting workstreams (also tracked in ADO): planning/docs/repo foundation AB#3150; platform + per-feature ADRs AB#3154 (Closed). See ADR plan.
Decisions locked ​
- Structure: one monorepo, layered via workspaces. → ADR 0001
- Mobile tech: React Native + Expo + EAS Build. → ADR 0002
- End-user auth: Clerk (Apple/Google social login); NO Entra for end users. → ADR 0003
- CI/CD: GitHub Actions (HCH classified as community/open-source repo). → ADR 0004
- Compute: Azure Container Apps (containerized Node.js API). → ADR 0024 (supersedes ADR 0004 Azure Functions choice)
- Database: PostgreSQL on Azure Database for PostgreSQL Flexible Server; portable to AWS RDS / GCP Cloud SQL / Supabase as a connection-string swap. → ADR 0024 (supersedes ADR 0004 Azure SQL choice)
- Web app hosting: Azure Static Web Apps Free — custom domain heritageva.app (HTTPS-only); installable PWA; opens to sign-in/register; no public or marketing site. → ADR 0004
- Infrastructure tenant: HCS Azure tenant / subscription; dedicated resource group
rg-heritageva-prod-<region>; all resources CAF/WAF-named with workload tokenheritageva. DNS managed in Cloudflare (heritageva.app). - Project management: Azure DevOps Boards is the single source of truth.
- Code hosting: code + PRs on GitHub (Heritage-Virginia); ADO Boards for work items, linked via
AB#. - Observability: four-layer model; App Insights + Log Analytics + Azure Monitor + auth-provider logs. → ADR 0005
- RBAC: two planes; six canonical roles (member, family_admin, ministry_leader, content_approver, admin, comms_author); app authorization enforced server-side in the API. → ADR 0006, extended by ADR 0023
- Account model: single
Userstable, nullable email, parent-managed child credentials, FamilyGroups, Announcements (no-reply). → ADR 0007 - SMS provider: Twilio via provider-neutral
SmsProvideradapter. → ADR 0013 - Cloud portability: abstract compute/DB/storage/secrets; provider swap = config change, not rewrite. → ADR 0024
Phase 0 status — COMPLETE ​
All open decisions resolved. ADRs 0001-0024 all Accepted (see docs/internal/adr/). The full decision layer is locked; no ADR remains Proposed. Phase 1 is unblocked.
Platform scope — what "the platform" includes ​
The platform (Epic AB#3074) is the most important deliverable. It is not a thin foundation — it owns everything every surface and feature depends on:
- Infrastructure & DevOps: Bicep IaC; dev/test/prod; GitHub Actions CI/CD; Key Vault; the four-layer observability baseline; cost governance; security baseline.
- Identity & access: Clerk auth (Apple/Google); member signups + minister approval workflow; sessions; server-side RBAC (six roles); the two-plane model.
- Member & family domain: the Account model, Family Groups, the family portal, member profiles, parent-managed child sub-accounts, and the member directory.
- Core shared services every feature uses: the API framework;
api-clientSDK;shared-types; theuidesign system; the notifications transport (channels), audit logging, and the file/media storage primitives the Sermons & Music Hub builds on. - Core web shell (
apps/web): navigation, auth-gated routing, layout, and account/profile screens; installable PWA (web app manifest + service worker + icons); custom domain heritageva.app. The web app is the first usable client and testbed before iOS ships. - Cross-cutting: validation, error handling, rate limiting, OWASP API security baseline, and the data-protection/COPPA foundations.
Calendar, Announcements, Messaging, the Sermons & Music Hub, and the apps are clients of the platform, delivered in their own Epics after it.
Web entry point & portal subdomains — heritageva.app (decided 2026-06-20/2026-06-21) ​
There is no public or marketing site and no interim landing page. Going to heritageva.app opens directly to the sign-in / register screen in apps/web — exactly like opening the iOS or Android app.
- The web app (
apps/web, React + Vite) is the first usable client of the platform API and part of Platform Epic AB#3074. It is an installable PWA: web app manifest (standalone display, icons including maskable,start_url=/), service worker for installability and offline shell. Users install it to desktop or home screen via the browser's Install prompt. - Hosting: Azure Static Web Apps (Free), apex custom domain heritageva.app (HTTPS-only). DNS managed in Cloudflare; CNAME/TXT validation against the live SWA endpoint is performed at deploy time, not before.
- Per-portal subdomains (decided 2026-06-21): each major portal is served on its own subdomain of
heritageva.app(calendar.,listen.,homeschool.,marketplace.,family., etc.). All subdomains are Cloudflare-proxied CNAMEs pointing to the same SWA. Cloudflare Universal SSL (free wildcard*.heritageva.app) terminates TLS; a Cloudflare Origin Rule rewrites the Host header to the SWA default hostname. The SPA readswindow.location.hostnameand mounts the matching portal. See ADR 0028. - Roadmap and changelog are member-facing, delivered inside the app after sign-in (AB#3159). They are not visible without a session.
- The
apps/landing/folder in the repo is a retired placeholder (preserved per the no-delete rule); it is not deployed. ADO Epics AB#3157 and AB#3300 are superseded by this model and should be retired/rescoped in ADO.
ADRs: ADR 0025 (infra naming + hosting), ADR 0029 (managed-identity CI/CD auth), ADR 0026 (heritageva.app domain), ADR 0027 (Claude Design + @hch/ui — web frontend design tooling), and ADR 0028 (per-portal subdomains + Cloudflare Universal SSL) are all Accepted as of 2026-06-21.
Platform foundation UI & view inventory (2026-06-22) ​
Every view in the platform foundation must be (a) designed as a responsive mockup encoding all three web viewports, (b) registered as DesignSync cards in the Claude Design project with the full naming convention, (c) tracked as one ADO User Story per view, and (d) backed by a web route + React page.
~35 canonical views are enumerated in ADR 0033 and specified in detail in docs/internal/design/platform-ui-view-inventory.md.
DesignSync card naming convention: <Screen> — <Variant/Role> · <Platform> · <Viewport>. Example: Members — Detail (Adult) · Web · Phone.
Responsive layout (locked): Phone < 640 px (bottom tab bar); Tablet 640–1023 px (bottom tab bar, max 640 px); Desktop ≥ 1024 px (left sidebar 220 px, max 860 px). Ratifies ADR 0031's open values.
Native apps: same view list; separate design passes (iPhone → iPad → Android) in their own Epics.
Member detail corrected model (ADR 0032 revised): All roles see the same detail screen. Adult: birthday, anniversary, address, phone, email. Kid: birthday only. Admin & minister: same detail + a "Manage" button → separate management screen.
Export member directory to Excel/CSV: ROADMAP item (no code now). ADO story Priority 4 under the Members feature.
ADO items: one Feature (view-inventory) + ~34 User Stories (one per view) under Epic AB#3074. See view inventory design doc for ADO mapping.
ADR plan — platform + per-feature ​
Request (2026-06-17): a detailed ADR for the platform and one ADR per feature, beyond the seven cross-cutting ADRs already accepted.
- Existing: ADRs 0001-0007 (structure, mobile, auth, stack, observability, RBAC, account model) plus ADR 0008 — Platform composition (accepted 2026-06-17, AB#3155).
- Per-feature ADRs 0009-0020 — all Accepted (2026-06-18), in delivery-priority order — 0009 iOS, 0010 Sermons & Music Hub, 0011 Calendar, 0012 Announcements, 0013 Messaging & Notifications, 0014 Android, 0015 Homeschool, 0016 Marketplace, 0017 Small Groups, 0018 Pony Express, 0019 Ride Share, 0020 Sister Community.
- Admin/portal & portability ADRs 0021-0024 — all Accepted (2026-06-18) — 0021 Admin & Ministry Portal, 0022 Family Portal, 0023 Communications authoring & approval, 0024 Cloud portability & provider abstraction.
- No ADR remains Proposed. The full set 0001-0024 is Accepted and the decision layer is locked. Each ADR is tracked as an ADO work item under Epic AB#3154 (closed 2026-06-18).
Tracked in ADO: Epic "Author detailed ADRs (platform and per-feature)" — AB#3154 (closed 2026-06-18; AB#3155 platform ADR 0008, AB#3156 Sermons & Music Hub ADR 0010; all per-feature and portal ADRs completed).
Repository structure — one repo, each feature a solution ​
The single monorepo must be organized so each feature is a vertical-slice "solution" across surfaces (apps/{api,web,mobile}/src/features/<feature>) stitched by packages/shared-types + api-client, with infrastructure/, database/, and the three documentation tiers under docs/.
Status: the skeleton has been reconciled to the decided structure (2026-06-17) — README placeholders only, still no code. The docs/ tree is now split into the two decided buckets (docs/internal/ organized by doc type (design/architecture/build/implementation/operations/overview + adr) + docs/member/); the old loose docs/*.md were sorted into internal/{design,architecture,build,overview}, ADRs moved to docs/internal/adr/, and the old mockups/ HTML was retired to docs/archive/mockups/ (rebuild as React in packages/ui + Storybook is AB#3160). The pnpm + Turborepo config (pnpm-workspace.yaml, turbo.json, .npmrc, package.json) is in place. apps/*/packages/*/infrastructure/* remain skeleton-only until Phase 1 code (AB#3074).
Decided target structure (research-backed):
text
heritage-community-hub/
├── apps/{web, mobile, api}/ # surfaces: web PWA (heritageva.app), RN+Expo mobile (iOS/Android), containerized API
├── packages/
│ ├── shared-types, api-client, shared-utils, shared-config, ui # ui hosts Storybook
│ └── features/<feature>/ # OPTIONAL: vertical-slice packages, only when truly shared web↔mobile
├── infra/ # Bicep IaC
├── docs/
│ ├── internal/{adr,design,architecture,build,implementation,operations,overview}/ # team only (by doc type); NOT public
│ └── member/ # how-to/support/about + roadmap/changelog CONTENT, served IN-APP after sign-in
├── pmo/ # PM/process docs (stays)
│ (no public docs tier — closed community; web entry = apps/web sign-in/register at heritageva.app)
├── pnpm-workspace.yaml turbo.json # if pnpm + Turborepo adoptedRecommended tooling (research-backed defaults): pnpm workspaces (nodeLinker: hoisted for Expo/Metro) + Turborepo for cached, affected-only builds; mockups rebuilt as real React components in packages/ui + Storybook (retire the old mockups/ HTML). Documentation organized by audience (internal team docs vs member in-app docs — no public tier) and, within internal, by document type (design / architecture / build / implementation / operations / overview + adr); ADRs live in docs/internal/adr/.
Sources: Expo Monorepos guide; Feature-Sliced Design monorepo guidance; Turborepo + pnpm 2026 comparisons. Full notes in the research summary captured with this session.
Caveat to weigh: Expo EAS Build historically assumes Yarn; if we adopt pnpm, validate the EAS path early. npm workspaces is the conservative fallback. (See decision 7.)
The current interim skeleton (apps/{api,web,mobile}/src/features, packages/*, infrastructure/{modules,environments}, docs/{adr,member,archive} + tier index) will be reconciled to the decided structure. apps/*/packages/*/infra/* are populated with code only in the Phase-1 Build Platform Epic (AB#3074).
Open questions / decisions to discuss ​
All four prior open questions are RESOLVED (2026-06-17). None block planning; the remaining work is build-time detail tracked in ADO.
- MVP scope — RESOLVED. The MVP is the Platform, delivered fully, first (Epic AB#3074) — then everything else in the locked delivery order. This is not a per-feature MVP cut; the platform is the first usable release and every other Epic is a client of it.
- Roadmap/changelog-from-ADO — RESOLVED. The roadmap and changelog are member-facing, served in-app after sign-in (not a public page). The build vs. buy / sync-cadence mechanism is a build-time implementation detail, decided when AB#3159 is built — not a planning blocker.
- Hosting, tenant, and domain — RESOLVED. Infrastructure runs in the existing HCS Azure tenant / subscription, in a dedicated resource group
rg-heritageva-prod-<region>. The domain heritageva.app is in Cloudflare; DNS is wired at deploy time. There is no interim landing site and no need for a new tenant. - Messaging scope — RESOLVED. "Messaging" = leadership one-way broadcasts (Announcements) + the notifications service (email / SMS / in-app / push). There is no user-to-user chat and nothing beyond that. (Epic AB#3138; Features AB#3145 notifications, AB#3146 one-way messaging.)
Repository structure & tooling — RESOLVED 2026-06-17 (to be recorded in the structure ADR, AB#3161; mockups rebuild AB#3160):
- Build orchestrator: Turborepo (confirmed — free/MIT open source; local caching is free, optional remote cache skippable). ("Builds" = compiling/bundling the code — both locally on a dev machine and in CI/GitHub Actions; Turborepo caches so only changed parts rebuild.)
- Package manager: pnpm (
nodeLinker: hoisted). - EAS Build + pnpm: try pnpm; validate the Expo EAS path early; fall back to npm if it fights.
- Feature code: in-app folders first (
apps/<surface>/src/features/<feature>/); promote a slice topackages/features/*only when it is genuinely shared web↔mobile. - Docs: two buckets — internal repo docs vs member-facing in-app docs (see Documentation model); no public docs tier.
- Mockups:
packages/ui+ Storybook; retire the oldmockups/. Keep the repo root clean.
Resolved 2026-06-18 (owner decisions during ADR review):
- ✅ 6th RBAC role "Communications Author" (
comms_author) — ACCEPTED. Drafts-only, cannot approve/publish. ADR 0023 Accepted; ADR 0006 role table extended to six roles. - ✅ SMS provider — DECIDED: Twilio, accessed through a provider-neutral
SmsProvideradapter (Telnyx named as the cheaper config-only swap). Not Azure Communication Services — ACS is Azure-locked and contradicts the portability posture. ~$17/month accepted as a modest ministry operating cost; security-audit S4 closed. ADR 0013 Accepted. - ✅ Database — DECIDED: Postgres on Azure Database for PostgreSQL Flexible Server now, portable to AWS RDS / GCP Cloud SQL / Supabase / on-prem as a connection-string swap. ADR 0024 Accepted; supersedes the ADR 0004 Azure SQL choice. (ADR 0024 also moves API compute Azure Functions → containerized on Azure Container Apps.)
ADR decision layer CLOSED (2026-06-18): the owner accepted the remaining feature/portal ADRs 0009-0012 and 0014-0022. All ADRs 0001-0024 are now Accepted — the decision layer is locked. No ADR remains Proposed. Next work is the design/architecture layer (Layer 2 of the build-ready pipeline), in delivery order, starting with the platform foundation (AB#3074). Landing-site protection = single shared password (resolved earlier).
ADRs produced (in docs/internal/adr/) ​
All ADRs 0001-0024 are Accepted (2026-06-18). ADRs 0001-0008 were accepted 2026-06-17; the owner accepted per-feature ADRs 0009-0020 and admin/portal & portability ADRs 0021-0024 on 2026-06-18. No ADR remains Proposed. Three decisions carried substantive choices and downstream ripples: ADR 0013 (SMS = Twilio, provider-neutral adapter), ADR 0023 (6th RBAC role comms_author, extends ADR 0006), and ADR 0024 (DB = Postgres; compute = Azure Container Apps — supersedes ADR 0004 compute + database choices). See docs/internal/adr/README.md for the full index and the ADR plan.