Information Security Program
Last updated: April 26, 2026 Version: 3
This document is the written Information Security Program for Kettle Muscle, maintained as required under:
- The Children's Online Privacy Protection Rule, as amended by the 2025 Final Rule (compliance deadline 22 April 2026), 16 C.F.R. §312.8 and §312.10 (written information security program);
- GDPR Article 32 and the parallel UK GDPR (appropriate technical and organisational measures);
- California CPRA §1798.100(e) (reasonable security procedures);
- PIPEDA Principle 4.7 (safeguards);
- Quebec Law 25, ss. 10 and 63.10 (security measures and PIA);
- LGPD Articles 46–49 (security and good practices);
- DPDPA Section 8(5) (reasonable security safeguards).
It is referenced in §9 of our Privacy Policy.
1. Scope and ownership
Program owner. Pulkit Kakkar, acting as both the data controller and the security owner of the service, is responsible for this program.
Scope. All personal information collected, processed, or stored in connection with the Kettle Muscle mobile application and associated Firebase backend.
Risk posture. Kettle Muscle is a solo-developer, pre-revenue, consumer fitness app. Security controls are sized to the scale of the operation while meeting the legal minimums listed above.
2. Risk assessment
Annually, and whenever a material change occurs, we identify and evaluate reasonably foreseeable internal and external risks to the confidentiality, security, and integrity of personal information. The current risk register includes:
| Risk | Likelihood | Impact | Primary mitigations |
|---|---|---|---|
| Stolen or lost device | Medium | Medium (user's own data; other users unaffected) | Per-user isolation at the backend; on-device encryption by iOS; Secure Enclave for BYO-AI keys |
| Compromised Firebase project credential | Low | High | MFA on the Firebase console owner account; least-privilege service accounts; App Check; quarterly credential review |
| Malicious actor impersonating another user | Medium | High | Firebase Auth + App Check + Firestore rules enforce per-UID isolation; every write is attested by App Check |
| Data exfiltration via compromised SDK / supply chain | Low | High | Pinned dependency versions; lockfile committed; only vetted third parties (Firebase ecosystem); no ad SDK |
| Cross-border transfer risk | N/A (mitigation, not a risk itself) | High (regulatory) | SCCs / UK IDTA / LGPD contractual safeguards; documented Quebec PIA |
| Insider risk | Low | Low | Pulkit is the sole admin; no shared credentials; no employees |
| Under-age enrolment | Medium | Medium (COPPA liability) | Client-enforced age gate before any PII collection; server-side ageVerified field |
| AI provider leakage of prompt data | Medium (provider-side) | Medium | BYOK architecture — keys and prompts go direct from device to provider; we see nothing |
| Account-deletion failure mid-cascade | Low | Medium | "Deleting" sentinel written before cascade; resumable from crash |
3. Technical controls
3.1 Encryption
- In transit. All communications between the client and Firebase services use TLS 1.2 or higher. Third-party sign-in (Apple, Google) uses OAuth over TLS.
- At rest. Firebase Firestore and Cloud Functions encrypt data at rest by default using Google-managed keys.
- Device storage. SQLite data on the user's device relies on iOS hardware encryption tied to the device passcode. BYO-AI API keys are stored in the iOS Keychain via
expo-secure-storewith theWHEN_UNLOCKEDaccess flag. Keychain items are encrypted with a key protected by the Secure Enclave on devices that support it; they are not stored within the Enclave itself. - Secrets. No API keys, tokens, or service-account credentials are committed to the repository. Environment variables used for the public Firebase configuration are non-secret per Firebase's security model; sensitive server-side keys live only in Google Secret Manager and are injected into Cloud Functions at deploy time.
3.2 Authentication and authorisation
- Users authenticate via Firebase Authentication using Sign in with Apple, Sign in with Google, or email + password. Passwords are enforced to NIST SP 800-63B Rev 4: minimum fifteen characters, no arbitrary composition rules, checked against the Have I Been Pwned breach corpus via k-anonymity before acceptance.
- Session security relies on Firebase's short-lived ID tokens and long-lived refresh tokens, both stored by Firebase SDK in the platform keychain.
- Firestore rules enforce per-user isolation: reads and writes to
/users/{uid}/...paths requirerequest.auth.uid == uidand a valid App Check token (request.app_check.token != null). Schema is validated server-side; unknown fields are rejected. - Firebase App Check (DeviceCheck on iOS, Play Integrity on Android) attests that requests originate from a genuine app install, blocking most scripted abuse.
- Administrative access to the Firebase console and the domain registrar is protected with a hardware security key and a second factor.
3.3 Data minimisation and segregation
- The app collects only the data listed in §2 of the Privacy Policy.
- Personally identifiable data and fitness data are stored in per-user document trees, never in shared collections.
- Analytics and crash-reporting SDKs are configured to strip personal identifiers before transmission; event parameters matching names like
email,name,phone,dob,addressare actively stripped in code.
3.4 Secure software development
- Source control. All code lives in a private Git repository. Protected main branch; commits include author attribution.
- Dependency hygiene. Lockfile committed; third-party libraries are pinned to tested versions; critical libraries (Firebase SDK, Expo, React Native) are upgraded on Apple-recommended cadence.
- Automated checks. CI runs type-checking, unit tests, and policy-enforcement scripts (for example,
scripts/lint-no-bare-deletes.shenforces that every destructive query is scoped byuser_id;scripts/lint-no-placeholder-contacts.shblocks ship with placeholder contacts in legal docs). - Secure defaults. Offline-first architecture avoids unnecessary network dependencies. Foreign-key constraints and transaction boundaries are enforced at the database level.
3.5 Logging and monitoring
- Firebase provides authentication logs, rule-violation logs, and Cloud Functions logs, retained per Firebase's defaults.
- Client-side crash reports (Crashlytics) record stack traces without user identifiers.
- Logs that could contain personal information are reviewed only where necessary for investigating an incident.
- Firebase logs are retained in accordance with Firebase's defaults (for example, 30 days for Cloud Functions logs, and 7–30 days for Firestore audit logs depending on tier).
3.6 Subscription billing webhook security
The RevenueCat webhook (functions/src/revenuecat-webhook.ts) is the only inbound endpoint that writes subscription entitlement state into Firestore. It is hardened with multiple independent layers:
- Bearer-token authentication. The webhook accepts only requests carrying a valid
Authorization: Bearer <RC_WEBHOOK_SECRET>header. The secret is stored in Google Secret Manager viadefineSecret(NOT the deprecatedfunctions.config()mechanism) and is rotated on a quarterly cadence and immediately on any suspected leak. Bearer comparison is constant-time (crypto.timingSafeEqual) to defeat timing attacks. - Timestamp tolerance. Each event payload carries
event.event_timestamp_ms. Requests are rejected if the timestamp is more than 10 minutes skewed from server time, narrowing the window for replay of stale captured headers. - Environment-scoped idempotency. The dedupe key is
rc_events/{environment}_{event.id}whereenvironmentis one ofSANDBOXorPRODUCTIONfrom the RevenueCat payload. Sandbox events arriving on the production webhook URL are rejected with HTTP 400; production events on the sandbox webhook are likewise rejected. The dedupe document is created withFirestore.create()(which throws on existing) AFTER the entitlement write succeeds — biasing toward duplicate processing rather than missed processing under partial-failure conditions. - Atomic operations on multi-account events. TRANSFER events (Family Sharing reassignments) execute inside a Firestore
runTransactionso the revoke from the sourceappUserIDand the grant to the targetappUserIDare applied or rolled back together; partial-state TRANSFERS cannot persist. - No public IP allowlist. RevenueCat does not publish a stable egress IP range; bearer + timestamp + environment dedupe are the actual hardening.
- Log sanitisation. The handler never logs the
Authorizationheader; a Cloud Logging exclusion alerts if the regexBearer [A-Za-z0-9+/]{20,}ever appears in any log stream. SentrybeforeSendstrips authorization, cookies, and any header containingsecret/token/key. - Rate-limit and abuse bound. The Function is deployed with
maxInstances: 10to bound abuse-driven cost. - GDPR Art. 17 deletion path. The companion
wipeRevenueCatUsercallable (functions/src/wipe-revenuecat-user.ts) issuesDELETE /v1/subscribers/{appUserID}to RevenueCat using a separateRC_API_KEY(REST Secret API key, NOT the public SDK key). It is invoked from the account-deletion cascade and never throws; failures are queued inrc_deletion_retries/{uid}for a scheduled retry, so a RevenueCat outage cannot strand a half-deleted user. - Client write blocking. Firestore rules block client writes to
users/{uid}.entitlements,entitlementsUpdatedAt,cacheInvalidationAt, andlastBillingEventIdviarequest.resource.data.diff(resource.data).affectedKeys().hasAny(['entitlements', 'entitlementsUpdatedAt', 'cacheInvalidationAt', 'lastBillingEventId']). Only the Admin SDK from the webhook can write these fields. - Kill-switch audit trail. Every change to
config/billing(the universal-grant override) triggersfunctions/src/config-billing-audit.ts, which posts to a Slack webhook and appends a forensic record toconfig/billing_audit/{ts}with previous + next state. The Slack call is wrapped in a 5-secondAbortControllerso a Slack outage does not backpressure the audit Function.
These controls are tested in __tests__/firebase/revenuecat-webhook.test.ts and __tests__/firebase/wipe-revenuecat-user.test.ts.
4. Organisational controls
- Single operator. Pulkit Kakkar is the sole administrator. There is no shared credential, no off-boarding problem at current scale, and no unvetted third-party engineer with production access.
- Principle of least privilege. Service-account keys are issued with the narrowest roles sufficient for the task; no "owner" or "editor" role on day-to-day deployment tooling.
- Third-party review. Before adopting a new processor (a new SDK, a new Firebase product, an advertising or analytics vendor), we review the processor's privacy and security posture and update this program, the Retention Policy, and the Privacy Policy.
- Training. As a solo operator, Pulkit maintains familiarity with current OWASP Mobile Top 10, App Store Review Guidelines (especially 5.1.x on privacy), and the regulatory changes in §Preamble. Training is ongoing and self-directed.
5. Incident response
If we become aware of a suspected or actual compromise of personal information, we follow this procedure:
- Contain. Revoke compromised credentials, invalidate sessions, disable affected features.
- Assess. Determine scope: which users, which data categories, which jurisdictions.
- Record. Log the incident, response, timeline, and decisions.
- Notify regulators where required:
- GDPR / UK GDPR — within 72 hours of becoming aware, to the lead supervisory authority, if the breach is likely to result in a risk to rights and freedoms (Art. 33).
- LGPD — within a reasonable timeframe, to the ANPD (Art. 48).
- DPDPA — to the Data Protection Board of India once operational.
- PIPEDA — without delay, to the Office of the Privacy Commissioner of Canada, if the breach creates a real risk of significant harm.
- US state laws — per the specific state's timeline (e.g., California Civil Code §1798.82 "in the most expedient time possible").
- Notify affected users without undue delay where required by the applicable law, and always when the breach is likely to result in a high risk to their rights.
- Remediate. Close the root cause; update this program, and the Retention Policy or Privacy Policy where relevant.
Breach register. All security incidents involving personal information, regardless of whether they meet a notification threshold, are logged in our internal breach register with enough detail to permit regulator review. The register is retained for at least 24 months, as required by PIPEDA §10.3 and the Breach of Security Safeguards Regulations (SOR/2018-64), and for any longer period required by other applicable law.
6. Data subject request handling
Requests to access, correct, delete, export, or otherwise exercise data-subject rights under any of the laws listed in the Preamble are handled as follows:
- Request arrives at contact@kettlemuscle.com.
- Verify the requester is the account holder (typically by confirming an action from within the authenticated app or by matching the email).
- Fulfil within the applicable deadline — in every case within 30 days of verification, extendable by 30 additional days where reasonably necessary (or 45 days under WMHMDA) with notice to the requester.
- Log the request, response, and outcome in the compliance ledger; retained per §2 of the Retention Policy.
Users may exercise most of these rights directly from the app under Profile → Privacy:
- Download my data → generates a JSON export via a Cloud Function; rate-limited to one export per 24 hours.
- Delete account → triggers the cascade described in §3 of the Retention Policy.
7. Cross-border transfer safeguards
Firebase infrastructure hosts data in the United States. For each region from which users access the service, we document the corresponding transfer mechanism in §7 of the Privacy Policy.
8. Written compliance artifacts we maintain
We maintain the following internal documents, available in summary form to a user or regulator on request:
- Record of Processing Activities (ROPA) — GDPR Art. 30. Required regardless of headcount because we process special-category data (GDPR Art. 9).
- Data Protection Impact Assessment (DPIA) — GDPR Art. 35. Required because we process fitness and body data (special-category), which meets the EDPB's nine-factor DPIA trigger.
- Legitimate Interests Assessment (LIA) — GDPR Art. 6(1)(f). Documents the three-part test (purpose / necessity / balancing) for the stability-telemetry processing described in §2.3 of the Privacy Policy.
- Quebec Privacy Impact Assessment (PIA) — Law 25 s.3.3 / s.63.5. Required for any transfer of Quebec-resident personal information outside Quebec; a summary is available to users on request.
- Breach register — PIPEDA §10.3, retained for at least 24 months; see §5 above.
- Consent records — timestamp + version + surface of each consent given, retained per the Data Retention Policy.
9. Changes to this program
Material changes bump the version number at the top of this document. Routine wording updates update the date. The program is reviewed at least annually, and whenever the risk register materially changes.
10. Contact
Security-related enquiries, including vulnerability reports, go to contact@kettlemuscle.com with the subject line "Security". We do not yet operate a formal bug-bounty programme; we will acknowledge legitimate reports and not pursue good-faith security researchers who follow responsible-disclosure practice.
End of Information Security Program.