TechIDaily Journal
The TechIDaily Privacy Manifesto: On-Device by Default
TechIDaily builds seven apps across health, focus, and entertainment. Every one of them keeps user data on the device. Here is the five-pillar manifesto, the audit process, and the architectural patterns we use to honor it.
The TechIDaily Privacy Manifesto: Why Every App We Ship Stays On Your Device
*The five pillars, the per-app audit process, and the architectural patterns that every TechIDaily app ships with.*
TechIDaily ships seven iOS apps. They cover health, focus, entertainment, and education. They run on hundreds of thousands of devices across North America and Europe. Every one of them keeps user data on the device. None of them ship training samples, behavioral fingerprints, or usage analytics to a server. This is not a marketing line. It is a structural property of how we build, and it is the subject of this post.
1. Why Privacy Is Structural, Not a Marketing Line
Most apps claim to be privacy-respecting. The claim is usually true in spirit and usually false in detail. A privacy-respecting app that ships a crash report with a stack trace, a unique device identifier, and a session replay ships a behavioral fingerprint. The user does not see the identifier or the replay, but the server sees them, and the server can correlate them across sessions.
We chose to make privacy structural because structural choices are the only ones that survive engineering turnover. A privacy policy written in a wiki decays within six months. A privacy architecture written in code survives for the lifetime of the codebase. Every TechIDaily app ships with a PrivacyGate module that enforces the architecture at build time, and the module is reviewed in every code review.
2. Pillar 1: On-Device Inference by Default
Every inference that can run on the device must run on the device. The cost of an on-device inference is bounded by the device's hardware. The cost of a server-side inference is unbounded, because the server cost grows with the user base and the user's data is exposed to the server's operators.
The practical rule is: if the inference runs in under 100 ms on the device, it runs on the device. Anything slower than 100 ms on the device is a candidate for server-side, but only if the user's data has been irreversibly anonymized before the inference. We have not yet shipped a server-side inference, and the rule has not been triggered.
3. Pillar 2: Minimal Data Collection
Every piece of data the app collects must have a user-visible purpose. The purpose must be displayed in the app's first-run experience, and the user must be able to opt out of the collection without losing access to the app's core features.
The implementation is a DataPurpose enum that tags every data field with the purpose it serves. A linter in the build pipeline rejects any data field that is not tagged, and a runtime check rejects any data field whose purpose the user has opted out of. The linter runs in CI and the runtime check runs in production.
4. Pillar 3: Transparent Algorithms
Every algorithm that affects the user must be documented in the app. The documentation lives in the app's settings, under "How this app works", and it covers every adaptive system, every recommendation engine, and every personalization model.
The documentation is plain-language, not technical. We do not expose the model weights, the training data, or the inference budget. We do explain what the algorithm does, what data it uses, and what the user can do to influence it. The documentation is reviewed by the editorial team, not just the engineering team, because the audience is the user, not the engineer.
5. Pillar 4: User Control Over Export and Delete
Every piece of user data the app stores must be exportable and deletable. Export produces a JSON file in the app's documents directory, and the file is in a documented schema. Delete produces an empty database, and the deletion is irreversible.
The export and delete operations are wired into the app's settings, and they are tested in every release cycle. A release that breaks export or delete is a release that does not ship. The test is a single XCTest case that runs against every TechIDaily app, and the test must pass before the build can be uploaded to App Store Connect.
6. Pillar 5: No Third-Party Trackers, Ever
No third-party SDK. No analytics. No crash reporter that ships user data. No advertising network. No attribution SDK. No remote config that ships user data. The list is exhaustive by design, and the build pipeline rejects any third-party SDK that is added to the project.
The rule has cost us partnerships. Three potential partners wanted to integrate their analytics SDK, and we declined all three. The rule has also saved us from three potential breaches. The trade-off is intentional.
7. The Per-App Audit Process
Every TechIDaily app goes through a PrivacyGate audit before it ships. The audit is a checklist of 24 items, and every item must be confirmed by the app's lead engineer and the privacy lead. The audit covers the data the app collects, the inferences it runs, the network calls it makes, the third-party SDKs it includes, and the user-facing documentation it ships.
The audit produces a PrivacyGate.score between 0 and 100. The minimum score to ship is 85. The score is published in the app's settings, alongside the documentation, and the user can see it. A score below 85 blocks the release in CI.
8. Architecture Patterns: How We Implement It
The five pillars map to a set of Swift patterns that every TechIDaily app shares. The patterns are extracted into a private Swift package called PrivacyCore, and the package is the first dependency every TechIDaily app adds to its project.
The patterns include:
LocalOnlyStorage: a wrapper around SQLite that refuses to write to any location outside the app sandbox.PurposeTaggedField<T>: a property wrapper that tags every field with aDataPurposeand refuses to read or write the field if the user has opted out.AuditChecklist: a runtime that runs the 24-item PrivacyGate checklist and produces the score.ExportSchema: a JSON schema definition that the export operation uses to serialize the user's data.DeleteOperation: a runtime that deletes every user data store in the app and verifies the deletion is complete.
The patterns are not optional. They are enforced by the build pipeline. An app that tries to skip a pattern fails to build.
9. Code: The PrivacyGate Audit Function
The audit function runs in production at app launch. It walks the 24-item checklist, reports any failures to the app's log, and produces the score that the user sees.
struct PrivacyGate {
static func audit() -> Int {
var score = 100
if !verifyLocalOnlyStorage() { score -= 10 }
if !verifyPurposeTaggedFields() { score -= 10 }
if !verifyExportSchema() { score -= 10 }
if !verifyDeleteOperation() { score -= 10 }
if !verifyNoThirdPartyTrackers() { score -= 20 }
if !verifyNetworkCallsAreMinimal() { score -= 10 }
if !verifyUserDocumentation() { score -= 5 }
if !verifyOnDeviceInference() { score -= 10 }
return max(0, score)
}
}The score is displayed in the app's settings. A score of 85 or higher is shown in green. A score below 85 is shown in red, and the app refuses to ship to the App Store.
10. Code: Local-Only Storage Wrapper
The LocalOnlyStorage wrapper is a thin layer over SQLite that refuses to write to any path outside the app sandbox. It also refuses to write to any path that is backed by iCloud, because iCloud backups are an out-of-device destination that the user has not explicitly opted into for that specific data.
final class LocalOnlyStorage {
private let db: Connection
init() throws {
let url = try FileManager.default.url(
for: .applicationSupportDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
).appendingPathComponent("local.sqlite")
let isICloud = url.path.contains("Mobile Documents")
precondition(!isICloud, "LocalOnlyStorage refuses iCloud-backed paths")
db = try Connection(url.path)
}
}The precondition runs in production. A path that is silently backed by iCloud would crash the app at launch, which is the correct behavior for a privacy violation.
11. What We Refused to Ship
Three examples from the last eighteen months.
Personalization server. A potential partner wanted to ship a server-side personalization model that would have required sending every user's behavioral fingerprint to their backend. We declined the partnership.
Crash reporter with stack traces. A third-party crash reporter wanted to ship full stack traces with the user's device identifier. We replaced it with a custom crash reporter that ships anonymized stack traces and no device identifier.
Attribution SDK for marketing. A marketing partner wanted to integrate an attribution SDK that would have shipped the user's device identifier to their servers for ad attribution. We declined the integration.
12. What's Next
Three things are in active development. First, a public Privacy Scorecard that lets any user audit any TechIDaily app's privacy posture from a single dashboard. Second, a third-party PrivacyGate audit that lets independent researchers verify our claims. Third, an open-source release of the PrivacyCore package, under a license that requires any forks to ship their own PrivacyGate audit.
If any of this resonates with how you think about software privacy, the seven TechIDaily apps are all available on the App Store. Each one ships with its PrivacyGate score in the settings, and each one's PrivacyGate audit is reproducible from the source code.
*This manifesto describes the privacy architecture of TechIDaily's seven shipping apps. It does not describe the privacy posture of third-party software that may integrate with our apps. Users who integrate TechIDaily apps with other software should review the other software's privacy practices independently.*