Privacy policy

What we can collect is very little. So here it is, in full.

This policy is short because there is very little we can collect. The list below leaves nothing out. The full technical boundary lives in the threat model; to verify with your own hands, go to the public verification page.

Last updated: 2026-09-22

Identity: there are no accounts

默·Tacet has no sign-up form, no email, no name. Your identity is an anonymous number generated randomly on the server, connected to your passphrase by a one-way hash. One passphrase maps to exactly one account; we cannot, and never will, know who is using it.

Your passphrase never exists in any of our systems: what travels online is its hashed value (derived with memory-hard Argon2id since 2026-09-10; earlier accounts upgrade automatically on their next login), and the server stores the result of hashing that value once more. These hashes cannot be reversed into the passphrase by design, so there is no "forgot passphrase" reset service.

What we collect

Encrypted entriesYour journal is encrypted with AES-GCM on your device before it is uploaded. What we store is ciphertext, structurally impossible to read.
Passphrase hashThe passphrase value after two rounds of hashing (login credentials are derived with Argon2id since 2026-09-10; earlier accounts upgrade automatically after one login). Used to verify logins and to check that one passphrase cannot open a second account. The passphrase cannot be recovered from it.
Salt and wrappingThe cryptographic material needed to unwrap your journal key (a random salt and the encrypted key wrapping). Opening them requires your passphrase or your recovery kit.
Recovery kit hashThe recovery kit is stored only as a hash; the kit itself cannot be reconstructed from it.
Quota countersBackup count and byte usage. Used only to enforce the free limit (100 entries), nothing else.
TimestampsAccount creation time and the time each entry is received.
Share linksStored when you create a share: the hash of the share code, an encrypted wrapping with a ciphertext snapshot, and an expiry (free default 7 days). The share code itself exists only at the moment of creation; afterwards it is always a hash on the wire.
IP logsRecorded by the Cloudflare edge for rate limiting and abuse prevention. We never link them to content (which we cannot read anyway).
WishesThe wish text (up to 500 characters) sent from the app. Never linked to your journal, account number, or IP; we record only a signed-in flag at the moment of submission (not which account). A wish cannot be deleted after submission.
Annual-pass interest list (retired)Before the paid plan opened, the introduction page offered an anonymous interest registration: an anonymous sequential number issued in order, plus an optional note (up to 500 characters). The number was pure count feedback, not a spot on a waiting list, and carries no redemption power: the launch price goes to the discount code at checkout on a first-come, first-served basis. The registration entry was retired when the paid plan opened; previously submitted anonymous numbers and notes remain kept long-term (the cannot-be-deleted-after-submission contract is unchanged) and contain no field that can identify you.
Language preferenceThe interface language (zh/en/ja) you explicitly choose on these pages or in the app, kept on your device as a first-party cookie (tacet_lang) and in local storage so it survives across pages and visits. It travels with same-origin requests, but our server never reads, stores, or links it to your journal, account number, or IP.

How long each item is kept

Principle: content exists only to provide the feature you asked for; when you delete, it is erased. Below is the actual retention of every item, with no boilerplate.

