Repository navigation
Feedback Technical Architecture
neil warner edited this page Oct 12, 2026
·
2 revisions
Target Audience: Core Engineers & System Architects
Related Non-Technical Guide: User Feedback & Private Prayer Triage
Private Triage Repository: njwandroid/selahfeedback
graph TD
A[Client UI EmojiFeedbackDialog] -->|User Tap / BetterFeedback| B(FeedbackService Dart)
B -->|Upload PNG Asset| C[GitHub Contents API PUT<br/>/contents/feedback_assets/fileName.png]
C -->|Commit SHA & URL| B
B -->|Create Issue POST| D[GitHub Issues API<br/>/repos/njwandroid/selahfeedback/issues]
B -->|Firestore REST POST| E[(Cloud Firestore user_feedback)]
B -->|Doorbell.io REST POST| F[Doorbell.io Webhook / Email]
G[Firebase Remote Config] -->|github_feedback_token| B
H[api.ipify.org] -->|public_ip discovery| B
-
Zero Plaintext Secrets in Repository:
- The GitHub Personal Access Token is stored in Firebase Remote Config under key
github_feedback_token. - On app startup,
RemoteConfigServicefetches and activates the parameter dynamically. - The token resides in volatile memory and encrypted cache โ never in git history or client source files.
- The GitHub Personal Access Token is stored in Firebase Remote Config under key
-
Automated Screenshot Asset Upload:
-
Endpoint:
PUT https://api.github.com/repos/njwandroid/selahfeedback/contents/feedback_assets/{fileName} -
Headers:
Authorization: Bearer <github_feedback_token>Accept: application/vnd.github.v3+jsonUser-Agent: Selah-Scripture-Audio-Meditation/0.3.1
-
Payload:
{ "message": "chore(feedback): upload screenshot asset {fileName}", "content": "<base64_encoded_png_bytes>", "branch": "main" } -
Markdown Image Embedding:
The issue body embeds the uploaded asset using session-authenticated GitHub blob links:
Note: We intentionally avoid
 ๐ [View Screenshot in Repository](https://github.com/njwandroid/selahfeedback/blob/main/feedback_assets/{fileName})
raw.githubusercontent.comURLs because GitHub private repositories return HTTP 404 for unauthenticated raw requests.
-
Endpoint:
-
Client IP & Device Context:
-
Discovery Service:
AppDeviceInfoService.getClientContext() -
Public IP: Discovered via
https://api.ipify.org?format=jsonwith a 2-second connection timeout, falling back gracefully to'unavailable'(or'127.0.0.1'during unit test fixtures). -
Hardware Profiling: Attaches
platform,app_version,device_model, andnpsto every reflection note.
-
Discovery Service:
-
Multi-Channel Fanout & Fallbacks:
-
Firestore REST: Written to
projects/selahwordapp/databases/(default)/documents/user_feedbackfor analytics querying. -
Doorbell.io: Gracefully bypassed if
DOORBELL_APP_IDis not supplied in the environment. -
GitHub Issues: Primary triage channel with automatic labeling (
user-feedback,happy/neutral/sad,screenshot,platform:web/platform:ios/platform:android).
-
Firestore REST: Written to
-
Unit Test:
test/unit/github_feedback_test.dart- Asserts HTTP PUT screenshot upload payload with base64 validation.
- Asserts issue creation payload, label arrays, and IP telemetry injection.
- Asserts markdown embedding format.
-
Coverage: 87/87 tests passing green (100%);
flutter analyze: 0 warnings.
Overview
- ๐ Welcome Home
- ๐ Onboarding & Contributor Guide
- ๐ Soft Launch Checklist
- ๐ Review Guide Tomorrow Night
๐ฟ Product & Ministry
- Product & Ministry Home
- ๐ Sharing & Invitation Kit
- User Feedback & Prayer Triage
- Data-Driven Ministry Insights
โ๏ธ Engineering & Architecture
- Engineering Home
- Audio Platform Matrix: Web vs PWA vs APK
- Firebase Hosting Previews
- Feedback Technical Architecture
- Firebase Analytics & Telemetry
- Releases & Roadmap
- Acoustic Calibration Guide
- WhisperX Alignment ADR
๐ Quick Links