shard_core/database/tinydb_migration.py is a one-time data migration from the TinyDB era: on startup it checks for shard_core_db.json, and if it is there, reads the JSON tables into Postgres and renames the file to .backup. It arrived with 2980bfb (2026-04-10, "Replace TinyDB with PostgreSQL for all persistent storage") and has done its job.
It cannot fire any more
migrate_tinydb_data() runs from init_database() on every startup, but does nothing unless that JSON file exists — which requires a shard that has never booted a Postgres core. All 11 managed shards are on v29; Postgres landed in April, many core versions ago. There is no shard left for this code to help.
Why remove it rather than leave it lying there
It is not inert in the way dead code usually is — it holds a second copy of knowledge that lives elsewhere, and that copy drifts:
- Four column allowlists (
_IDENTITY_COLUMNS, _INSTALLED_APP_COLUMNS, _TERMINAL_COLUMNS, _PEER_COLUMNS) restate the schema that the migrations own.
_ensure_owner_user is a second implementation of service/user.py::get_or_create_owner.
#221 had to edit both: dropping identities.email meant fixing an INSERT here that named it, and the owner-user creation had to learn about pending_email in two places instead of one. That is the cost being paid repeatedly for a path that can no longer run — and it will be paid again by the next migration that touches identities or users.
Scope
shard_core/database/tinydb_migration.py
- its call in
shard_core/database/database.py::init_database()
tests/test_migration/ (test_migration.py, __init__.py, and the three init_db*.json fixtures)
tests/fixtures/sample_tinydb.json
- the
_DateTimeEncoder import from kv_store if nothing else uses it
Self-hosters: decided, delete it
The fleet check covers managed shards only, so a self-hoster on a pre-April core would in principle still have the JSON file and lose their direct upgrade path.
Decision: ignore that case. There are no known self-hosters on versions that old. Recorded here so the question is not reopened during implementation — if one ever turns up, the answer is an intermediate version, not keeping this module alive.
shard_core/database/tinydb_migration.pyis a one-time data migration from the TinyDB era: on startup it checks forshard_core_db.json, and if it is there, reads the JSON tables into Postgres and renames the file to.backup. It arrived with2980bfb(2026-04-10, "Replace TinyDB with PostgreSQL for all persistent storage") and has done its job.It cannot fire any more
migrate_tinydb_data()runs frominit_database()on every startup, but does nothing unless that JSON file exists — which requires a shard that has never booted a Postgres core. All 11 managed shards are on v29; Postgres landed in April, many core versions ago. There is no shard left for this code to help.Why remove it rather than leave it lying there
It is not inert in the way dead code usually is — it holds a second copy of knowledge that lives elsewhere, and that copy drifts:
_IDENTITY_COLUMNS,_INSTALLED_APP_COLUMNS,_TERMINAL_COLUMNS,_PEER_COLUMNS) restate the schema that the migrations own._ensure_owner_useris a second implementation ofservice/user.py::get_or_create_owner.#221 had to edit both: dropping
identities.emailmeant fixing anINSERThere that named it, and the owner-user creation had to learn aboutpending_emailin two places instead of one. That is the cost being paid repeatedly for a path that can no longer run — and it will be paid again by the next migration that touches identities or users.Scope
shard_core/database/tinydb_migration.pyshard_core/database/database.py::init_database()tests/test_migration/(test_migration.py,__init__.py, and the threeinit_db*.jsonfixtures)tests/fixtures/sample_tinydb.json_DateTimeEncoderimport fromkv_storeif nothing else uses itSelf-hosters: decided, delete it
The fleet check covers managed shards only, so a self-hoster on a pre-April core would in principle still have the JSON file and lose their direct upgrade path.
Decision: ignore that case. There are no known self-hosters on versions that old. Recorded here so the question is not reopened during implementation — if one ever turns up, the answer is an intermediate version, not keeping this module alive.