Encrypted entries and attachmentsThey stay on the server until you delete them or delete your account; deletion is immediate, with no retention period and no cleanup on our side. The local trash is only a buffer on your device: a deletion first moves the entry to the local trash, which removes it after 30 days; you can restore it at any time until then. The server-side deletion marker takes effect the moment you delete.
Account and login credentialsErased when you delete your account, effective immediately. The only exception: an empty shell account that was never bound and never uploaded a single entry is cleaned up automatically after 48 hours, to prevent anonymous account flooding. Bound accounts are never in this category.
Login sessionsA login credential lasts at most 180 days and expires after 30 days idle. Login credentials created before 2026-09-10 were all expired in one pass on 2026-09-17 (forcing one re-login); when re-logging in, an account that has not yet completed the Argon2id upgrade gets a login credential lasting at most 7 days (on current app builds, whose login sends both hash columns; an old single-column build's request form cannot be told apart by the server, so its credential stays at the usual 180 days; the app updates itself, and the next login after the update uses the 7-day cap); the login itself triggers the upgrade, and after it completes, login credentials return to the usual at-most-180-days. Expired or invalid sessions are removed from the database and leave nothing behind.
Share linksReadable during their lifetime (7 days by default on the free tier); once expired or revoked, the row is removed in the cleanup cycle and reads fail immediately.
Rate-limit countersEach endpoint's rate-limit record maps an IP to a 60-second fixed window; the window starts at the first request and is reset in full afterwards. Not a persistent record.
Wrong-passphrase lockoutThe brute-force lock in the recovery flow (3 consecutive failures per IP) lasts 10 minutes and is cleared the moment it lifts.
Wishes and annual-pass interestNon-deletability is their contract: anonymous notes and interest registrations (including the retired historical entries) are kept long-term for product-improvement evaluation. They contain no field that can identify you.
Edge logsRequest logs are recorded by Cloudflare at the edge and kept only for hours (Cloudflare's public policy); we have not enabled any extended retention.

What we do not collect

Identity dataNo email, name, phone number, address, or payment account exists on our servers.
Journal contentNot a promise not to look: it is structurally unreadable. What the server receives is never text.
Third-party scriptsThis service (including these pages) contains no external JavaScript: no analytics, no ads, no tracking.
Behavioral profilesNo ad targeting, and no data that could be used for it.

How your entries are protected

Keys are generated on your device: the wrapping key is derived from your passphrase with Argon2id (a memory-hard KDF; earlier accounts use PBKDF2 with 600,000 iterations and upgrade automatically on their next login). Entries are encrypted with AES-GCM before they ever leave the device. From start to finish, the server touches only ciphertext.

The precise boundary of "the server cannot read it" (including the conditions under which it holds even against a malicious server) is written in the threat model; you can unwrap and re-verify your encrypted backup with your own hands on the public verification page at any time.

The decryption key stays on your device (the cost of local mode, stated honestly in the threat model). Bound accounts always have "lock on open" enabled: the key is immediately sealed with your PIN, no usable decryption key remains in device storage, and the next open asks for the PIN to unlock. This setting affects only this device and shares the same PIN as login; it cannot be turned off for bound accounts (pure-local mode is not affected). Until an older account completes its one-time PIN setup (guided in the app), a key briefly remains in device storage.

When signing out of this device, you can also choose to erase the journal data on it: the sign-out confirmation in "Devices and sign-ins" inside the app offers an "Also erase the data on this device" option. When checked, entries, image attachments, and the local key are removed from this device immediately; left unchecked (the default), the words stay on this device and belong only to you.

Offline and cache

Tacet can be added to your device's home screen and used as an app. To keep it open even offline, the browser caches the application shell (HTML, CSS, JavaScript) locally. That cache is managed by a Service Worker served from the same origin as the page: it caches the app shell only, and never your journal entries, keys, or passphrases; when online, the app always checks with the server for the latest version, and the cache is only the offline fallback. These pages (including this one) and the share reader never enter any cache. Clearing your browser data removes this cache as well.

The exception when you pay

The yearly plan is billed through Polar. A receipt needs an email; it lives only in Polar, not in our database. After a payment is redeemed, a hash of the payment proof is linked to your anonymous account: "that this identity has paid" becomes linkable. Your journal content remains unreadable. This is the structural exception that comes with paying, written here, not hidden elsewhere.

Payment data goes only to Polar: as merchant of record, Polar alone receives your card number and checkout details; we neither store nor touch them, and refunds, taxes, and payment disputes are carried by Polar under its own policies. Paid status only changes the backup and share quota caps and has zero connection to journal content: the account number is still generated randomly on the server, and entries are encrypted on the device before they ever leave it, paid or not.

Share links

Sharing is available after binding an account (pure local mode has no such option). When you publish an entry as a share link, the server keeps: the hash of the share code, an encrypted wrapping, and a ciphertext snapshot of that entry. A reader needs both the link and your share passphrase to decrypt it locally in the browser; the server can read neither. A share is a snapshot: later edits and deletions do not sync, expiry is tiered by plan (free: 7 days by default; annual pass: up to 90 days), and you can revoke it in the app at any time.

Anyone holding the link can report it: the link alone is enough, no share passphrase required, and we cannot and never use a report to decrypt content. Once a report is verified against the hash, the link immediately loses its read path (the reader shows "taken down after a report"); the report record (hash, optional note) is removed together with the link. We cannot, and never will, read any shared content out of a report.

Deletion

You can delete your account in the app at any time: the account row, all encrypted backups, and login credentials are erased immediately, with no retention period; the share links you created and their report records are removed as well. We also never delete any entry on your behalf; deletion is always your decision and your action.

Service and operator

This service, 默·Tacet (tacet.ink), is operated by an individual based in Taiwan. Service contact: support@tacet.ink; see the terms of service.

Infrastructure

The service runs on Cloudflare (Workers, D1, Pages, R2) with TLS for the entire transfer. Where data is processed is determined by the Cloudflare edge network.

Listed formally, everyone who can touch your data is exactly these two:

CloudflareAll execution and storage for this service: the program runs on Workers, ciphertext and account hashes live in D1, encrypted backup image attachments live in R2, pages are served by Pages, and rate limiting and logs sit at the edge. Your journal content is already encrypted before it reaches Cloudflare; Cloudflare cannot read it either.
PolarThe payment platform for the paid plan (now open: annual-pass checkout and receipts are delivered by Polar): the receipt email lives only in Polar and never enters our database.

The billing email is kept by Polar under its own privacy policy; apart from this, no third party touches your data.

Your rights

The anonymous design is itself the strongest data protection: we cannot know who you are, so we cannot leak, resell, or hand over your journal. Within that anonymity, you still hold these practically exercisable rights:

AccessYour entry count, storage, and plan-level usage aggregates are visible in the app's security settings; your account number is on the same page for reconciliation.
DeletionDelete your account in the app (security settings); the account row and all ciphertext are erased immediately. The flow is described in the "Deletion" section above.
PortabilityMarkdown, JSON, and encrypted backups, three formats, exportable at any time, free forever; encrypted backups can be re-verified offline on the public verification page.
Access and portability requestsprivacy@tacet.ink
What we cannot do Some rights are structurally unenforceable under the anonymous design, stated honestly: with no email and no way to identify you, we cannot correct anything for a specific identity or selectively delete anonymous records such as wishes or annual-pass interest entries (including the retired historical entries); a lost passphrase has no customer-service reset. Every deletion path that can exist lives inside the app.

Legal basis

Our operation and legal entity are in Taiwan, and the governing law is the law of Taiwan (see the terms of service). Taiwan's Personal Data Protection Act is the legal basis for how we process data: we collect only what is necessary to provide the service (data minimization), disclose it honestly and plainly (this page), and provide access and deletion within what is actually possible. Cross-border processing is carried by Cloudflare's global infrastructure; this is the existing reality of every web service, stated as it is, without promises that outrun the facts.

We hold ourselves to the standards of the GDPR: minimal collection, encryption, explicit retention periods, and deletion and portability that actually work. To be precise, the EU's GDPR does not directly apply to an operator based in Taiwan with no EU presence (Taiwan is not on the EU adequacy list), so this page says "held to GDPR standards, jurisdiction stated honestly" rather than "GDPR compliant". That wording is part of the brand: never claim what you do not have.

If a breach ever happens

The worst case is the first line of the threat model: the database holding ciphertext and hashes is stolen, and what leaves is a box of ciphertext. Even then we will state the facts: within a reasonable time after confirming an incident, we will publish on the threat model page and the introduction page what was affected, whether content could be read, and what you can do, and coordinate the investigation with Cloudflare. With no email list we cannot notify anyone individually; please rely on announcements rather than proactive notices. We also ask users to treat passphrase strength as the first line of defense: with a strong passphrase, a stolen box of ciphertext stays sealed.

Boundary statement

默·Tacet is a writing tool. It is not medical care, psychotherapy, or crisis intervention, and it cannot provide any emergency help. If you are in danger or in deep distress, please contact professional help channels in your region.

Changes to this policy

If this policy changes in substance, we will update this page and change the "last updated" date. With no account system and no email list, we cannot notify you proactively; bookmarking this page and returning once in a while is all we can suggest.

Start writing