Spirebound, my free idle wizard-tower game, has an optional cloud save built on Firebase email sign-in and a Firestore database. I wrote it and tested it, and sign-in now works on the live site, but I have not yet watched a verified account save on one device and load on another. Here is what I learned, and what I still have not proven. The game itself is in Spirebound is live, with details on the project page.
Which rules protect the save data?
The database started in production mode, so nothing was open by default. Each player has one save document keyed to their own account ID. As published, the rules let only that owner read or write it, accept only a fixed list of fields, and reject a document of 400,000 bytes or more. Writes also require a verified email. Deleting your own save is exempt, so someone who never verified can still remove their data. Sign-in works on the live site, but I have not yet confirmed these rules against a real save and load.
Why does sync wait for email verification?
Without it, anyone can make a throwaway account with someone else’s address and write data under it. The game blocks sync until the email is confirmed, and after you confirm, it forces a token refresh so the verified flag shows up without signing out. The rules check that flag too, so the gate should hold even if someone skips my interface and calls the service directly. I have not tried that against the live project.
Where should the password policy live?
In the console, not only in the form. I set the minimum at 10 characters and the maximum at 128 in the project settings, because a check in my interface only advises. The form adds stricter checks for common passwords, simple letter-for-number swaps, and passwords built from the email name, but those are a courtesy, not the defence.
How do I stop the page sending data elsewhere?
The page’s content security policy allows connections to exactly three Google hosts, the ones sign-in, token refresh and the database use. The build computes the script hashes and fails if the host list or the hash set drifts. On the live site the page booted and logged no policy violations. In local tests against the built page, a request to a foreign host was blocked. Because the sign-in token lives in browser storage, I also moved the game to its own subdomain instead of the shared arcade address. The rest of my games are on the games index.
What did the tests prove?
The cloud code has 30 tests. To check the tests could fail, I broke the code 11 different ways and confirmed each break was caught. Subagent reviewers, standing in for a human panel, found 12 issues. I fixed them. None of that replaces a live signed-in round trip, so it stays on the open list.
What is still open?
The API key is not restricted to my domain yet. It is meant to be public, but I still need to restrict it. A sign-up error may reveal whether an email already has an account, and I have not confirmed that either way. A token may stay valid for about an hour after a password change. There is no two-factor sign-in, no breached-password check and no email change. Verification emails come from Firebase’s own domain, so they may land in spam, and fixing that needs a custom mail server I have not set up. And a save on one device loaded on another is still untested.
